Как я могу отправить строку через 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>

person J_Strauton    schedule 09.02.2015    source источник
comment
Вы пробовали на своем примере? С какой версией Android и устройством вы тестировали его? Я только что протестировал Nexus 4 под управлением Android 5.0.1 (LRX22C), и ваш пример работает нормально, даже когда экран закреплен.   -  person Michael Roland    schedule 20.02.2015
comment
Я попробовал это с двумя Nexus 7 под управлением Android 5. Оба ваших устройства должны иметь закрепленный экран, чтобы столкнуться с проблемами.   -  person J_Strauton    schedule 21.02.2015
comment
На Android 5.0.1 ваш пример все еще работает: на принимающем устройстве экран автоматически открепляется и запускается новый экземпляр действия. Может ли это быть связано с ручным закреплением, а не с программным кодом?   -  person Michael Roland    schedule 23.02.2015
comment
Я тестировал ручное закрепление и закрепление кода - ничего не работает.   -  person J_Strauton    schedule 04.03.2015


Ответы (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);
person Michael Roland    schedule 26.02.2015