【问题标题】:NFC Tag start without asking the user what application to useNFC Tag 无需询问用户使用什么应用程序即可启动
【发布时间】:2014-04-02 10:26:34
【问题描述】:

我的应用程序基本上只是获取任何标签的标签 ID

我希望应用程序在不询问用户使用什么应用程序的情况下运行

直接来自同一个应用

我在网上找到了一个关于如何开发 NFC 读写器的教程

但每次我点击系统都会要求用户选择一个应用程序(即使我关闭了应用程序)

因为我要为不同的实现创建不同的活动,所以通过使用相同的方法Android系统会要求用户选择许多应用程序(它们都是我的应用程序活动)

这是我的代码:-

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.nfc.test"
    android:versionCode="1"
    android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="19" />

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.NFC" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        <activity android:name=".TapToRegisterTag" android:screenOrientation="portrait">
            <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" />
        </activity>

        <!-- Other Activities -->

    </application>

</manifest>

TapToRegisterTag.java

package com.nfc.test;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class TapToRegisterTag extends Activity{

    // Prepare NFC Tag variables
    Tag myTag;
    String tagID;
    NfcAdapter mNfcAdapter;
    public static final String MIME_TEXT_PLAIN = "text/plain";
    public static final String TAG = "NfcDemo";

    ImageView logo;
    TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.register_tag_layout);

        logo = (ImageView)findViewById(R.id.imageView2);
        txt = (TextView)findViewById(R.id.textView);

        // prepare NFC
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        if (mNfcAdapter == null) {
            // Stop here, we definitely need NFC
            Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
            finish();
            return;

        }

        if (!mNfcAdapter.isEnabled()) {
            Toast.makeText(this, "NFC is disabled.", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "NFC is Enabled.", Toast.LENGTH_LONG).show();
        }

        handleIntent(getIntent());
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();

        /**
         * It's important, that the activity is in the foreground (resumed). Otherwise
         * an IllegalStateException is thrown. 
         */
        setupForegroundDispatch(this, mNfcAdapter);
        try{
            this.myTag = (Tag) getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
            this.tagID = OnetapActivity.bytesToHex(myTag.getId());
            Toast.makeText(this, "Tag ID: \n" + tagID, Toast.LENGTH_LONG).show();
        }catch (Exception ex){
            Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show();
        }
    }


    @Override
    protected void onPause() {

        stopForegroundDispatch(this, mNfcAdapter);

        super.onPause();
    }

    @Override
    protected void onNewIntent(Intent intent) { 

        handleIntent(intent);

    }

    private void handleIntent(Intent intent) {
        // TODO: handle Intent

        String action = intent.getAction();
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

            String type = intent.getType();
            if (MIME_TEXT_PLAIN.equals(type)) {

                //new NdefReaderTask().execute(tag);
                try{
                    this.myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                    this.tagID = OnetapActivity.bytesToHex(this.myTag.getId());
                    Toast.makeText(this, "Tag ID: \n" + tagID, Toast.LENGTH_LONG).show();
                }catch (Exception ex){
                    Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show();
                }

            } else {
                Log.d(TAG, "Wrong mime type: " + type);
            }
        } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {

            // In case we would still use the Tech Discovered Intent
            this.myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            String[] techList = this.myTag.getTechList();
            String searchedTech = Ndef.class.getName();

            for (String tech : techList) {
                if (searchedTech.equals(tech)) {
                    //new NdefReaderTask().execute(tag);

                     try{
                         myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                         //this.myTag = (Tag) getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
                         this.tagID = OnetapActivity.bytesToHex(myTag.getId());
                         Toast.makeText(this, "Tag ID: \n" + tagID, Toast.LENGTH_LONG).show();
                     }catch (Exception ex){
                         Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show();
                     }

                    break;
                }
            }

        }

    }

    public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
        final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);

        IntentFilter[] filters = new IntentFilter[1];
        String[][] techList = new String[][]{};

        // Notice that this is the same filter as in our manifest.
        filters[0] = new IntentFilter();
        filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
        filters[0].addCategory(Intent.CATEGORY_DEFAULT);
        try {
            filters[0].addDataType(MIME_TEXT_PLAIN);
        } catch (MalformedMimeTypeException e) {
            throw new RuntimeException("Check your mime type.");
        }

        adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
    }


    public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
        adapter.disableForegroundDispatch(activity);
    }

}

