2017-08-07 50 views
1

我正在開發一款NFC應用程序。我正在使用一個例子,其中發送和接收數據由同一活動執行。現在我需要將發送到另一個,出於某種原因,接收不再工作。接收意向動作MAIN而不是NDEF消息

這裏是我的mainifest:

<uses-permission android:name="android.permission.NFC" /> 

<uses-feature 
    android:name="android.hardware.nfc" 
    android:required="true" /> 
    <activity 
     android:name=".Screens.LogIn.LogInActivity" 
     android:launchMode="singleTop"> 

     <intent-filter> 
      <action android:name="android.nfc.action.NDEF_DISCOVERED" /> 
      <category android:name="android.intent.category.DEFAULT"/> 
      <data android:mimeType="text/plain" /> 
     </intent-filter> 

     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 

和接收活動:

public class LogInActivity extends AppCompatActivity { 

public static final String TAG = LogInActivity.class.getSimpleName(); 

private String messagesToReceive= null; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_log_in); 
    replaceFragment(); 

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

private void replaceFragment() { 
    android.support.v4.app.FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction(); 
    LogInFragment fragment = new LogInFragment(); 
    ft.replace(R.id.fragmentFrame, fragment, LogInFragment.TAG); 
    ft.commit(); 
} 

@Override 
public void onResume() { 
    super.onResume(); 
    handleNfcIntent(getIntent()); 
} 

@Override 
public void onNewIntent(Intent intent) { 
    handleNfcIntent(intent); 
} 


private void handleNfcIntent(Intent NfcIntent) { 

    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(NfcIntent.getAction())) { 
     Parcelable[] receivedArray = 
       NfcIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); 

     if(receivedArray != null) { 
      NdefMessage receivedMessage = (NdefMessage) receivedArray[0]; 
      NdefRecord[] attachedRecords = receivedMessage.getRecords(); 

      for (NdefRecord record:attachedRecords) { 
       String string = new String(record.getPayload()); 
       if (string.equals(getPackageName())) { continue; } 
       messagesToReceive = string; 
      } 
      Toast.makeText(this, "Received " + 
        " Messages", Toast.LENGTH_LONG).show(); 
     } 
     else { 
      Toast.makeText(this, "Received Blank Parcel", Toast.LENGTH_LONG).show(); 
     } 
    } 
} 

的問題是,NfcIntent.getAction()總是等於android.intent.action.MAIN,即使應用程序打開時,我與NFC發送數據。如您所見,清單中有動作NDEF_DISCOVERED

這是我送:

public NdefRecord[] createRecords() { 
    NdefRecord[] records = new NdefRecord[2]; 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     byte[] payload = messagesToSend. 
       getBytes(Charset.forName("UTF-8")); 
     NdefRecord record = new NdefRecord(
       NdefRecord.TNF_WELL_KNOWN,  //Our 3-bit Type name format 
       NdefRecord.RTD_TEXT,   //Description of our payload 
       new byte[0],     //The optional id for our Record 
       payload);      //Our payload for the Record 

     records[0] = record; 
    } 
    else { 
     byte[] payload = messagesToSend.//messagesToSendArray.get(i). 
       getBytes(Charset.forName("UTF-8")); 

     NdefRecord record = NdefRecord.createMime("text/plain",payload); 
     records[0] = record; 
    } 
    records[1] = NdefRecord.createApplicationRecord(getActivity().getPackageName()); 
    return records; 
} 


@Override 
public NdefMessage createNdefMessage(NfcEvent event) { 
    if (messagesToSend != null && !messagesToSend.equals("")) { 
     return null; 
    } 
    NdefRecord[] recordsToAttach = createRecords(); 
    return new NdefMessage(recordsToAttach); 
} 
+0

你在另一端發送了什麼數據? –

+0

只是一個字符串。正如你可以在這裏看到的「android:mimeType =」text/plain「」 –

+0

@MichaelRoland我編輯了我的帖子 –

回答

1

