Possibility for Fake NFC(Near Field Communication) Launch - android

I am working on Near Field Communication for reading data from NFC Tags.
I don't have NFC supported Android Mobile and NFC Tags to test the Application i created .
I want to know whether it is possible to Launch my App through intent filter(Should assume NFC tag is detected from my device)
My Manifest Snippet :
<activity
android:name=".ServerActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="abc.com"
android:pathPrefix="/aaap"
android:scheme="http" />
</intent-filter>
</activity>
My Activity Snippet :
#Override
protected void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
Toast.makeText(getApplicationContext(), "ACTION_TAG_DISCOVERED",
Toast.LENGTH_LONG);
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
}

I may be completely missing the point here, but from what I understood, you basically want to fire off an intent that will get picked by the receiver you declared in your manifest, right? Have you tried setting up a very simple test app that does exactly this using the sendBroadcast(...) method?
Intent exampleIntent = new Intent("android.nfc.action.NDEF_DISCOVERED");
sendBroadcast(exampleIntent)
You can add any extra data to the Intent per your requirements.

After some research on NFC i found that we can read/write NFC Tags without NFC enabled device.. But answer is so simple.. It's nothing but playing with Intents :
We have to call this snippet for invoking NFC :
final Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED);
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, "Custom Messages");
startActivity(intent);
Also we should register our Activity to Android System through Manifest file like below :
Manifest.xml
<activity
android:name="TagViewer" >
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Same way if you have more than one Activity using same action we will be getting chooser from which we can launch our Desired Activity.
Receiving inside Activity :
TagViewer .java
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
Log.v("NFC Launched","NFC Launched");
}
We have this sample in Developer Sample Demo.

Have a look at Open NFC. They have a NFC simulator that migh be useful to attach to your android simulator. Never used it with Android, but I've used it with BlackBerry simulators.
EDIT:
Last version 4.4.1 for Android ICS released.

Related

Reading/Handling NFC Tags without activity [duplicate]

This question already has answers here:
Get NFC tag with NDEF Android Application Record (AAR)
(2 answers)
Closed 7 years ago.
I got to solve the following problem (if its even possible):
I'm working on an Android app, which loads information from the internet, corresponding to the scanned NFC tag.
As long as the activity is in foreground, I receive the intent with the action ACTION_TAG_DISCOVERED (through the foreground dispatch system), get the NFC ID of the intent and proceed.
But it was requested, to show the information form the scanned tag directly, even if the activity is not yet in the foreground.
Starting/Brining the app back to foreground works by writing the package name in an Android Application Record (AAR) to the NFC tag, but I'm not receiving the intent with the ID of the tag, without scanning the tag a second time, after the activity was opened.
Is there any possibility to start an activity and get the tag ID of the NFC tag by scanning an NFC tag only once?
All sources I researched now said, that an activity running in foreground is required to obtain the intent, containing the ID of the scanned tag.
EDIT:
Trying to explain my problem more exactly. What I got yet:
<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.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc" />
</intent-filter>
My Activity:
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
if (intent.getByteArrayExtra(NfcAdapter.EXTRA_ID) != null) {
byte[] TagId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)
…
}
}
}
This works fine, as long as the activity is running.
Now, the activity is in background or was not created yet.
I scan an NFC tag, and the activity starts, because the package was written to this NFC tag. After starting, the ID of the scanned tag should be available, without scanning the tag an second time
I'm not sure I understand what problem you are having but I have used NFC tags in the past this way.
Put this intent-filter on your Activity in the manifest:
<activity
android:name=".LibraryActivity"
android:label="#string/title_activity_library" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="myapp"
/>
</intent-filter>
</activity>
note: you'll have to change "myapp" to whatever scheme your NFC tags use
Then inside your activity you should be able to do something like this to get the data from your tag:
public void onNewIntent(Intent intent) {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//do something with tagFromIntent
}
This will launch your activity even if it wasn't running before.

