0

I have an app with 2 classes, I need my app to open the second class CardActivity when the NFC tag tapped/swiped. The app opens fine, but MainActivity is run, instead of CardActivity.

I would hazard a guess that this is an issue with my manifest, but it looks correct. Here it is regardless:

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

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

    <uses-permission android:name="android.permission.NFC" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

         <activity
            android:name=".CardActivity"
            android:label="@string/app_name" >

            <!-- Handle a collectable card NDEF record -->
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
                <data android:mimeType="application/vnd.spotsofmagic.spotsofmagic"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
         </activity>

    </application>

</manifest>

I'm confident the tag itself is correct, as I have opened it in another app to view it's contents.

Below are the two classes.

CardActivity:

package com.spotsofmagic.spotsofmagic;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.bluetooth.*;

public class CardActivity extends Activity implements OnClickListener {

    private static final String TAG = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.card_activity);

        // see if app was started from a tag and show game console
        Intent intent = getIntent();

        Log.e(TAG, "Hello world.  Intent Type: "+ intent.getType());

        if(intent.getType() != null && intent.getType().equals(MimeType.NFC_DEMO)) {
            Parcelable[] rawMsgs = getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            NdefMessage msg = (NdefMessage) rawMsgs[0];
            NdefRecord cardRecord = msg.getRecords()[0];
            String payload = new String(cardRecord.getPayload());
            turnBluetoothOn(payload);
        }
    }

    private void turnBluetoothOn(String payload) {

        final AlertDialog.Builder builder=new AlertDialog.Builder(this);
        builder.setTitle("Alert Dialog");
        builder.setMessage(payload);
        builder.setIcon(android.R.drawable.ic_dialog_alert);


        BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            // Device does not support Bluetooth
        }
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, 1);
        }
        android.os.Process.killProcess(android.os.Process.myPid());

    }

    public void onClick(DialogInterface dialog, int which) {
        // TODO Auto-generated method stub

    }
}

MainActivity:

package com.spotsofmagic.spotsofmagic;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.TextView;


public class MainActivity extends Activity implements OnClickListener {
    private static final String TAG = "Activity...";
    private NfcAdapter mAdapter;
    private TextView mTextView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        // grab our NFC Adapter
        mAdapter = NfcAdapter.getDefaultAdapter(this);

        // TextView that we'll use to output messages to screen
        mTextView = (TextView)findViewById(R.id.text_view);

        displayMessage("Loading payload...");

    }

    private void displayMessage(String message) {
        mTextView.setText(message);
    }

    public void onClick(DialogInterface arg0, int arg1) {
        // TODO Auto-generated method stub

    }
}

Here is the code I used to write the tag. This is done on a different app incidentally:

NdefRecord appRecord = NdefRecord.createApplicationRecord("com.spotsofmagic.spotsofmagic");

        // record that contains our custom "retro console" game data, using custom MIME_TYPE
        byte[] payload = getPayload().getBytes();
        byte[] mimeBytes = MimeType.NFC_DEMO.getBytes(Charset.forName("US-ASCII"));
        NdefRecord cardRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, 
                                                new byte[0], payload);
        NdefMessage message = new NdefMessage(new NdefRecord[] { cardRecord, appRecord});

// Some code here removed for readability


 Ndef ndef = Ndef.get(tag);
    if (ndef != null) {
        ndef.connect();
        ndef.writeNdefMessage(message);
NFC guy
  • 10,151
  • 3
  • 27
  • 58
Mike
  • 8,767
  • 8
  • 49
  • 103
  • package="com.spotsofmagic.spotsofmagic" Not sure if its the problem. You may want to change the subpackage name or package name so they are not the same. – wtsang02 Aug 30 '12 at 20:53
  • Not the issue, but definitely bad practice on my part. Will get that changed :) – Mike Aug 30 '12 at 21:19

1 Answers1

1

Does the NDEF message on the tag contain an Android Application Record? That could explain how MainActivity is launched. However, that can only be the cause if the AAR is the first record of the NDEF message on the tag or if the first record does not match the intent filter.

NFC guy
  • 10,151
  • 3
  • 27
  • 58
  • Yes, I'm using an Android Application Record. I have edited the question to include the code used to write the NFC tag – Mike Aug 30 '12 at 21:12
  • My guess would be that the MIME type in the intent filter ("application/vnd.spotsofmagic.spotsofmagic") is not identical to `MimeType.NFC_DEMO`. Then the intent filter does not match, which causes MainActivity to be launched (by the AAR). – NFC guy Aug 30 '12 at 21:20
  • You're absolutely right. `MimeType.NFC_DEMO` was set to the writer app, rather than the reader. Thanks for your help :) – Mike Aug 30 '12 at 21:25