Как я могу отправить строку через NFC во время закрепления экрана?
Я пытаюсь отправить String
через NFC, пока мое приложение использует закрепление экрана. Не работает: передача не происходит; но если я отключу экран закрепления передачи String
работает.
Я могу немного отключить закрепление экрана, а затем выполнить передачу, но это угроза безопасности.
Как я могу это сделать?
Вот весь код, если вы хотите попробовать. Все, что вам нужно сделать, это включить ручное закрепление экрана в настройках вашего приложения (так что это меньше кода и все равно дает тот же результат). Я проверил это на двух Nexus 7, работающих под управлением Android 5.0.
Вам не нужно читать весь этот код, этот вопрос, вероятно, может быть решен, если вы знаете что-то, что я могу добавить в мой манифест, который позволил бы NFC при закреплении экрана.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidnfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.NFC"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidnfc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback
{
TextView textInfo;
EditText textOut;
NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInfo = (TextView)findViewById(R.id.info);
textOut = (EditText)findViewById(R.id.textout);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.setNdefPushMessageCallback(this, this);
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
@Override
protected void onResume()
{
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
{
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
textInfo.setText(inMsg);
}
}
@Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
}
@Override
public void onNdefPushComplete(NfcEvent event) {
final String eventString = "onNdefPushComplete\n" + event.toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), eventString, Toast.LENGTH_LONG).show();
}
});
}
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
String stringOut = textOut.getText().toString();
byte[] bytesOut = stringOut.getBytes();
NdefRecord ndefRecordOut = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
bytesOut);
NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
return ndefMessageout;
}
}
расположение
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidnfc.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textStyle="bold" />
<EditText
android:id="@+id/textout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
1 ответ
Я не уверен, что это действительно отвечает на ваш вопрос, но я хотел бы обобщить мои выводы:
При испытании вашего примера на Android 5.0.1 (LRX22C на Nexus 4) принимающая сторона автоматически откручивает экран при получении сообщения NDEF и (повторно) начинает действие. Таким образом, кажется, что фильтр намерений, который зарегистрирован в манифесте, получает приоритет над (ручным?) Закреплением экрана.
Я знаю, что это не совсем соответствует опыту, описанному в вопросе. Мне интересно, связано ли это с другой версией Android (5.0 против 5.0.1) или из-за использования ручного закрепления экрана вместо программного закрепления экрана...
В моей тестовой настройке я смог решить проблему (т.е. предотвратить автоматическое открепление активности) с помощью системы диспетчеризации переднего плана, чтобы зарегистрировать активность для получения сообщения NDEF:
В вашем onResume()
метод создает отложенное намерение, подобное этому, и включает отправку переднего плана:
PendingIntent pi = this.createPendingResult(0x00A, new Intent(), 0);
nfcAdapter.enableForegroundDispatch(this, pi, null, null);
После этого вы будете получать уведомления о найденных тегах через действия onActivityResult()
метод:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 0x00A:
onNewIntent(data);
break;
}
}
Кроме того, вы должны отключить отправку переднего плана в вашем onPause()
метод:
nfcAdapter.disableForegroundDispatch(this);