0

my application basically just taking the Tag ID of any Tags

I want the application to run without asking the user what application to use

Directly from the same app

I found a tutorial in internet on how to develop an NFC writer and reader

but every time I tap the system will ask the user to choose an application (EVEN if I closed the application)

because I'm going to create different activities for different implementation so by using the same method Android System will ask the user to choose many applications (they all are my app Activities)

this is my Code:-

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>
-->
ahmadssb
  • 95
  • 2
  • 13

3 Answers3

0

The only thing I know so far is the implementation of AARs (Android Application Records). These are NDEF messages in your tags, which only starts the application given in the AAR. That works pretty well. However, you have to implement NDEF indents. There are some AAR writers in the Android market you can try out.

pizzaani
  • 332
  • 1
  • 9
0

Actually I found a solution thanks to my friend

this is his Answer:

maybe you should change the 'filter' and 'techlist' to null

Your code:

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

Change to

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

Reference:

If any IntentFilters are provided to this method they are used to match dispatch Intents for both the ACTION_NDEF_DISCOVERED and ACTION_TAG_DISCOVERED. Since ACTION_TECH_DISCOVERED relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled by passing in the tech lists separately. Each first level entry in the tech list represents an array of technologies that must all be present to match. If any of the first level sets match then the dispatch is routed through the given PendingIntent. In other words, the second level is ANDed together and the first level entries are ORed together.

If you pass null for both the filters and techLists parameters that acts a wild card and will cause the foreground activity to receive all tags via the ACTION_TAG_DISCOVERED intent.

Source:

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

ahmadssb
  • 95
  • 2
  • 13
0

I decompile one of google play apk and make this code:

  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;
    }
  }

Don't forget add permission:

<uses-permission android:name="android.permission.NFC" />
Alexmelyon
  • 1,168
  • 11
  • 18