将NDEF消息写入Runnable内的标记

时间:2014-03-06 13:22:27

标签: android multithreading nfc runnable ndef

我最近开始在Android上开发,并开始使用带有 NDEF 消息的NFC标签的项目。我设法创建了一个简单的应用程序,它将从text / plain NDEF记录中读取并将数据写入屏幕。

现在我正致力于将 NDEF 消息写入标签。我好像有它工作,但想知道是否最好在主UI线程以外的线程上编写标签?

最近开始学习之后,我被教导在主线程中执行(可能)长时间运行的任务是禁止的,并且认为写入标签会如此。但是,将代码写入Runnable()中的标记似乎会导致写入失败。所以,我的问题是。我错误地认为写入标签应该是从主线程完成的吗?或者我错了使用Runnable? 并且如果之前已经回答道歉,我尝试使用谷歌搜索,但在主题上找不到多少。

我已经包含了我的示例代码:

按钮处理程序:

public void writeButton(View view)
{
    //Some validation
    createMessageToWrite();
}

创建消息:

public void createMessageToWrite()
{       
    EditText messageBox = (EditText)findViewById(R.id.toWrite);
    String toWrite = messageBox.getText().toString();
    if(toWrite.length() == 0)
        toWrite = "This is some text from My writer";
    NdefRecord textRecord = NdefRecord.createMime("text/plain", toWrite.getBytes());
    NdefRecord aar        = NdefRecord.createApplicationRecord(getPackageName());

    NdefMessage message = new NdefMessage(new NdefRecord[]{textRecord, aar});
    messageToWrite=message;
    Toast.makeText(getApplicationContext(), "Message made", Toast.LENGTH_SHORT).show();

    write();
}

最后,我的代码写入标签:

public void write()
{       
    Toast.makeText(getApplicationContext(),"Starting write. Touch tag",Toast.LENGTH_SHORT).show();
    sleep(3000);
//  Runnable r = new Runnable()
    //{
//      @Override
//      public void run()
//      {
            Toast.makeText(getApplicationContext(),"Starting runnable. Touch tag",Toast.LENGTH_SHORT).show();
            sleep(3000);

            if(messageToWrite == null)
            {
                Toast.makeText(getApplicationContext(),"Message is null",Toast.LENGTH_SHORT).show();
                return;
            }

            Toast.makeText(getApplicationContext(), "Trying", Toast.LENGTH_SHORT).show();
            sleep(3000);

            try
            {                   
                if(theTag != null)
                {
                    theTag.connect();//The tag is a global var set in onCreate() or onNewIntent()
                    theTag.writeNdefMessage(messageToWrite);
                    theTag.close();
                }
                else
                {
                    Toast.makeText(getApplicationContext(), "tag is null", Toast.LENGTH_SHORT).show();
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "IOException", Toast.LENGTH_LONG).show();
            }
            catch (FormatException e)
            {
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "Format", Toast.LENGTH_LONG).show();
            }
            Toast.makeText(getApplicationContext(),"Written",Toast.LENGTH_SHORT).show();
        }
//      };
//      Thread t = new Thread(r);
//      t.start();
//  }

发布的代码有效,但取消注释Runnable()会导致应用崩溃。不幸的是,我正在处理的系统没有设置为允许从设备进行USB调试,而我没有安装驱动程序的权限。所以,在设置之前,我必须满足于“应用已经停止工作”的消息......

非常感谢任何和所有帮助

编辑:语法

1 个答案:

答案 0 :(得分:2)

首先,在不知道你得到什么异常的情况下,我会假设崩溃/异常不是由在单独的线程中执行写操作而是通过从非UI线程显示Toast引起的。

必须始终从UI线程中显示

Toast。您可以通过将Toast.makeText(...).show()调用包含在以下内容中来解决此问题:

runOnUiThread(new Runnable() {
    public void run() {
        Toast.makeText(YourActivityClass.this, yourMessage, Toast.LENGTH_SHORT).show();
    }
});

其次,优良作法是在单独的线程中访问NFC标签(或者通常用于执行IO操作)。

第三,用户与NFC标签的交互通常是非常短的动作,并且用户通常仅在实际的读取,写入等操作期间轻敲标签。因此,保存Tag句柄并在稍后通过额外的用户输入(按下按钮)调用写入操作通常是一个非常糟糕的想法(尽管可能存在一些罕见的例外)。

更好的方法是存储要写入的NDEF消息,将应用程序设置为某种“写入模式”状态,并提示用户点击标记。然后,在标记检测时,启动写入线程并让它写入先前保存的消息。