Launch Specific App when NFC is discovered

I am using NFC in my app and it is working fine. However I want to make sure that only my app is launched and no other App is there to handle the intent. Following is the code for it in my Manifest file:
<activity android:name="com.mypackage.name.BeamActivity">
<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>
I have another sample app on my phone which is detecting NFC Intent and providing me Intent Chooser. Following is the code for it in Manifest file.
<activity android:name="com.package2.name.NFCStickyNotesActivity" android:label="Sticky Notes" >
<!-- Handle notes detected from outside our application -->
<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>
I would like my App to be the only app to handle the particular NFC Intent when my App push it across from another device.
I am not sure whether I have to do something specific in the manifest file or in the code. Any help is appreciated.
The reason why you get an intent chooser is that multiple activities are registered for the data type text/plain. This is a rather common case and you should therefore avoid using such generic data types for the NDEF record that should launch your activity. You have two options to overcome this problem:
Use an NFC Forum external type for your NDEF record (this is what ThomasRS already mentioned). With this method you create a custom record type that is meaningful to your application only. You can create such a record (to write it to your tag or to send over Beam) with something like this:
NdefRecord extRecord = NdefRecord.createExternal(
"yourdomain.com", // your domain name
"yourtype", // your type name
textBytes); // payload
You can then register your activity to launch upon this record like this:
<activity ...>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc" android:host="ext"
android:pathPrefix="/yourdomain.com:yourtype" />
</intent-filter>
</activity>
Use an Android Application Record (AAR). An AAR will make sure that the NDEF_DISCOVERED intent is delivered to an app with a specific package name only. You can create such a record (to write it to your tag or to send over Beam) with something like this:
NdefRecord appRecord = NdefRecord.createApplicationRecord(
"com.yourdomain.yourapp");
NdefRecord textRecord = NdefRecord.createTextRecord(
"en", // language code
"yourtext" // human-readable text);
NdefMessage msg = new NdefMessage(
textRecord,
appRecord); // use the AAR as the *last* record in your NDEF message
Use the External Type NDEF record with your own domain and give your app a corresponding intent-filter.

OnNewIntent through external class

I am developing an application for NFC.
On the tags, we have an application record, what is starting our application, and a text record, what has an id. When my app is reading the textrecord, send a request through the net to our server, get the response, and do things, like show buttons, doesn't matter.
When i started to learn android, i learned, there is a good thing to use a general engine, what has a lot of tool for myself, so when i need a new app, i can reuse my engine functions.
So, i've created this GameEngine class as a separated project.
I tried it without TAG_DISCOVERED filter, also tried when i've give not the text/plain mime type, but my application.
package GameEngine;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public abstract class GameEngine extends Activity {
private final String TAG = "DH GAME ENGINE";
/**************************************************
* Here are the override methods
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "Engine constructor");
super.onCreate(savedInstanceState);
init();
}
public abstract void init();
//MORE overrides here...
}
In my app, i have the init function. Here i set up the layout, set some flags.
In the onNewIntent method, i have this piece of code:
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
Log.d(TAG, "A tag was scanned!");
GEPhone.vibrate(this, 500);
tagSerial = GENFC.getTagId(getIntent());
}
It's works great. After this i read my id and parse it. I am using ndef-tools to parse the NDEF messages, but i think this is does not matter.
My problem is, when i am on the home screen, and my application is not running, when i first tap the NFC with the phone, my application is starting, but sadly, the onNewIntent method does not run.
I tried to search for it, i know, i am not the first who has this problem, and i read everywhere, i shoul add to this to the AndroidManifest.xml:
android:launchMode="singleTop"
No change.
Now, i also tried something else. I outsourced the whole thing from the onNewIntent into a handleIntent method, so my onNewIntent now seems like this:
#Override
public void onNewIntent(Intent intent) {
Log.d(TAG, "onNewIntent");
// Set the intent
setIntent(intent);
handleIntent(intent);
}
And i am also calling the this handleIntent from the init method.
But the result are the same.
If i am calling this handlentent from the init like this:
handleIntent(getIntent());
For some reason, this condition will be false.
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
....
}
What do i wrong?
PS: my other problem is, i can not debug this whole thing, because if i am clicking the debug button in the eclipse, it's starts the application, so i can not simulate, what happens (with breakpoints), when the application starts because of the NFC tag starts it.
Ps2: now logged, what is the action when i start the application and it is:
Main activity(29861): Action is: android.intent.action.MAIN
UPDATE
After some researching, and playing with the settings, now i realized the following:
If i am using this in manifest:
android:launchMode="singleTask"
and this filter:
<category android:name="android.intent.category.DEFAULT" />
<!-- <data android:mimeType="*/*" /> -->
<data android:mimeType="application/hu.sma.htdalpha" />
</intent-filter>
and data type is */*, then everything is work fine, except, all TAG is opening my application, even if there are only a text like "adsdasd".
If i am using my own package, then apllications open, and action will be android.intent.action.MAIN again.
UPDATE 2
As Michael asked, i copy here the AndroidManifest.xml.
The description above is a littlebit confusing. The point of the problem, as i read about it, that something not ok with the intents. The package name is ok, but every time, every where onCreate, onNewIntent, onStart, onResume, everywhere if i Log.d the getIntent().getAction(), will be android.intent.action.MAIN, and android.nfc.action.NDEF_DISCOVERED is never triggered. Only, if the application was started once.
The NDEF seems like this (see image)
The manifest is this.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="hu.sma.htdalpha"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="hu.sma.htdalpha.MainActivity"
android:label="#string/app_name"
android:launchMode="singleTask" >
<!--
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/hu.sma.htdalpha" />
</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>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
First of all, if you want your app to be started by your tag and want to receive the parsed NDEF message, your tag should contain the following:
An NDEF record that you want to filter upon as the first record of the NDEF message (you can only create intent-filters for the very first NDEF record on an NFC tag). In your case this would be the Text record. However, you might want to consider using an NFC Forum external type record with your custom application-specific type name instead (see here. The Text record should only be used if it contains human-readable non-interpreted text.
If you want to make sure that only your app is started with the tag and that your app's Play Store page is automatically opend if the user does not have the app installed, you can use an Android Application Record (AAR). This record should be the last record in the NDEF message. An AAR will be honored regardless of the position in the NDEF message.
Next, you have to create an appropriate intent filter for the activity that should receive the tag dicovery event and the NDEF message that triggered it:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
Or if you used your custom NFC Forum external type:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/yourdomain.com:yourtypename"/>
</intent-filter>
If your app does not have a matching intent filter and your tag contains an Android Application Record, the first activity declared in your manifest that has an intent filter for android.intent.action.MAIN and with android.intent.category.LAUNCHER will be started and as it does not declare to expect an NFC intent it will be passed the android.intent.action.MAIN. That's what happened in your case.
Next, in your activity, you can receive the NFC intent (with getIntent()) in onCreate(), onStart(), etc. and forward it to your handleIntent(...) method. As you filtered for NDEF_DISCOVERED, you will receive an NDEF_DISCOVERED intent. Thus you would use something like this:
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
// do something
}
If you want to receive further NFC intents while your activity is already in the foreground, you can handle them in onNewIntent(). This method will only be called if you added the proper launchMode to your activity). Better yet you can register for the foreground dispatch to give your activity priority for receiving NFC events.
Finally, you should normally not use the TAG_DISCOVERED intent in your manifest. This intent filter is meant as a fallback (if no other app's NFC intent filter matches) and to be backward compatible to the first edition of the NFC API (in Android 2.3). Moreover it is used for the catch-all version of the foreground dispatch.

Reading a QR-Code with URI -> BroadcastReceiver ignored, while Activity works fine

I'm trying to receive a simple custom intent, based on my wn URI.
Here is my manifest:
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.intenttest.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>
<receiver
android:name="com.example.intenttest.TestReceive"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="testo" />
</intent-filter>
</receiver>
</application>
My receiver is extremely simple:
public class TestReceive extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
Log.d("", "YAY!!!!!");
Toast.makeText(context, "TEST!!!", Toast.LENGTH_LONG).show();
}
}
When I try browsing to testo://blahblah, or fir this intent via URI Launer my receiver is not being fired.
Here is the code to simulate firing the intent from a different app:
String url = "testo://test/test";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
sendBroadcast( i );
But when I move the <intent-filer> block to the <activity> tag in the manifest, the activity IS being fired.
How can I make my receiver receive the intent?
If you are trying to dynamically register a receiver you should do so programmatically. This example by Eric Nordvik will server you well!
Now, the main reason to do it this way is because it is straight forward. The downside is that you won't be able to receive broadcasts when your application's lifecycle is not currently active (paused, stopped).
Update: As read in the comments, the OP requires to receive broadcasts independent of the lifecycle of the activity. I would urge anyone to rethink his design and only then decide if it is really needed.
As specified by the official documentation, android:name is used to designate the name of the class that implements the BroadcastReceiver. Omitting it in your code means that the Activity itself will receive the broadcast. I believe your issue is that you did not fully qualify it by android:name but referred to it as name. Fixing it should also fix your problem!
Update: The OP has since corrected a typo and this is not the issue. At this point, my best guess is either that the broadcast is generated wrongly or that the reference to the BroadcastReceiver should use the shorthand notation android:name=".NameOfReceiverClass".
OK - This whole issue was probably caused by me taking the wrong approach.
The sample code for sending the intent DOES work and does initiate my receiver.
So it appears that most QR Readers in the market do not fire an intent with the QR-read URI, as in my sample code, but rather look for an Activity that should respond to it and then call it directly.
I have no idea why is this the case.
The solution was to create a silent Activity, that handles what the BroadcastReceiver was supposed to handle.
Oy vey.

Android NFC Intents are not starting my activity

I am trying to write a simple application to interact with NFC tags, but I cant seem to get my phone to do anything but trigger the default NFC tag app. I really just want to be able to intercept any tag I scan, determine if it has some data on it, and take action accordingly.
Right now my manifest file looks like
<uses-sdk android:minSdkVersion="10" />
<uses-feature android:name="android.hardware.nfc" android:required="true"/>
<uses-permission android:name="android.permission.NFC"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".NfcActivity"
android:label="#string/app_name">
<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.NDEF_DISCOVERED"/>
</intent-filter>
</activity>
</application>
However when scanning an NFC tag, I never see the activity start. Am I missing something here? I tried placing the intent filter inside a BroadcastReceiver and had no luck either...
You cannot have your app started by all NFC tags you scan. Android will determine what the most suitable app is based on how specific the intent filter is. However, if your app is running in the foreground, you can use NFC foreground dispatch to catch all NFC intents.
In onCreate() add:
mAdapter = NfcAdapter.getDefaultAdapter(this);
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
In onResume() add:
mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
In onPause() add:
mAdapter.disableForegroundDispatch(this);
In onNewIntent you can get at the NFC tag like this:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
The SDK docs show this as a basic example.
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
You are expecting the tags to be defined in NDEF format. So your program will only be launched if the tags being read is in NDEF format.
You can try more generic intent filters like TAG_DISCOVERED or TECH_DISCOVERED.
Android automatically choses the most relevant application to handle the scanned NFC tag. You need to be more specific in your intent-filter, i.e. only listen for TEXT-Tags, URL-Tags, or CONTACT-Tags. This can be done by further specifying the filter, using, your example, <data android:mimeType="text/plain" /> for TEXT-Tags. Otherwise, the default NFC-Tag app will be triggered.

Categories

Resources