@xml/nfc_tech_filter.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.Ndef</tech>
        <!-- class name -->
    </tech-list>
</resources>

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

【问题讨论】:

    标签: android android-intent nfc open-nfc


    【解决方案1】:

    到目前为止,我唯一知道的是 AAR(Android 应用程序记录)的实现。这些是标签中的 NDEF 消息,仅启动 AAR 中给出的应用程序。这很好用。但是,您必须实现 NDEF 缩进。 Android 市场上有一些 AAR 编写器您可以尝试。

    【讨论】:

      【解决方案2】:

      其实多亏了我的朋友,我找到了解决办法

      这是他的回答:

      也许您应该将“过滤器”和“技术列表”更改为空

      您的代码:

      adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
      

      改成

      adapter.enableForegroundDispatch(activity, pendingIntent, null, null);
      

      参考:

      如果向此方法提供了任何 IntentFilter,它们将用于匹配 ACTION_NDEF_DISCOVERED 和 ACTION_TAG_DISCOVERED 的调度 Intent。由于 ACTION_TECH_DISCOVERED 依赖于 IntentFilter 之外的元数据,因此该调度 Intent 是通过单独传入技术列表来处理的。技术列表中的每个第一级条目代表必须全部存在才能匹配的一系列技术。如果任何第一级集匹配,则调度通过给定的 PendingIntent 进行路由。换句话说,第二级是 AND 一起,第一级条目是 OR 一起。

      如果您为过滤器和 techLists 参数都传递了 null,这些参数充当通配符,并将导致前台活动通过 ACTION_TAG_DISCOVERED Intent 接收所有标签。

      来源:

      http://developer.android.com/reference/android/nfc/NfcAdapter.html#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][])

      【讨论】:

        【解决方案3】:

        我反编译了一个 google play apk 并制作了这段代码:

          public static void resume(Context con, Activity _activity) {
            NfcAdapter _nfcAdapter = NfcAdapter.getDefaultAdapter(con);
            if (!_isReceiveIntentEnabled) {
              if (_nfcAdapter != null) {
                _nfcAdapter.setNdefPushMessage(null, _activity, new Activity[0]);
                NfcAdapter localNfcAdapter = _nfcAdapter;
                Activity localActivity = _activity;
                int flag = PendingIntent.FLAG_NO_CREATE; // 536870912;
                Intent intent = new Intent(_activity, _activity.getClass()).addFlags(flag);
                PendingIntent localPendingIntent = PendingIntent.getActivity(_activity, 0, intent, 0);
                IntentFilter[] arrayOfIntentFilter = new IntentFilter[] { new IntentFilter("android.nfc.action.TECH_DISCOVERED") };
                String[][] techArr = new String[][] { new String[] { IsoDep.class.getName() } };
                localNfcAdapter.enableForegroundDispatch(localActivity, localPendingIntent, arrayOfIntentFilter, techArr);
              }
              _isReceiveIntentEnabled = true;
            }
          }
        
          public static void pause(Context con, Activity _activity) {
            NfcAdapter _nfcAdapter = NfcAdapter.getDefaultAdapter(con);
            if (_isReceiveIntentEnabled) {
              if (_nfcAdapter != null) {
                _nfcAdapter.disableForegroundDispatch(_activity);
              }
              _isReceiveIntentEnabled = false;
            }
          }
        

        别忘了添加权限:

        <uses-permission android:name="android.permission.NFC" />
        

        【讨论】:

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