我正在实现CreateNdefMessageCallback和OnNdefPushCompleteCallback。由于某些原因,永远不要触碰回调方法,日志中也不会出现错误。
虽然我确实从API听到声音,但我正在调试的手机是运行版本4.0.4的NexusS。
这是我的活动:
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()
时,将通过调用onNewIntent()
通知您的Activity有关新的NFC意图,因此您应在Activity中重写该方法以接收意图。NfcAdapter.CreateNdefMessageCallback
和NfcAdapter.OnNdefPushCompleteCallback
用于通过Android Beam将NDEF数据发送到另一个NFC设备。用户需要点击屏幕以激活发送NDEF消息,这将导致呼叫createNdefMessage()
和onNdefPushComplete()
。
再说一遍:如果将null
作为过滤器和techLists参数传递给NfcAdapter.enableForegroundDispatch()
,它们将充当通配符(因此,您无需像现在一样声明完整的技术列表)。
关于java - 无法使用4.x Android NFC API推送NdefMessage,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10081852/