0

我正在实现 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>
4

2 回答 2

2

从您的问题和示例代码中,我并不完全清楚您是要接收 NDEF 消息、发送它们还是两者兼而有之。

使用 时NfcAdapter.enableForegroundDispatch(),您的 Activity 将通过调用 获得有关新 NFC 意图的通知onNewIntent(),因此您应该在 Activity 中覆盖该方法以接收意图。

NfcAdapter.CreateNdefMessageCallbackNfcAdapter.OnNdefPushCompleteCallback用于通过 Android Beam将NDEF 数据发送到另一个 NFC 设备。用户需要点击屏幕来激活发送 NDEF 消息,这将导致调用createNdefMessage()onNdefPushComplete()

还有一点要注意:如果您将null过滤器和 techLists 参数传递给NfcAdapter.enableForegroundDispatch()它将充当通配符(因此您不需要像现在一样声明完整的技术列表)。

于 2012-04-10T20:20:33.603 回答
0

看起来您获得了两次默认的 NFC 适配器?

nfcAdapter = NfcAdapter.getDefaultAdapter(this);

您在检查 nfcAdapter 上的 null 之前执行一次,然后在您的 if 语句中再次执行此操作。这可能会产生一些奇怪的影响。不过我不确定。此外,您似乎正在运行时声明意图过滤器。如果您仍然有问题,请在清单中执行此操作以进行调试。更容易确定某些东西以这种方式正确过滤了意图。

有关更多示例,请参阅此示例代码和 SDK 中的 Android Beam 示例:

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

于 2012-04-10T16:32:36.400 回答