2016-10-04 2 views
1

Ich habe die Dokumentation ein paar Mal gelesen und habe mir den Beispielcode angesehen, aber ich kann nicht herausfinden, was ich falsch mache.Warum empfängt Android Beam/NFC die von mir gesendeten Datensätze nicht?

Immer wenn ich meine zwei Geräte zusammenstelle, sehe ich den Beam-Bildschirm und tippe darauf, aber nichts scheint gesendet zu werden und keiner meiner Breakpoints wird getroffen. Hier ist mein Code, bitte helfen Sie mir herauszufinden, warum nichts an das andere Gerät gesendet wird. Im Editor kann ich sehen, dass alles in BeamFileActivity läuft, ich sehe einfach nie einen der Breakpoints in MainActivity auf dem empfangenden Gerät abrufen. Was mache ich falsch?

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: Dies ist, was die Absicht Lichtstrahl empfangen wird, ich bin die Methoden nur einschließlich ich denke, relevant sind.

@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: Dies ist eine separate Aktivität, die nur Anweisungen zum Übertragen der Daten anzeigt und den tatsächlichen Strahl ausführt.

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); 
} 

Wirklich alles ist aus den Beispielen und Dokumentation here, here und here

Antwort

2

Du einen anderen NDEF Rekord als das, was Ihr MainActivity erwartet sendet. ": SpreadsheetDom com.myapp": Ihr MainActivity für das NFC-Forum externen Typ registriert

<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> 

Da Absicht Filter in Android sind Case- empfindlich aber NFC Forum externen Typnamen sind Case- unempfindlich, Android konvertiert automatisch die Namen der externen Typen von NFC Forum (genau wie bei MIME-Typen) in unter -case. Da Ihr Intent-Filter die Großbuchstaben "S" und "D" enthält, entspricht er niemals dem Typnamen Ihres externen NFC Forum-Typs. Daher müssen Sie die Typnamen wie alle Kleinbuchstabe angeben um eine Übereinstimmung zu erzielen (siehe auch 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> 

nächste in Ihrem BeamFileActivity Sie erstellen einen externen Datensatz mit dem ungültigen Typnamen „application/com .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") 
}); 

Ein NFC-Forum externen Typ Name, der die oben Intent-Filter passt wäre "com.myapp: spreadsheetdom"(auch hier alle Kleinbuchstaben). Sie können mit einem solchen Datensatz erstellen (stellen Sie sicher, dass US-ASCII-Kodierung für den Typ-Namen verwenden):

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") 
}); 

Schließlich ist zu beachten, dass „com.myapp“ ist keine wohlgeformte Domain-Namen für einen externen Typ gemäß der NFC Forum Record Type Definition. Stattdessen wäre ein wohlgeformter Domainname "myapp.com" (Internetdomänennamenformat anstelle des Java-Paketnamenformats).

+0

Ich habe die vorgeschlagenen Änderungen vorgenommen und es funktioniert immer noch nicht. Ich wechselte zu einer einfachen Textnachricht und änderte den Typ in TNF_MIME_MEDIA und ich konnte Daten zur Übertragung erhalten. Als ich jedoch wieder zu meinem Tabellenkalkulationsprogramm wechselte, hörte es auf zu arbeiten und es scheint, dass das Problem die Größe sein könnte. Ich konvertiere den Tabellendom in einen Bytearrayoutputstream und füllt 9 Puffer in diesem Objekt. Ich weiß nicht, ob das viel ist oder nicht, scheint sehr viel zu sein.Gibt es eine Beschränkung für die Menge der Daten, die Sie mit einer TNF_MIME_MEDIA-Nachricht senden können? – Hardy

+0

@Hardy Wie groß (in Bytes) ist Ihr Datenblob? Arbeitet der externe Typ mit der einfachen Textnachricht? –

+0

Wenn ich den externen Typ versuche, geht es immer zum Play Store und öffnet nie meine App. Die ByteArrayOutputStream.size() Berichte 322.000 – Hardy

Verwandte Themen