2014-03-06 52 views
0

我最近開始在Android中開發並已啓動一個項目,使用NFC標籤和NDEF消息。我設法創建了一個簡單的應用程序,它將從文本/純NDEF記錄中讀取數據並將數據寫入屏幕。將NDEF消息寫入可運行內部的標記

現在我正在編寫NDEF消息到標籤。我似乎有它的工作,但不知道是否最好在除主UI線程之外的線程上寫標籤?

在最近開始學習的時候,我被告知,在主線程中執行(可能)長時間運行的任務是一個不允許的,並且認爲寫入標籤也是如此。但是,將代碼寫入Runnable()中的標籤似乎會導致寫入失敗。所以,我的問題是。我的想法是錯誤的,即寫入標籤應該從主線程完成。或者我錯了使用Runnable? 如果已經回答過此問題,並表示歉意,我嘗試了使用Google搜索,但無法在該主題上找到太多內容。

我包括我的示例代碼:

按鈕處理程序:

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調試,並且我沒有安裝驅動程序的權限。所以,直到某個設定,我不得不接受了「該應用程序已停止工作」的消息......

任何非常感謝所有幫助

編輯:語法

+0

在我寫這篇文章時,我發現Runnable可能無法訪問(class-level)標籤對象theTag。這可能是問題嗎? – cprlkleg

回答

2

首先,不知道你得到了什麼異常,我會假設崩潰/異常不是由在單獨的線程中執行寫入操作引起的,而是通過從非UI線程中顯示Toast引起的。

Toast必須始終從UI線程顯示。您可以通過類似下面包裹Toast.makeText(...).show()呼叫解決這個問題:

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

其次,它是訪問NFC標籤(或一般做的IO操作)在一個單獨的線程很好的做法。第三,用戶與NFC標籤的交互通常是非常短的動作,並且用戶通常僅在實際讀取,寫入等操作期間點擊標籤。因此,保存Tag句柄並稍後在其他用戶輸入(按下按鈕)時調用寫入操作通常是一個非常糟糕的主意(儘管如此,也可能存在一些罕見的例外情況)。

更好的方法是存儲要寫入的NDEF消息,將您的應用程序設置爲某種「寫入模式」狀態並提示用戶點擊標記。然後,在標籤檢測時,啓動寫入線程並讓它寫入先前保存的消息。

+0

非常感謝您的回覆。在不正確的線程上運行的敬酒很可能是問題,非常感謝您的洞察力。我正在努力獲取安裝USB調試的驅動程序,因此希望能夠儘快獲得更好的洞察力。 – cprlkleg

+0

更要感謝您關於如何構建流程的建議,我只是想在完成代碼之前讓寫入工作。然而,你所說的話是非常真實而且很好的建議。 親切的問候 – cprlkleg