簡體   English   中英

無法使用 4.x 推送 NdefMessage Android NFC API

[英]Unable to push NdefMessage with 4.x Android NFC API

我正在實施 CreateNdefMessageCallback 和 OnNdefPushCompleteCallback。 由於某種原因,回調方法從未被觸及,日志中也沒有錯誤。

不過,我確實聽到了 API 的聲音,我正在調試的手機是運行 4.0.4 版的 Nexus S。

這是我的活動:

public class TestActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback
{
  private static SoundHelper soundHelper;

  private PowerManager.WakeLock wakeLock;

  private NfcAdapter nfcAdapter;
  private PendingIntent pendingIntent = null;
  private IntentFilter[] intentFiltersArray;
  private String[][] techListsArray;

  private TextView onScreenLog;
  private List<String> uniqueTagsRead = new ArrayList<String>();

  /** handler stuff */
  private static final int MESSAGE_SENT = 1;
  private final Handler handler = new Handler()
  {
    @Override
    public void handleMessage(Message msg)
    {
      switch (msg.what)
      {
        case MESSAGE_SENT:
          if (soundHelper != null)
          {
            soundHelper.playSound(R.raw.smw_coin);
          }

          updateTagCount();
          break;
      }
    }
  };

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test);

    soundHelper = new SoundHelper(this);

    onScreenLog = (TextView) findViewById(R.id.log);

    // nfc adapter
    nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if (nfcAdapter != null)
    {
      // callbacks
      nfcAdapter.setNdefPushMessageCallback(this, this);
      nfcAdapter.setOnNdefPushCompleteCallback(this, this);

      // other stuff
      nfcAdapter = NfcAdapter.getDefaultAdapter(this);
      pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
      IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
      try
      {
        ndef.addDataType("*/*");
      }
      catch (MalformedMimeTypeException e)
      {
        throw new RuntimeException("fail", e);
      }
      intentFiltersArray = new IntentFilter[] {ndef, };
      techListsArray = new String[][] {
          new String[] { IsoDep.class.getName() },
          new String[] { NfcA.class.getName() },
          new String[] { NfcB.class.getName() },
          new String[] { NfcF.class.getName() },
          new String[] { NfcV.class.getName() },
          new String[] { Ndef.class.getName() },
          new String[] { NdefFormatable.class.getName() },
          new String[] { MifareClassic.class.getName() },
          new String[] { MifareUltralight.class.getName() },
      };
    }
    else
    {
      onScreenLog.setText("NFC is not available on this device. :(");
    }
  }

  public void onPause()
  {
    super.onPause();

    // end wake lock
    wakeLock.release();

    nfcAdapter.disableForegroundDispatch(this);
  }

  public void onResume()
  {
    super.onResume();

    // start wake lock
    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen");
    wakeLock.acquire();

    nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
  }

  private void updateTagCount()
  {
    String newCount = String.valueOf(uniqueTagsRead.size());
    String text = getString(R.string.format_count);
    text = getString(R.string.format_count).replace("0", newCount);

    onScreenLog.setText(text);
  }

  @Override
  public NdefMessage createNdefMessage(NfcEvent event)
  {
    String message = "This is NFC message";
    NdefRecord mimeRecord = createMimeRecord("application/param.android.sample.beam",
    message.getBytes());
    NdefRecord appRecord = NdefRecord.createApplicationRecord("param.android.sample.beam");
    NdefRecord[] ndefRecords = new NdefRecord[] {
    mimeRecord,
    appRecord
    };
    NdefMessage ndefMessage = new NdefMessage(ndefRecords);
    return ndefMessage;

    /*
    String mimeType = "text/plain"; // "text/plain";

    NdefRecord[] data = {createMimeRecord(mimeType, TEXT_TO_WRITE.getBytes())};
    // data[data.length - 1] = NdefRecord.createApplicationRecord(); // com.test.nfc.application.activities.

    return new NdefMessage(data);
    */
  }

  /**
   * Creates a custom MIME type encapsulated in an NDEF record
   *
   * @param mimeType
   */
  public NdefRecord createMimeRecord(String mimeType, byte[] payload)
  {
    byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
    NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);

    return mimeRecord;
  }

  @Override
  public void onNdefPushComplete(NfcEvent event)
  {
    handler.obtainMessage(MESSAGE_SENT).sendToTarget();
  }
}

顯現:

    <uses-sdk android:minSdkVersion="14" />

    <supports-screens android:anyDensity="true" /> 

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

    <uses-feature android:name="android.hardware.nfc" />

    <application android:name="com.test.nfc.application.Application"
        android:icon="@drawable/icon_launcher_nfc_droid_hdpi"
        android:theme="@android:style/Theme.Light"
        android:label="@string/app_name">

        <activity
            android:label="@string/app_name"
            android:name=".application.activities.MainActivity"
            android:configChanges="orientation|keyboardHidden">
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:label="@string/test"
            android:name=".application.activities.TestActivity"
            android:configChanges="orientation|keyboardHidden"
            android:launchMode="singleTop">

            <intent-filter>
              <action android:name="android.nfc.action.TECH_DISCOVERED"/>
            </intent-filter>
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_list" />

        </activity>

    </application>

</manifest>

技術清單

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

從你的問題和示例代碼中,我並不完全清楚你是想接收 NDEF 消息,發送它們還是兩者。

使用NfcAdapter.enableForegroundDispatch()時,您的 Activity 將通過調用onNewIntent()收到有關新 NFC 意圖的通知,因此您應該在 Activity 中覆蓋該方法以接收意圖。

NfcAdapter.CreateNdefMessageCallbackNfcAdapter.OnNdefPushCompleteCallback用於通過 Android BeamNDEF 數據發送到另一個 NFC 設備。 用戶需要點擊屏幕以激活發送 NDEF 消息,這將導致調用createNdefMessage()onNdefPushComplete()

還有一點要注意:如果將過濾器和null參數的 null 傳遞給NfcAdapter.enableForegroundDispatch() ,這將充當通配符(因此您不需要聲明完整的技術列表,就像您現在所做的那樣)。

看起來您獲得了兩次默認的 NFC 適配器?

nfcAdapter = NfcAdapter.getDefaultAdapter(這個);

在檢查 nfcAdapter 上的 null 之前執行一次,然后在 if 語句中再次執行。 這可能會產生一些奇怪的效果。 不過我不確定。 此外,您似乎在運行時聲明了意圖過濾器。 如果仍然有問題,請在清單中執行此操作以進行調試。 更容易確定某些東西以這種方式正確地過濾了意圖。

有關更多示例,請參閱此示例代碼和 SDK 中的 Android Beam 示例:

http://developer.android.com/guide/topics/nfc/nfc.html#p2p

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM