Read a RFID/NFC Tag ID - java

I am trying to get a piece of code to be able to scan a Tag and display that tag in a TextView...
I have been getting really swamped down in this, any advice would be appreciated...
When I scan a tag, the noise for a tag being discovered is played... However the TextView is not updated... So the app can currently scan a tag, but it is not putting said tag ID in the TextView...
Java Main Class
package com.security.nfc;
import android.app.Activity;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.widget.TextView;
public class main extends Activity
{
#Override
protected void onCreate(Bundle b)
{
super.onCreate(b);
setContentView(R.layout.main);
}
public void onNewIntent(Intent intent)
{
Tag myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
TextView tagID = (TextView) findViewById(R.id.result);
tagID.setText("TagID: " + myTag.getId());
}
}
Android Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.security.nfc">
<application android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/ic_launcher"
android:theme="#style/AppTheme">
<activity
android:name="com.security.nfc.main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
</intent-filter>
</activity>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
</application>
<uses-permission android:name="android.permission.NFC" />
</manifest>

If you want to receive NFC tag discovery events while your activity is already visible in the foreground, you should register with the NFC foreground dispatch system. See Advanced NFC: Using the NFC Foreground Dispatch System. You would typically register using the NfcAdapter's enableForegroundDispatch() method. After that you can get the intents in your activity's onNewIntent() method (or as a pending intent result depending on how you register).

void onNewIntent (Intent intent)
This is called for activities that set launchMode to "singleTop" in their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity(Intent). In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
https://developer.android.com/reference/android/app/Activity.html#onNewIntent(android.content.Intent)

Related

Can't get NDEF_DISCOVERED action when opening the application with NFC tag

So I programmed an NFC tag to launch my application that I'm currently working on. I used the following service to do that:
https://play.google.com/store/apps/details?id=com.wakdev.wdnfc&hl=en
What I want to do is to switch from one activity to another whenever the NFC tag opens my application.
Under the manifest tag in my AndroidManifest.xml I have:
<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
And my MainActivity looks like this:
<activity android:name=".MainActivity">
<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:mimeType="text/plain" />
</intent-filter>
</activity>
Since the NFC tag opens the MainActivity first, I want to see whether it's been opened by NFC. If it has, switch to another activity.
The problem is that getIntent().getAction() always returns android.intent.action.MAIN while I'm expecting android.nfc.action.NDEF_DISCOVERED.
At the moment I'm performing this check (debugging basically) under onResume() method with the following code:
#Override
protected void onResume() {
super.onResume();
System.out.println(getIntent().getAction());
}
And I've tried performing this check under onCreate() and onStart() methods. All of them return android.intent.action.MAIN result while I expect android.nfc.action.NDEF_DISCOVERED.
I'm fresh in Android development and I'm just trying to make this work for a small prototype. Would appreciate if you guys could help me!
Edit: I got it working! I researched this question a lot and I believe that my NFC tag needed some extra data of a text/plain type (I did not specify this mimeType before as well so seems like it's mandatory). I also had put NDEF_DISCOVERED under LAUNCHER category while trying to debug the application and then changed it back to DEFAULT. I'm finally getting my desired results!
getIntent() returns the Intent that was used to create the activity. In your case, that is the home screen launcher Intent.
When you scan the NFC tag, a new Intent will be delivered to that activity. That Intent is passed to an onNewIntent() method that you can override.
Depending on how your activity is being used, you might need to handle both cases:
Where the user launched your app by scanning the NFC tag, so your activity was created with the NDEF Intent
Where the user launched your app by other means before scanning the NFC tag, so your activity was created with some other Intent and you get the NDEF Intent in onNewIntent()

The scope of loading a sub activity on onCreate()

I just need some information regarding the scope of execution. On my
To understand what is happening you need to know the Activity lifecycle
As you can see, when the app is launched, the first thing that's going to run is your onCreate() in this case, onCreate() has a method that inflates the view of your Activity, that method is called setContentView().
so, if you execute your code below setContentView, it will first inflate the view of MainActivity or the class you are in, and then just go to your other Activity.
If you want to start your Activity right when your app launches, just move your startActivity(...) above setContentView() in your onCreate(), but it will be better to do this in your manifest rather than just using a class to open another one.
To launch your WelcomeActivity just do this in your Manifest
<activity
android:name=".WelcomeActivity"
android:label="#string/app_name"
android:screenOrientation="sensorLandscape">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:screenOrientation="sensorLandscape"/>
<activity
So this
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
will define that WelcomeActivity executes first, then in WelcomeActivity do an intent to your MainActivity
Rather than load another activity within an activity, perhaps you should consider using a Fragment which are platform-defined modular sections of an activity with its own lifecycle and optional user-interface. See this for more info: https://developer.android.com/training/basics/fragments/fragment-ui
My advice would be to use support Fragments within your activity rather than another activity.

How to use non-main activity to capture custom url in unity game?

When someone clicks on a link in a webpage of form "com.foo.bar://testtest" I want it to open my unity game and for me to get the testtest data.
I'm an experienced programmer, but when it comes to android I kind of google my way around rather than really understanding anything. Bare that in mind. :)
I can react to links on android using intent-filters. However all the resources I've found have assumed you can extend your main activity to capture the new intent. It's possible to do that with unity, but for various reasons I'd rather not. I tried creating a new activity, exporting it to a jar, and adding this to my manifest in the application tag:
<activity android:name="com.foo.ProtocolCatcher"
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>
<data android:scheme="com.foo.bar" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
Clicking on a link successfully launches my game, but onto a black screen.
Edit: I've also tried this format to no change:
<activity android:name="com.foo.ProtocolCatcher"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="com.foo.bar" />
</intent-filter>
</activity>
What are the magic incantations to make the whole game boot, along with my custom activity, and let my custom activity read the incoming URL, without touching the main activity?
I suppose that you are missing a part of the boot sequence; the steps required are the following:
Define the ProtocolCatcher Activity with te proper scheme (OK)
Define the MainActivty, which represents your Unity3D game main Activity (OK)
Start the MainActivity when the ProtocolCatcher Activity gets started (MISSING)
Implementing the third step is super easy; just edit your ProtocolCatcher Activity's onCreate() method:
//ProtocolCatcher
//...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
Intent gameIntent = new Intent(this, MainActivity.class);
/*
//Pass the extra data to the game if needed
Intent sourceIntent = getIntent();
Uri data = sourceIntent.getData();
gameIntent.putExtra("uriData", data != null ? data.toString(): null);
*/
startActivity(gameIntent); //start the real game
finish(); //close the ProtocolCatcher activity
}
Considering the fact that you are "injecting" the ProtocolCatcher Activity manually, if you have problem to refer MainActivity from the ProtocolCatcher onCreate() you can lookup the relative Class using reflection.