接收的意圖行動MAIN,而不是NDEF_DISCOVERED爲NFC事件通常是一個明確的跡象表明,發送方發送包含一個Android應用程序記錄和你NDEF消息沒有過濾該NDEF消息的第一個記錄。

由於您的接收方有一個NDEF_DISCOVERED意圖過濾器,問題很可能位於發送端。看看您的代碼,這可能有幾個原因:

  1. 發送方在createNdefMessage()中創建NDEF消息。在那裏,你測試messagesToSend是空還是空。如果既不爲null也不空,你從NDEF消息創建回調返回null

    if (messagesToSend != null && !messagesToSend.equals("")) { 
        return null; 
    } 
    

    既然你沒有透露如果messagesToSend爲空或空的,沒有人能告訴你,如果atually來創建點在哪裏你擁有NDEF訊息。但是,messagesToSend可能是空/空,因爲從返回null將完全禁用波束。

  2. 您沒有透露發送方的剩餘代碼。因此,無法確定您是否實際註冊了createNdefMessage()回撥。你應該有一個像

    nfcAdapter.setNdefPushMessageCallback(this, this); 
    

    onCreate()。如果不是這樣,Android將使用默認的NDEF消息。默認的NDEF消息通常由您的應用的URI記錄和AAR組成。這可以解釋爲什麼接收方看到意圖操作MAIN,因爲您的活動未註冊接收該特定URI記錄。

  3. 在Android版本低於果凍豆,病情

    (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 
    

    計算爲true和你,因此,打if語句的一個分支。在此分支中,您將創建一個無效的結構的NFC論壇文本記錄。這可能會導致接收設備無法將NDEF記錄解碼爲有效的文本記錄。因此,接收設備可能不會將此記錄與text/plain類型的NDEF_DISCOVERED意向過濾器相匹配。

    爲了解決這個問題,您需要創建一個有效的文本記錄。文本RTD需要在形式編碼的有效載荷(也參見this post

     
    +----------+---------------+--------------------------------------+ 
    | Status | Language Code | Text         | 
    | (1 byte) | (n bytes)  | (m bytes)       | 
    +----------+---------------+--------------------------------------+ 
    
    其中Status等於該Language Code的長度n如果Text是UTF-8編碼和Language Code是IANA語言代碼(例如,「en」表示英語)。因此,對編碼記錄的正確方法應該是:

    public static NdefRecord createTextRecord(String language, String text) { 
        byte[] languageBytes; 
        byte[] textBytes; 
        try { 
         languageBytes = language.getBytes("US-ASCII"); 
         textBytes = text.getBytes("UTF-8"); 
        } catch (UnsupportedEncodingException e) { 
         throw new AssertionError(e); 
        } 
    
        byte[] recordPayload = new byte[1 + (languageBytes.length & 0x03F) + textBytes.length]; 
    
        recordPayload[0] = (byte)(languageBytes.length & 0x03F); 
        System.arraycopy(languageBytes, 0, recordPayload, 1, languageBytes.length & 0x03F); 
        System.arraycopy(textBytes, 0, recordPayload, 1 + (languageBytes.length & 0x03F), textBytes.length); 
    
        return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, null, recordPayload); 
    } 
    
  4. 當方法createRecords()被稱爲上線

    NdefRecord[] recordsToAttach = createRecords(); 
    

    messagesToSend null或空的(因爲你本來否則返回null) 。如果messagesToSendnull專門和你打線

    byte[] payload = messagesToSend.getBytes(Charset.forName("UTF-8")); 
    

    createRecords(),那麼這將導致NullPointerException(因爲你試圖訪問一個空實例的方法)。由於您從未發現此例外情況,因此回調createNdefMessage()將因相同的例外而失敗。在這種情況下,Android會處理這個異常,並且會自動使用默認的NDEF消息(包括一個URI記錄和一個針對你的應用程序的AAR)。由於您的接收端不會過濾該URI記錄(默認NDEF消息的第一條記錄),因此您的接收器將僅由AAR進行定義,並且您將收到意圖操作MAIN,因爲Android假定您的活動已準備好接收特定的NDEF消息。