【问题标题】:Illegal character in NDEF URI payloadNDEF URI 有效负载中的非法字符
【发布时间】:2013-02-10 14:25:36
【问题描述】:

我正在编写基于 NFC 的应用程序,该应用程序将使用 Url 扫描 NFC 标签。一旦扫描了标签,应用程序应该从数据库中检索信息并将其显示在 ListView 中。

当我扫描 NFC 标签时出现错误。

 Error in http connection java.lang.IllegalArgumentException: Illegal character in scheme at index 0: ??http://abc.com/~090123/get_items.php

logcat 在http:// 之前显示一些奇怪的?? 字符。

我正在使用以下代码在标签中编写 URL:

private boolean writeTag(Tag tag) {         
    byte[] uriField = "http://abc.com/~090123/get_items.php".getBytes(Charset.forName("US-ASCII"));
    byte[] payload = new byte[uriField.length + 1];

    System.arraycopy(uriField, 0, payload, 1, uriField.length);         

    NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                NdefRecord.RTD_URI, new byte[0], payload);
    NdefMessage message = new NdefMessage(new NdefRecord[] { uriRecord});
    // ....
}

我从 NFC 标签接收到这样的意图:

protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
    setContentView(R.layout.content_display);           

    Intent intent =  getIntent();    

    if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {

        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
            NfcAdapter.EXTRA_NDEF_MESSAGES);

        if(rawMsgs != null) {           

            NdefMessage msg = (NdefMessage) rawMsgs[0];        

            GetData getData = new GetData(this);
                getData.execute(new String(msg.getRecords()[0].getPayload()));
        }
    }
}

我正在使用以下代码从数据库中检索信息:

protected BufferedReader doInBackground(String... params) {
    ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    try {
        HttpClient httpclient = new DefaultHttpClient();

        for (int i = 0; i < params.length; i++) 
        {
            HttpPost httppost = new HttpPost(params[i]);
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
             is = entity.getContent();
        }

    } catch (Exception e) {
            Log.e("log_tag", "Error in http connection " + e.toString());
    }

    Log.e("Input Stream", "Input Stream:" + is);

    BufferedReader myReader = new BufferedReader(new InputStreamReader(is));

    return myReader;
}

我对以前的 NDEF 记录有这样的意图过滤器:

<activity
            android:name=".DisplayContentActivity"
            android:label="@string/app_name" >

            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <data
                    android:host="abc.com"
                    android:pathPrefix="/~090123/get_items.php"
                    android:scheme="http" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

任何帮助将不胜感激。

【问题讨论】:

    标签: android nfc ndef


    【解决方案1】:

    URI 负载的第一个字节是URI 标识符代码,它是一个URI 前缀,如http://www.mailto:。您在有效负载长度中正确添加了一个字节,并在复制 URL 时使用了 1 的偏移量。你永远不会写这个字节,所以它仍然是0x00没有前缀),这意味着你需要写整个 URL。这很好,不过如果您想节省几个字节,您可以将其设置为 0x03 以获得 http:// 前缀。

    使用msg.getRecords()[0].getPayload()读取payload时,需要自己剪掉那个字节,加上前缀。我认为没有针对此的原生 Android API,因此您必须自己查找前缀或尝试其他答案中提到的库。

    要正确读取 uri,您应该使用以下内容:

    byte[] payload = msg.getRecords()[0].getPayload();
    byte identifierCode = payload[0];
    
    String prefix = getUrlPrefix(identifierCode); // you need to implement this one
    String url = prefix +
        new String(payload, 1, payload.length -1, Charset.forName("US-ASCII"));
    
    getData.execute(url);
    

    getUrlPrefix 方法可以包含一个简单的 switch 语句来返回标识符代码的前缀字符串。

    您可以在此处查看代码列表:About the NDEF Format

    Value    Protocol
    -----    --------
    0x00     No prepending is done ... the entire URI is contained in the URI Field
    0x01     http://www.
    0x02     https://www.
    0x03     http://
    0x04     https://
    0x05     tel:
    0x06     mailto:
    0x07     ftp://anonymous:anonymous@
    0x08     ftp://ftp.
    0x09     ftps://
    0x0A     sftp://
    ...
    

    【讨论】:

    • 嗨,我试过像这样添加 URI 标识符代码: byte[] payload = new byte[uriField.length + 1];有效载荷[0] = 0x03; System.arraycopy(uriField, 0, payload, 1, uriField.length);我仍然遇到同样的错误。
    • @Sujal 重点是在读取有效载荷时,标识符代码字节包含在有效载荷中。我用一个例子更新了答案。
    • 在 Android 4.2 中,NdefRecord 类具有方便的方法 toUri() 从几种类型的 NDEF 记录中提取 URI。
    【解决方案2】:

    您正在错误地解析 NDEF 记录。第一个字节不是字符。要么阅读 NFC 论坛标准,要么查看我为在这种情况下提供帮助而创建的 lib。您可以查看 Android 源代码,了解您尝试读取的记录是如何构造的。

    【讨论】:

      猜你喜欢
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多