getActionBar().setDisplayHomeAsUpEnabled(true) throws NullPointerException

This question is asked several times in stackoverflow and I have tried all of them. But unfortunately neither is working for me.
I am trying to implement the navigation between two activities, as part of learning Android app development. My minium SDK and target SDK versions are 11 and 21 (Android 5), respectively. My settings in AndroidManifest.xml are shown below:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.navigation"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DetailActivity" >
</activity>
</application>
</manifest>
I have two activities: MainActivity and DetailActivity. When I click a button in MainActivity, the app successfully opens the DetailActivity. But when I am trying to enable the back button by using the following code, it returns a NullPointerExcepion:
getActionBar().setDisplayHomeAsUpEnabled(true);
My both the classes extend ActionBarActivity.
In MainActivity.java:
public class MainActivity extends ActionBarActivity {
...
}
In DetailActivity.java:
public class DetailActivity extends ActionBarActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
getActionBar().setDisplayHomeAsUpEnabled(true); // returns null pointer
}
I have also tried changing the themes. For example, android:theme="#android:style/Theme.Holo.Light".
You are inheriting from ActionBarActivity. Hence, you need to use getSupportActionBar(), not getActionBar(), to get at the appcompat-v7-supplied action bar backport.
import v7:
import android.support.v7.app.ActionBar;
then in the onCreate method:
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
Use this..
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
instead of this - getActionBar().setDisplayHomeAsUpEnabled(true);
it will work perfectly.
Summay:
To make sure you won't get a NullPointerException.
You need to:
Import the right library target to you minium SDK version.
Use the right themes, just as the question owner said.
But in my situation an if statement is necessary to solve my App from crash. By the way, I'm using an AppCompatActivity to hold my view fragment.
public onCreateView(LayoutInflater inflater, final ViewGroup container,Bundle savedInstanceState){
View view = inflater.inflate(R.layout.list_fragment, container, false);
ActionBar actionBar = getActivity().getActionBar();
if (actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
}

Go back to the First/Main activity without reloading it

I am developing an android app. I need to call my MainActivity without reloading it as it has huge amount of data fetch from internet.
Suppose, I am on third activity now and I want to go back to MainActivity.
If I use:
Intent i = new Intent(Third.this,Main.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
it will load MainActivity but I don't want to reload it. like from Second Activity I call finish() and it does exactly want i need.
This is how to do it:
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
metntion it in your AndroidManifest.xml file
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation">
do nothing inside the method onResume() and onstart() when coming back to this activity
and try intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); instead of addFlags() method
In Third activity when you want to go to first activity, put finish() mwthod there.
In Second activity, after onCreate() method, put
#Override
public void onResume(){
super.onResume();
finish();
}
I think this code will work for you, jus try it.
Try adding this to your manifest:
android:configChanges="keyboard|keyboardHidden|orientation">
add this line to the activity in your manifest like this:
<activity android:name=".Main"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Categories