我正在尝试开发一个用例,以便当任何具有支持NFC的智能手机的用户点击NFC标签时,浏览器应该使用标签中包含的URL打开.
目前我使用的是Mifare Classic 1K标签,其中包含我在NFC标签中写的网址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{ @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); } } }
的Manifest.xml
此外,我是否需要在设备中始终显示一个应用程序,以便调用浏览器.由于NFC是一项服务,因此不应该每个NFC设备都打开浏览器标签.
这是因为您正在将标记为" http://www.google.com " 的文本记录写入标记.NFC设备通常不知道如何解释标签上的文本(尽管它们只能显示该文本 - 而某些设备正是这样做的).
您要做的是根据NFC论坛的URI记录类型定义创建记录.该createRecord
方法可能如下所示:
private NdefRecord createRecord(String uri) throws UnsupportedEncodingException { byte[] uriBytes = uri.getBytes("UTF-8"); byte[] payload = new byte[1 + uriBytes.length]; // set prefix byte (see URI RTD for possibile values, we just use 0 indicating no prefix for now) payload[0] = 0; // copy uriBytes into payload System.arraycopy(uriBytes, 0, payload, 1, uriBytes.length); return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, null, payload); }
或者您可以使用Android的内置方法:
record = NdefRecord.createUri("http://www.google.com");
关于在其他设备上的检测:在S3上使用MIFARE Classic标签应该可行.S4(以及基于Broadcom NFC芯片组的任何其他设备)根本不支持MIFARE Classic,因此您需要切换到另一种标签技术来支持这些设备.