I want to simulate the touch event for my application. My manifest is like
<activity
android:name=".activity.TagActivity_"
android:label="@string/app_name"
android:launchMode="singleTask"
android:noHistory="true"
android:permission="android.permission.NFC"
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" />
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="ext"
android:pathPrefix="/abc:d"
android:scheme="vnd.android.nfc" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Question (1): I want to invoke my application from other application. How do I do that? My current code is like:
try {
final Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED);
NdefMessage ndefMessage = buildNdefMessage(getTagData());
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[] {ndefMessage});
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
But this is not invoking my application. probably because the data type and path prefix do not match. How do I pass this while starting the activity?
Question (2): For temp purpose I have added
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
to make it work, and my application is invoked. But while reading the tag I check the tag type, and since I am not passing any tag type, my app crashes. So how do I create a tag instance? There is no constructor for this. I mean I can't do Ndef ndef = new Ndef();
. And I don't basically have a tag so I can't event do Ndef ndef = Ndef.get(tag);
.
Regarding question (1): How to invoke NDEF_DISCOVERED
intent filter
Your activity ".activity.TagActivity_" filters has two different NDEF_DISCOVERED
. The first one matches if the intent contains a URI of the form "vnd.android.nfc://ext/abc:d". The second one matches if the intent contains a data type of "text/plain".
Consequently, you need to either add a matching URI or a matching MIME type to the intent that you use to start that activity.
MIME type "text/plain":
final Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED); intent.setType("text/plain"); startActivity(intent);
URI "vnd.android.nfc://ext/abc:d":
final Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED); intent.setData(Uri.parse("vnd.android.nfc://ext/abc:d")); startActivity(intent);
Any of the two will start your activity.
NOTE that you specified android:permission="android.permission.NFC"
for your receiving activity. You normally would not do that. Specifying this permission means that your sending application needs to have that permission.
Regarding question (2): How to pass a mock tag object?
It's possible to create a mock tag object instance using reflection (note that this is not part of the public Android SDK, so it might fail for future Android versions).
Get the
createMockTag()
method though reflection:Class tagClass = Tag.class; Method createMockTagMethod = tagClass.getMethod("createMockTag", byte[].class, int[].class, Bundle[].class);
Define some constants for preparing a valid mock NDEF tag instance:
final int TECH_NFC_A = 1; final String EXTRA_NFC_A_SAK = "sak"; // short (SAK byte value) final String EXTRA_NFC_A_ATQA = "atqa"; // byte[2] (ATQA value) final int TECH_NDEF = 6; final String EXTRA_NDEF_MSG = "ndefmsg"; // NdefMessage (Parcelable) final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength"; // int (result for getMaxSize()) final String EXTRA_NDEF_CARDSTATE = "ndefcardstate"; // int (1: read-only, 2: read/write, 3: unknown) final String EXTRA_NDEF_TYPE = "ndeftype"; // int (1: T1T, 2: T2T, 3: T3T, 4: T4T, 101: MF Classic, 102: ICODE)
Create an NDEF message:
NdefMessage ndefMessage = new NdefMessage(NdefRecord.createMime("text/plain"), "Text".getBytes("US-ASCII"));
Create the tech-extras bundle for a Type 2 tag with that NDEF message:
Bundle nfcaBundle = new Bundle(); nfcaBundle.putByteArray(EXTRA_NFC_A_ATQA, new byte[]{ (byte)0x44, (byte)0x00 }); //ATQA for Type 2 tag nfcaBundle.putShort(EXTRA_NFC_A_SAK , (short)0x00); //SAK for Type 2 tag Bundle ndefBundle = new Bundle(); ndefBundle.putInt(EXTRA_NDEF_MAXLENGTH, 48); // maximum message length: 48 bytes ndefBundle.putInt(EXTRA_NDEF_CARDSTATE, 1); // read-only ndefBundle.putInt(EXTRA_NDEF_TYPE, 2); // Type 2 tag ndefBundle.putParcelable(EXTRA_NDEF_MSG, ndefMessage); // add an NDEF message
Prepare an anti-collision identifier/UID for your tag (see
Tag.getId()
method). E.g. a 7-byte-UID for a Type 2 tag:byte[] tagId = new byte[] { (byte)0x3F, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, (byte)0x90, (byte)0xAB };
Then you can create a mock tag instance by invoking the
createMockTag()
methodTag mockTag = (Tag)createMockTagMethod.invoke(null, tagId, // tag UID/anti-collision identifier (see Tag.getId() method) new int[] { TECH_NFC_A, TECH_NDEF }, // tech-list new Bundle[] { nfcaBundle, ndefBundle }); // array of tech-extra bundles, each entry maps to an entry in the tech-list
Once you created that mock tag object, you can send it as part of the NDEF_DISCOVERED
intent:
Intent ndefIntent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndefIntent.setType("text/plain");
ndefIntent.putExtra(NfcAdapter.EXTRA_ID, tagId);
ndefIntent.putExtra(NfcAdapter.EXTRA_TAG, mockTag);
ndefIntent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[]{ ndefMessage });
Optionally, you can explicitly define your target activity as the receiving component:
ndefIntent.setComponent(...); // or equivalent
You can then send this intent to your activity:
startActivity(ndefIntent);
The receiver can then use the moch tag object to retrieve instances of the technology classes (e.g. Ndef.get(tag)
) but any method that requires IO operations will fail.
来源:https://stackoverflow.com/questions/28046115/how-to-simulate-the-tag-touch-from-other-application