【发布时间】:2014-03-11 17:37:47
【问题描述】:
我正在尝试开发一个用例,这样当任何启用了 NFC 的智能手机的用户点击 NFC 标签时,浏览器应该会打开标签中包含的 URL。
目前我正在使用 Mifare Classic 1K 标签,其中包含我在 NFC 标签中写入的 URL http://www.google.com。
现在,当我点击/扫描 Google Nexus 7 (2012) 版本中的标签时,会检测到标签,但浏览器未显示。同样在包括三星 S3、S4 在内的其他设备上,根本没有检测到该标签。为什么会这样?
这是我编写和读取标签的代码,
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//check for nfc
adapter = NfcAdapter.getDefaultAdapter(this);
PendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writeTagFilters = new IntentFilter[] { tagDetected };
//write tag
write("http://www.google.com",tag);
}
private void write(String text, Tag tag) throws IOException, FormatException {
NdefRecord[] records = { createRecord(text) };
NdefMessage message = new NdefMessage(records);
// Get an instance of Ndef for the tag.
Log.i("App","Tag:" +tag);
Ndef ndef = Ndef.get(tag);
// Enable I/O
ndef.connect();
// Write the message
ndef.writeNdefMessage(message);
// Close the connection
ndef.close();
}
private NdefRecord createRecord(String text) throws UnsupportedEncodingException {
String lang = "en";
byte[] textBytes = text.getBytes();
byte[] langBytes = lang.getBytes("US-ASCII");
int langLength = langBytes.length;
int textLength = textBytes.length;
byte[] payload = new byte[1 + langLength + textLength];
// set status byte (see NDEF spec for actual bits)
payload[0] = (byte) langLength;
// copy langbytes and textbytes into payload
System.arraycopy(langBytes, 0, payload, 1, langLength);
System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);
NdefRecord recordNFC = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
return recordNFC;
}
@Override
protected void onNewIntent(Intent intent){
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
mytag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(mytag);
Toast.makeText(this, this.getString(R.string.ok_detection) + mytag.toString(), Toast.LENGTH_LONG ).show();
}
}
private class NdefReaderTask extends AsyncTask<Tag, Void, String> {
@Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e("App", "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
@Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(getApplicationContext(), "Read content: " +result,Toast.LENGTH_LONG).show();
webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(result);
}
}
}
清单.xml
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name="com.framentos.hellonfc.MainActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.NFC" />
另外,我是否需要在设备中始终存在一个应用程序才能调用浏览器。由于 NFC 是一项服务,所以不应该每个 NFC 设备都通过点击标签打开浏览器。
【问题讨论】:
标签: android browser nfc mifare ndef