2016-10-04 2 views
1

Я прочитал документацию несколько раз и посмотрел пример кода, но я не могу понять, что я делаю неправильно.Почему Android Beam/NFC не получает записи, которые я отправляю?

Всякий раз, когда я складываю свои два устройства, я вижу экран Beam и нажимаю его, но ничего не посылает, и ни один из моих точек останова не попадает. Вот мой код, пожалуйста, помогите мне выяснить, почему ничто не отправляется на другое устройство. В редакторе я вижу, что все в BeamFileActivity запущено, я просто никогда не вижу, чтобы какие-либо точки останова в MainActivity получили доступ к принимающему устройству. Что я делаю не так?

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.myapp"> 
    <uses-permission android:name="android.permission.NFC" /> 
    <uses-feature android:name="android.hardware.nfc" android:required="true" /> 
    <application 
    android:name=".MainActivity" 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme"> 
     <meta-data 
      android:name="QUERY_LOG" 
      android:value="false" /> 
     <meta-data 
      android:name="DOMAIN_PACKAGE_NAME" 
      android:value="com.myapp.domain" /> 

     <activity 
      android:name=".MainActivity" 
      android:exported="true" 
      android:label="@string/app_name" 
      android:windowSoftInputMode="adjustResize"> 

      <intent-filter> 
       <action android:name="com.google.android.apps.drive.DRIVE_OPEN" /> 
       <action android:name="com.google.android.apps.drive.DRIVE_SAVE" /> 
       <data android:mimeType="application/vnd.google-apps.drive-sdk.111111111" /> 
       <data android:mimeType="application/vnd.google-apps.spreadsheet" /> 
       <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:scheme="vnd.android.nfc" 
        android:host="ext" 
        android:pathPrefix="/com.myapp:SpreadsheetDom"/> 
      </intent-filter> 
     </activity> 
     <activity 
      android:name=".dialog.BeamFileActivity" 
      android:label="@string/title_activity_beam_file" 
      android:parentActivityName=".MainActivity" 
      android:theme="@style/AppTheme.NoActionBar"> 
      <meta-data 
       android:name="android.support.PARENT_ACTIVITY" 
       android:value="com.myapp.MainActivity" /> 
     </activity> 
    </application> 

MainActivity: Это то, что получит намерение Beam, я только в том числе методы, которые я думаю, актуальны.

@Override 
protected void onResume() { 

    super.onResume(); 

    //I removed some code that reloads my application, didn't seem relevant 

    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) { 
     processIntent(getIntent()); 
    } 
} 

/** 
* Parses the NDEF Message from the intent and stores the collection 
*/ 
void processIntent(Intent intent) { 

    Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); 
    // only one message expected during the beam 
    NdefMessage msg = (NdefMessage) rawMsgs[0]; 

    //This is the data I'm beaming, It has a method that converts its data to a byte array, and a method, fromBytes() that converts bytes into the object 
    SpreadsheetDom dom = new SpreadsheetDom(); 
    try { 

     for(int i = 0; i < msg.getRecords().length; i++) { 

      if(SpreadsheetDom.class.getName().equalsIgnoreCase(new String(msg.getRecords()[i].getType()))) { 

       dom.fromBytes(msg.getRecords()[i].getPayload()); 
       //removed some code that saves and displays changes 
      } 
     } 
    } catch(IOException | ClassNotFoundException e) { 

    } 
} 

@Override 
public void onNewIntent(Intent intent) { 

    setIntent(intent); 
} 

BeamFileActivity: Это отдельная деятельность, которая просто отображает инструкции по сияя данных и делает фактический луч.

private void initFileToBeam(Long spreadsheetId) { 

    try { 

     List<SpreadsheetDom> spreadsheets = db.getSpreadsheetDao().queryForEq(SpreadsheetDom.SPREADSHEET_ID_NAME, spreadsheetId); 
     if(spreadsheets != null && spreadsheets.size() > 0) { 

      fileToBeam = spreadsheets.get(0); 
     } 
    } catch(SQLException e) { 

     ErrorDialog ed = new ErrorDialog(this, "Unable to beam current collection."); 
     ed.show(); 
    } 
} 

