2011-05-10 25 views
2

我完全不熟悉Android开发,必须编写一个简单的应用程序来读取大学的nfc标签(与nexus s)。Android NFC前台调度问题

我的问题是,当nexus发现一个标签时,我的应用没有列在“选择一个动作” - popup中。其目的是在http://developer.android.com/guide/topics/nfc/index.htmlhttp://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundDispatch.html

描述阅读使用前景分派方法的标签,我认为有什么东西在清单中失踪,但我不知道是什么。 这里的清单:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.iforge.android.nfc" 
> 
<uses-permission android:name="android.permission.INTERNET"></uses-permission> 
<uses-permission android:name="android.permission.NFC" /> 
<uses-permission android:name="android.permission.CALL_PHONE" /> 
<application 
    android:icon="@drawable/icon" 
    android:label="@string/app_name" 
> 
<activity android:name=".simulator.FakeTagsActivity" 
    android:theme="@android:style/Theme.NoTitleBar"> 
    <intent-filter> 
     <action android:name="android.intent.action.MAIN" /> 
     <category android:name="android.intent.category.LAUNCHER" /> 
    </intent-filter> 

</activity> 

    <activity android:name="TagViewer" 
     android:theme="@android:style/Theme.NoTitleBar" 
    > 
     <intent-filter> 
      <action android:name="android.nfc.action.NDEF_DISCOVERED"/> 
      <data android:mimeType="mime/type" /> 
     </intent-filter> 

     <intent-filter> 
      <action android:name="android.nfc.action.TECH_DISCOVERED"/> 

     </intent-filter> 

     <intent-filter> 
      <action android:name="android.nfc.action.TAG_DISCOVERED"/> 
     </intent-filter> 
    </activity> 
</application> 
<uses-sdk android:minSdkVersion="10" /> 
<uses-feature android:name="android.hardware.nfc" android:required="true" /> 

这里是当标签被发现,应该叫活动(这是打造出来的机器人NFCDemo的还有ForegroundDispatch-例子)的代码:

public class TagViewer extends Activity 
{ 

WebView webView; 
private NfcAdapter mAdapter; 
private PendingIntent mPendingIntent; 
private IntentFilter[] mFilters; 
private String[][] mTechLists; 

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    mAdapter = NfcAdapter.getDefaultAdapter(this); 
    mPendingIntent = 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("*/*"); /* Handles all MIME based dispatches. 
             You should specify only the ones that you need. */ 
    } 
    catch (MalformedMimeTypeException e) { 
     throw new RuntimeException("fail", e); 
    } 

    mFilters = new IntentFilter[] { 
      ndef, 
    }; 

    mTechLists = new String[][] { new String[] { NfcF.class.getName() } }; 


    setContentView(R.layout.tag_viewer); 
    webView = (WebView) findViewById(R.id.webView1); 
    webView.getSettings().setJavaScriptEnabled(true); 
    webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false); 
    webView.getSettings().setPluginsEnabled(false); 
    webView.getSettings().setSupportMultipleWindows(false); 
    webView.getSettings().setSupportZoom(false); 
    webView.setVerticalScrollBarEnabled(false); 
    webView.setHorizontalScrollBarEnabled(false); 

    resolveIntent(getIntent()); 
} 

@Override 
public void onResume() { 
    super.onResume(); 
    mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists); 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    mAdapter.disableForegroundDispatch(this); 
} 

void resolveIntent(Intent intent) 
{ 
    // Parse the intent 
    String action = intent.getAction(); 
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) 
    { 
     // When a tag is discovered we send it to the service to be save. We 
     // include a PendingIntent for the service to call back onto. This 
     // will cause this activity to be restarted with onNewIntent(). At 
     // that time we read it from the database and view it. 
     Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); 
     NdefMessage[] msgs; 
     if (rawMsgs != null) 
     { 
      msgs = new NdefMessage[rawMsgs.length]; 
      for (int i = 0; i < rawMsgs.length; i++) 
      { 
       msgs[i] = (NdefMessage) rawMsgs[i]; 
      } 
     } 
     else 
     { 
      // Unknown tag type 
      byte[] empty = new byte[] {}; 
      NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty); 
      NdefMessage msg = new NdefMessage(new NdefRecord[] {record}); 
      msgs = new NdefMessage[] {msg}; 
     } 
     // Setup the web-view 
     setUpWebView(msgs); 
    } 
    else 
    { 
     Log.e("ViewTag", "Unknown intent " + intent); 
     finish(); 
     return; 
    } 
} 

void setUpWebView(NdefMessage[] msgs) 
{ 
    if (msgs == null || msgs.length == 0) return; 

    String urlToLoad = MessageParser.parseMessage(msgs[0]); 
    if(!urlToLoad.matches("")) webView.loadUrl(urlToLoad); 

} 

@Override 
public void onNewIntent(Intent intent) 
{ 
    setIntent(intent); 
    resolveIntent(intent); 
    Log.i("Foreground dispatch", "Discovered tag with intent: " + intent); 
} 
} 

