【问题标题】:Writing plain text to an NFC tag, problems with intents将纯文本写入 NFC 标签,意图问题
【发布时间】:2015-08-13 13:46:02
【问题描述】:

我正在尝试制作一个将简单的纯文本消息写入 NFC 标签的应用程序。用户在 EditText 框中写入一条消息,然后按下按钮,应用程序将文本写入标签。 我一直在关注本教程:http://www.framentos.com/it/android-tutorial/2012/07/31/write-hello-world-into-a-nfc-tag-with-a/ 但是,当我尝试将 NFC 标签放在它旁边时,手机会打开另一个应用程序,而不是使用我已经打开的应用程序。我知道问题出在意图上,但我不想在清单中声明意图过滤器,因为我不希望在将标签放在手机旁边时打开应用程序,我希望应用程序是已经提前开了。 这是应用程序的代码:

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class MainActivity extends AppCompatActivity {

    NfcAdapter adapter;
    PendingIntent pendingIntent;
    IntentFilter writeTagFilters[];
    Tag mytag;
    Context ctx;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ctx=this;
        Button btnWrite = (Button) findViewById(R.id.button);
        final EditText message = (EditText)findViewById(R.id.edit_message);
        btnWrite.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v) {
                try {
                    if(mytag==null){
                        Toast.makeText(ctx, ctx.getString(R.string.error_detected), Toast.LENGTH_LONG).show();
                    }else{
                        write(message.getText().toString(),mytag);
                        Toast.makeText(ctx, ctx.getString(R.string.ok_writing), Toast.LENGTH_LONG ).show();
                    }
                } catch (IOException e) {
                    Toast.makeText(ctx, ctx.getString(R.string.error_writing), Toast.LENGTH_LONG ).show();
                    e.printStackTrace();
                } catch (FormatException e) {
                    Toast.makeText(ctx, ctx.getString(R.string.error_writing) , Toast.LENGTH_LONG ).show();
                    e.printStackTrace();
                }
            }
        });

        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_NDEF_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        writeTagFilters = new IntentFilter[] { tagDetected };
    }

    private NdefRecord createRecord(String text) throws UnsupportedEncodingException {

        //create the message in according with the standard
        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];
        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;
    }

    private void write(String text, Tag tag) throws IOException, FormatException {

        NdefRecord[] records = { createRecord(text) };
        NdefMessage message = new NdefMessage(records);
        Ndef ndef = Ndef.get(tag);
        ndef.connect();
        ndef.writeNdefMessage(message);
        ndef.close();
    }

    @Override
    protected void onNewIntent(Intent intent){
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())){
            mytag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Toast.makeText(this, this.getString(R.string.ok_detection) + mytag.toString(), Toast.LENGTH_LONG ).show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {


   return true;
    }

    return super.onOptionsItemSelected(item);
}

}

请帮忙,我不知道我做错了什么! 我只是 NFC 和 Android 编程的初学者!

【问题讨论】:

    标签: java android android-intent nfc


    【解决方案1】:

    您必须使用启用前台调度:http://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc.html#foreground-dispatch

    前台调度系统允许一个活动拦截一个 意图并声称优先于处理相同的其他活动 意图。

    更新1

    所有种类的标签都很难写,其中一些有封闭的规范。你可以先写NdefNdefFormatable标签。

    例如:

    @Override 
    protected void onPause() {
        super.onPause();
        mAdapter.disableForegroundDispatch(this);
    }
    
    @Override 
    protected void onResume(){
      super.onResume();
      PendingIntent 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) {
        Log.e(TAG,"Bad MIME type declared",e);
        return;
      }
      IntentFilter[] filters=new IntentFilter[]{ndef};
      String[][] techLists=new String[][]{new String[]{Ndef.class.getName()},new String[]{NdefFormatable.class.getName()}};
      mNfcAdapter.enableForegroundDispatch(this,pendingIntent,filters,techLists);
    }
    
    @Override 
    protected void onNewIntent(Intent intent) {
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String[] techList = tag.getTechList();
        for (String tech : techList) {
              if (tech.equals(Ndef.class.getName())) {
                  //write NDEF msg
              } else if (tech.equals(NdefFormatable.class.getName())) {
                  //format and write NDEF msg
              }
        }
    }
    

    【讨论】:

    • 我还是有问题。它给了我一个空指针异常,在 onResume 函数中。我认为这是因为 techListArrays,因为我不知道如何使用它或在其中放入什么:(
    • 好吧,我使用以下代码修复了它:code.tutsplus.com/tutorials/… 非常感谢!!
    • 您可以在您的技术列表中使用 NDEF developer.android.com/reference/android/nfc/tech/Ndef.html。你只会得到已经 NDEF 格式的 TAG。
    • 如果我想写各种标签怎么办?我怎样才能做到这一点?我必须在我的 res 文件夹中创建一个 techlist 文件吗?之后我如何在我的代码中实现它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多