@Override 
public NdefMessage createNdefMessage(NfcEvent event) { 

    if(fileToBeam == null) { 

     Long spreadsheetId = Settings.getInstance().get(SettingKey.CURRENT_SPREADSHEET).getValue(); 
     initFileToBeam(spreadsheetId); 
    } 

    NdefMessage msg = null; 
    try { 

     msg = new NdefMessage(
       new NdefRecord[]{ 
         new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, "application/com.myapp:SpreadsheetDom".getBytes(), new byte[0], fileToBeam.toBytes()), 
         //NdefRecord.createExternal("com.myapp", "spreadsheetdom", fileToBeam.toBytes()), 
         NdefRecord.createApplicationRecord("com.myapp") 
       }); 
    } catch(IOException e) { 

     String textMessage = "Unable to transfer collection: " + e.getMessage(); 
     msg = new NdefMessage(
       new NdefRecord[]{ 
         NdefRecord.createMime("text/plain", textMessage.getBytes()), 
         NdefRecord.createApplicationRecord("com.myapp") 
       }); 
    } 

    return msg; 
} 

@Override 
public void onResume() { 

    super.onResume(); 

    Intent exportFileIntent = getIntent(); 
    Long spreadsheetId = exportFileIntent.getLongExtra(Constants.EXTRA_SPREADSHEET_ID, Database.INVALID_ID); 

    initFileToBeam(spreadsheetId); 

    mNfcAdapter = NfcAdapter.getDefaultAdapter(this); 
    if (mNfcAdapter == null) { 

     Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show(); 
     finish(); 
     return; 
    } 
    // Register callback 
    mNfcAdapter.setNdefPushMessageCallback(this, this); 
} 

Действительно все это из примеров и документации here, here и here

ответ

2

Вы отправляете другой записи ЦНК, чем то, что ваш MainActivity предпологает. Ваш MainActivity зарегистрирован для NFC Forum внешнего типа "com.myapp: SpreadsheetDom":

<intent-filter> 
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/> 
    <category android:name="android.intent.category.DEFAULT"/> 
    <data android:scheme="vnd.android.nfc" 
      android:host="ext" 
      android:pathPrefix="/com.myapp:SpreadsheetDom"/> 
</intent-filter> 

Поскольку намерения фильтров в Android являются прецедентным чувствительны но NFC Forum имена внешнего типа к регистру нечувствительного, Android автоматически преобразует имена внешних типов NFC Forum (как и для типов MIME) в ниже -case. Поскольку ваш фильтр намерения содержит буквы верхнего регистра «S» и «D», он никогда не будет соответствовать типу имени вашего внешнего типа NFC Forum. Таким образом, вы должны указать имя типа, как и все строчные для достижения совпадения (см также here):

<intent-filter> 
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/> 
    <category android:name="android.intent.category.DEFAULT"/> 
    <data android:scheme="vnd.android.nfc" 
      android:host="ext" 
      android:pathPrefix="/com.myapp:spreadsheetdom"/> 
</intent-filter> 

Далее в вашем BeamFileActivity вы создаете внешнюю запись с именем недопустимого типа «приложение/ком .myapp: spreadsheetDom ":

msg = new NdefMessage(new NdefRecord[] { 
     new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, "application/com.myapp:SpreadsheetDom".getBytes(), new byte[0], fileToBeam.toBytes()), 
     NdefRecord.createApplicationRecord("com.myapp") 
}); 

NFC-форум внешнее имя типа, который соответствует указанным выше намерение фильтр будет "com.myapp: spreadsheetdom"(опять же, все строчные буквы). Вы можете создать такую ​​запись с (убедитесь, что использовать кодировку US-ASCII для имени типа):

msg = new NdefMessage(new NdefRecord[] { 
     new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, "com.myapp:spreadsheetdom".getBytes("US-ASCII"), new byte[0], fileToBeam.toBytes()), 
     NdefRecord.createApplicationRecord("com.myapp") 
}); 

Наконец, отметим, что «com.myapp» не является хорошо сформированным доменное имя для внешнего вида в соответствии с определением типа записи журнала NFC. Вместо этого хорошо сформированное доменное имя будет «myapp.com» (формат имени домена Интернета вместо формата имени пакета Java).

+0

Я внес изменения, которые вы предложили, и он все еще не работает. Я переключился на простое текстовое сообщение и изменил тип на TNF_MIME_MEDIA, и мне удалось получить данные для передачи. Однако, когда я переключился на свою электронную таблицу, он перестал работать, и, похоже, проблема может быть размером. Я конвертирую табличное пространство в поток bytearrayoutput и заполняет 9 буферов в этом объекте.Я не знаю, много ли это или нет, похоже, много. Есть ли ограничение на количество данных, которое вы можете отправить с сообщением TNF_MIME_MEDIA? – Hardy

+0

@ Харди Как большой (в байтах) ваш капля данных? Работает ли внешний тип с простым текстовым сообщением? –

+0

Когда я пытаюсь использовать внешний тип, он всегда идет в магазин воспроизведения и никогда не открывает мое приложение. Отчеты byteArrayOutputStream.size() 322,000 – Hardy

Смежные вопросы