我试了很多,但没有任何工作。如果有人能告诉我我错过了什么,那将是非常棒的。我跑出来的时间:-(

感谢

回答

0

如果您启动Activity并注册foregroudn dispatch,必须做的是为ACTION_TAG_DISCOVERED注册一个意图过滤器 - 这是最低的过滤器,并匹配所有发现的标签。如果你想更具体一些,你可以为标签技术或者包含ndef的标签注册一个意图过滤器。

但是,如果您想要使用水龙头向标签从主屏幕启动应用程序,则必须以不同方式执行此操作。我成功地将一个MIME消息放到一个标签上,并将该MIME类型注册到我的活动中。另一种方法是将URL添加到标记中,然后注册一个用来计算方案和主机的意图过滤器。对于MIME,这是你所需要的:

为了使这个比赛,该标签需要的描述有一默默NDEF消息。

4

你的清单文件需要处理技术发现的意图,在一个单独的高科技过滤器的XML,像这样:

<intent-filter> 
     <action android:name="android.intent.action.MAIN" /> 
     <category android:name="android.intent.category.LAUNCHER" /> 
    </intent-filter> 
    <intent-filter> 
     <action android:name="android.nfc.action.TECH_DISCOVERED"/> 
      </intent-filter> 
      <meta-data android:name="android.nfc.action.TECH_DISCOVERED" 
           android:resource="@xml/nfc_tech_filter" /> 
      <intent-filter> 
       <action android:name="android.nfc.action.TAG_DISCOVERED"/> 
      </intent-filter> 

然后你RES/XML/nfc_tech_filter.xml必须处理你想这样的NFC科技股:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 
    <tech-list> 
     <tech>android.nfc.tech.MifareUltralight</tech> 
     <tech>android.nfc.tech.Ndef</tech> 
     <tech>android.nfc.tech.NfcA</tech> 
    </tech-list> 
    <tech-list> 
     <tech>android.nfc.tech.MifareClassic</tech> 
     <tech>android.nfc.tech.Ndef</tech> 
     <tech>android.nfc.tech.NfcA</tech> 
    </tech-list> 
</resources> 

每个科技节点都像AND,而tech-list节点的作用类似于或。我建议您首先使用NFC标签阅读器等工具扫描您的标签,以了解您的技术。像其他网站

然后在Java代码中,您可以启用/禁用前景调度系统已经科技股,我设置了相同的科技股,因为我在XML中做这样的:

private void setUpForegroundDispatchSystem() 
    { 
     this.nfcAdapter = NfcAdapter.getDefaultAdapter(this); 

     this.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("*/*"); /* Handles all MIME based dispatches. 
              You should specify only the ones that you need. */ 
      ndef.addDataScheme("http"); 
     } 
     catch (MalformedMimeTypeException e) { 
      throw new RuntimeException("fail", e); 
     } 
     this.intentFiltersArray = new IntentFilter[] {ndef}; 
     this.techListsArray = new String[][] { new String[] { MifareUltralight.class.getName(), Ndef.class.getName(), NfcA.class.getName()}, 
               new String[] { MifareClassic.class.getName(), Ndef.class.getName(), NfcA.class.getName()}}; 

    } 

您必须启用和禁用此在暂停和恢复方法中。 希望这个信息可以帮助你。

+0

通过任何方式,有没有办法不添加我的技术列表在java文件中,并在发送挂起的意图时引用我的xml? – Android 2013-10-07 06:48:26

+0

@matiasnj你确定你的'AndroidManifest.xml'和'res/xml/nfc_tech_filter.xml'代码对于前台调度是必要的吗? – 2016-03-28 18:56:47

+0

老实说这个代码是从5年前,我没有尝试在新的android开发平台内​​。到了这个时候,当NFC越来越多时,答案是肯定的,你需要它们。 – matiasnj 2016-06-07 11:54:55

4

前台调度明确要求使用正确配置的Activity:它看起来不像您可以在AndroidManifest.xml中使用IntentFilter设置前台调度(您的应用程序实际上必须位于前台,即运行)。下面的代码似乎正常工作(我只是测试它)的情况下,你仍然有兴趣(ACTION_TAG_DISCOVERED是我在看的):

private NfcAdapter mAdapter; 
    private PendingIntent pendingIntent; 
    private IntentFilter[] mFilters; 
    private String[][] mTechLists; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

     setContentView(R.layout.main); 

     mAdapter = NfcAdapter.getDefaultAdapter(this); 
     pendingIntent = PendingIntent.getActivity(
      this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); 

    // Setup an intent filter for all MIME based dispatches 
     IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); 
     try { 
      ndef.addDataType("*/*"); 
     } catch (MalformedMimeTypeException e) { 
      throw new RuntimeException("fail", e); 
     } 
     IntentFilter td = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); 
     mFilters = new IntentFilter[] { 
       ndef, td 
     }; 

     // Setup a tech list for all NfcF tags 
     mTechLists = new String[][] { new String[] { 
       NfcV.class.getName(), 
       NfcF.class.getName(), 
       NfcA.class.getName(), 
       NfcB.class.getName() 
      } }; 
    } 

@Override 
    public void onResume() 
    { 
     super.onResume(); 

     mAdapter.enableForegroundDispatch(this, pendingIntent, mFilters, mTechLists); 
    } 

    @Override 
    public void onPause() 
    { 
     super.onPause(); 
     mAdapter.disableForegroundDispatch(this); 
    } 

    @Override 
    public void onNewIntent(Intent intent){ 
     // fetch the tag from the intent 
     Tag t = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 
     String tlist = getTechList(t); 
     android.util.Log.v("NFC", "Discovered tag ["+tlist+"]["+t+"] with intent: " + intent); 
     android.util.Log.v("NFC", "{"+t+"}"); 
} 
+0

它应该是'mTechLists = new String [] [] { new String [] {NfcF.class.getName()}, new String [] {NfcB.class.getName()}, new String [] { NfcA.class.getName()}, new String [] {NfcV.class.getName()}, };' – Jekton 2018-01-08 03:25:08