Using gcm to update an ImageView in a ListView - java

So here is my problem, what I'm trying to do is the following:
I have a simple ListView class that gets the item info (name of the item) from a MySql DB via PHP script and that works fine.
The other part of the ListView item is a ImageView. It represents 3 states the item can be in. A picture of a green "traffic light" means 'its OK', a red one, its 'not OK' and a grey one means 'service not available'. The state change trigger comes from an other app (via gcm) and the message contains a value of -1, 0 or 1 which I want to use to trigger the ImageView changes.
Here is my onCreate method for my Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_channel_list);
mRegistrationProgressBar = (ProgressBar) findViewById(R.id.registrationProgressBar);
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
mRegistrationProgressBar.setVisibility(ProgressBar.GONE);
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(context);
boolean sentToken = sharedPreferences
.getBoolean(SENT_TOKEN_TO_SERVER, false);
if (sentToken) {
Log.i(TAG, getString(R.string.gcm_send_message));
} else {
Log.i(TAG, getString(R.string.token_error_message));
}
}
};
// Registering broadcast receiver
registerReceiver();
if (checkPlayServices()) {
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
/*----------------------------------------------------------------------------------------*/
/*---------------------------------AsyncTask that makes the ListView ---------------------*/
/*----------------------------------------------------------------------------------------*/
PostResponseAsyncTask taskRead = new PostResponseAsyncTask(ChannelList.this, this);
taskRead.execute(SERVER_ADDRESS + "Script.php");
BindDictionary<Channel> dict = new BindDictionary<Channel>();
dict.addStringField(R.id.tvName, new StringExtractor<Channel>() {
#Override
public String getStringValue(Channel channel, int position) {
return channel.channel_name;
}
});
FunDapter<Channel> adapter = new FunDapter<>(
ChannelList.this, channelList, R.layout.layout_list, dict);
lvChannel = (ListView) findViewById(R.id.lvChannels);
lvChannel.setAdapter(adapter);
/*----------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------*/
}
Then I have the GcmListenerService class:
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
/**
* Called when message is received.
*
* #param from SenderID of the sender.
* #param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
String commercial = data.getString("commercial");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
Log.d(TAG, "Commercial: " + commercial);
if (from.startsWith("/topics/")) {
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, ChannelList.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent, // 0 => Request code
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 , notificationBuilder.build()); // 0 => ID of notification
}
}
Then I have the RegistrationIntentService class:
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegIntentService";
private static final String[] TOPICS = {"global"};
public static final String SENT_TOKEN_TO_SERVER = "sentTokenToServer";
public static final String REGISTRATION_COMPLETE = "registrationComplete";
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
// [START register_for_gcm]
// Initially this call goes out to the network to retrieve the token, subsequent calls
// are local.
// R.string.gcm_defaultSenderId (the Sender ID) is typically derived from google-services.json.
// See https://developers.google.com/cloud-messaging/android/start for details on this file.
// [START get_token]
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
// [END get_token]
Log.i(TAG, "GCM Registration Token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(token);
// Subscribe to topic channels
subscribeTopics(token);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(SENT_TOKEN_TO_SERVER, true).apply();
// [END register_for_gcm]
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
/**
* Persist registration to third-party servers.
*
* Modify this method to associate the user's GCM registration token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
/**
* Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
*
* #param token GCM token
* #throws IOException if unable to reach the GCM PubSub service
*/
// [START subscribe_topics]
private void subscribeTopics(String token) throws IOException {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
for (String topic : TOPICS) {
pubSub.subscribe(token, "/topics/" + topic, null);
}
}
// [END subscribe_topics]
}
The InstanceIDListenerService:
public class MyInstanceIDListenerService extends InstanceIDListenerService {
private static final String TAG = "MyInstanceIDLS";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. This call is initiated by the
* InstanceID provider.
*/
// [START refresh_token]
#Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
// [END refresh_token]
}
And the AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tumex.useralpha"
xmlns:tools="http://schemas.android.com/tools"
>
<uses-permission android:name="android.permission.INTERNET"/>
<!-- [START gcm_permission] -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- [END gcm_permission] -->
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="#android:icon"
>
<activity android:name=".Login">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ChannelList"></activity>
<!-- [START gcm_receiver] -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="gcm.play.android.samples.com.gcmquickstart" />
</intent-filter>
</receiver>
<!-- [END gcm_receiver] -->
<!-- [START gcm_listener] -->
<service
android:name="com.tumex.useralpha.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- [END gcm_listener] -->
<!-- [START instanceId_listener] -->
<service
android:name="com.tumex.useralpha.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<!-- [END instanceId_listener] -->
<service
android:name="com.tumex.useralpha.RegistrationIntentService"
android:exported="false">
</service>
</application>
So how do I go about this, make a ImageView react to values received from gcm message? If I have forgotten anything that can be helpful in solving my problem please let me know. Thank you

I suppose you want to update ImageView in ListView only if Activity with this ListView is showing.
In that case use LocalBroadcastManager:
YourActivity.java
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//int for List, String for Dictionary
String item_id_or_name = intent.getExtra("ITEM_ID_OR_NAME");
int status_for_item = intent.getExtra("ITEM_STATUS");
//find this item in you List or Dictionary
//and set new Status for this item
yourAdapter.notifyDataSetChanged();
}
};
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(YourActivity.this).registerReceiver(receiver,
new IntentFilter("FILTER_NAME"));
}
#Override
public void onPause() {
LocalBroadcastManager.getInstance(YourActivity.this).unregisterReceiver(receiver);
super.onPause();
}
YourGcmListenerService.java:
#Override
public void onMessageReceived(String from, Bundle data) {
//...parse received data
Intent updateStatus = new Intent("FILTER_NAME");
updateStatus.putExtra("ITEM_ID_OR_NAME", id_or_name);
updateStatus.putExtra("ITEM_STATUS", item_status);//-1, 0, 1
LocalBroadcastManager.getInstance(this).sendBroadcast(updateStatus);
//...
}

Related

WorkManager only executing periodic enqueued tasks when app opened

My app requires that a notification be sent twice a day. For testing purposes, I have shortened this time to 1 hour. This, of course, must be done in the background/when app is closed, so I have already tried AlarmManager and that did not work. I have therefore switched to WorkManager. someone suggested that I use periodicWork to accomplish my task but here is the issue:
WorkManager only executes all periodic work when the app is open
Another weird thing: If I leave the app alone for 3 hours, I will get way more than three notifications when I open the app.
I know for a fact that WorkManager is not executing because I have instantiated a Date Object whenever doWork() is called, and that timestamp from the date object is printed to the notification. This printed time will ALWAYS show as the time I have opened the app, meaning all of the queued work requests were executed at once when I opened the app.
Here is what is used to set the alarm. Note that cancelAlarm() does not cancel the alarm, but rather resets a shared preference I used for debugging
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter);
ToggleButton toggle = findViewById(R.id.toggleButton);
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
setAlarm();
} else {
cancelAlarm();
}
}
});
}
private void setAlarm() {
Constraints constraints = Constraints.NONE;
PeriodicWorkRequest testRequest = new PeriodicWorkRequest.Builder(ReminderWorker.class, 1, TimeUnit.HOURS)
.setConstraints(constraints)
.build();
WorkManager.getInstance().enqueueUniquePeriodicWork("ReminderWork", ExistingPeriodicWorkPolicy.KEEP, testRequest);
}
private void cancelAlarm() {
SharedPreferences savedSharedPreferences = getApplicationContext().getSharedPreferences("USER_PREFERENCES", Context.MODE_PRIVATE);
final SharedPreferences.Editor editor = savedSharedPreferences.edit();
editor.putInt("Test", 0);
editor.commit();
}
Here is the actual ReminderWorker class, I put a SHaredPreference variable to check the amount of times the worker fired, and a Date objectto check the time fired. These are printed in the notification.
public class ReminderWorker extends Worker {
int i;
public final String CHANNEL_ID = "MainChannel";
public ReminderWorker(#NonNull Context context, #NonNull WorkerParameters params) {
super(context, params);
}
#NonNull
#Override
public Result doWork() {
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
SharedPreferences savedSharedPreferences = getApplicationContext().getSharedPreferences("USER_PREFERENCES", Context.MODE_PRIVATE);
final SharedPreferences.Editor editor = savedSharedPreferences.edit();
i = savedSharedPreferences.getInt("Test", 0) + 1;
editor.putInt("Test", i);
editor.commit();
createNotificationChannel();
buildNotification(cal);
return Result.success();
}
private void createNotificationChannel() {
String name = "Birthday Notifications";
String description = "Reminds you when your friends birthday approaches";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
private void buildNotification(Calendar cal) {
Context context = getApplicationContext();
Intent openTap = new Intent(context, EnterActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, openTap, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
builder.setSmallIcon(R.drawable.pix_cake);
builder.setContentTitle("TestNotification");
builder.setStyle(new NotificationCompat.BigTextStyle()
.bigText("TestText" + i + " Time: " + cal.get(Calendar.HOUR) + ":" + cal.get(Calendar.MINUTE)));
builder.setPriority(NotificationCompat.PRIORITY_MAX);
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(i, builder.build());
//notificationManager.cancelAll();
}
}
In case it is needed, here is my AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myfirstapp">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SET_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:icon="#mipmap/main_icon"
android:label="#string/app_name"
android:roundIcon="#mipmap/main_icon_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".ListOfDaysActivity" />
<activity android:name=".MainActivity" />
<activity android:name=".EnterActivity"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
No errors thrown, just not the result expected. I need a notification to show up roughly every hour but that simply isn't happening.Any way around this?
Do you remove the application from task manager? Which device are you using for testing? There are some devices that force close the app and WorkManager tasks are rescheduled once you open the app again.
This answer might help you understand what is going on - https://stackoverflow.com/a/52605503/1313699

Why my alarm not working with BOOT_COMPLETED

My app work when my android is not restart but when I turn off my Android the app not working despite I add BOOT_COMPLETED.
I have looked for similar questions but all of them work just as I do, I do not know what is wrong
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.proyect.d.alarm">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SET_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<service android:name=".BootService" />
<receiver
android:name=".RestartAlarmsReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".MyAlarmReceiver"
android:process=":remote" />
</application>
RestartAlarmsReciver
public class RestartAlarmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent i = new Intent(context, BootService.class);
ComponentName service = context.startService(i);
}
}
}
BootService: it's equals that my main AlarmService
public class BootService extends IntentService {
public BootService(String name) {
super(name);
}
private NotificationManager notificationManager;
private final int NOTIFICATION_ID = 1010;
private AdminSQLiteOpenHelper admin;
private Cursor fila;
private SQLiteDatabase bd;
private String alarm, descrip, title;
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Calendar calenda = Calendar.getInstance();
int hour, min, day, m, year;
String cadenaF, cadenaH, date_system, time_system;
day = calenda.get(Calendar.DAY_OF_MONTH);
m = calenda.get(Calendar.MONTH) + 1;
year = calenda.get(Calendar.YEAR);
hour = calenda.get(Calendar.HOUR_OF_DAY);
min = calenda.get(Calendar.MINUTE);
date_system = m + "-" + day + "-" + year + " ";
time_system = hour + ":" + min;
admin = new AdminSQLiteOpenHelper(getApplicationContext(), vars.bd, null, vars.version);
bd = admin.getWritableDatabase();
if (bd != null) {
fila = bd.rawQuery("SELECT * FROM alarma WHERE datea='" + date_system + "' AND timea= '" + time_system + "'", null);
if (fila.moveToFirst()) {
alarm = fila.getString(0);
title = fila.getString(1);
descrip = fila.getString(2);
triggerNotification(getApplicationContext(), title + "\n" + descrip);
}
}
bd.close();
}
private void triggerNotification(Context contexto, String t) {
Intent notificationIntent = new Intent(contexto, MainActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(contexto, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
long[] pattern = new long[]{2000, 1000, 2000};
NotificationCompat.Builder builder = new NotificationCompat.Builder(contexto);
builder.setContentIntent(contentIntent)
.setTicker("")
.setContentTitle("alarm ")
.setContentTitle("")
.setContentText(t)
.setContentInfo("Info")
.setLargeIcon(BitmapFactory.decodeResource(contexto.getResources(), R.drawable.ic_launcher_background))
.setSmallIcon(R.drawable.ic_launcher_background)
.setAutoCancel(true)
.setSound(defaultSound)
.setVibrate(pattern);
Notification notificacion = new NotificationCompat.BigTextStyle(builder)
.bigText(t)
.setBigContentTitle("example")
.setSummaryText("more example")
.build();
notificationManager = (NotificationManager) contexto.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notificacion);
}
}
Thanks
Can you change your receiver to add export and category?
<receiver android:name=".RestartAlarmsReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
As per official documentation
android:exported
Whether or not the broadcast receiver can receive messages from sources outside its application — "true" if it can, and "false" if not. If "false", the only messages the broadcast receiver can receive are those sent by components of the same application or applications with the same user ID.
The default value depends on whether the broadcast receiver contains intent filters. The absence of any filters means that it can be invoked only by Intent objects that specify its exact class name. This implies that the receiver is intended only for application-internal use (since others would not normally know the class name). So in this case, the default value is "false". On the other hand, the presence of at least one filter implies that the broadcast receiver is intended to receive intents broadcast by the system or other applications, so the default value is "true".
This attribute is not the only way to limit a broadcast receiver's external exposure. You can also use a permission to limit the external entities that can send it messages (see the permission attribute).
Hope this will help

Notification.Builder does not create a notification

Im trying to create a notification from an edittext and broadcast receiver. In my first Activity the user should input a message and push the broadcast button. I want to take that string and create a notification from it and open a new activity that displays the message. I am doing all the notification work in my broadcast receiver class.
I have looked around onlne at examples and other peoples code but im not sure what im not getting right. The application loads up just fine and the broadcast button sends the broadcast to the receiver and Logs the string but the notification is never created.
Thanks for any help.
Broadcast class that sends broadcast message:
public class BroadcastReceiverActivity extends Activity
{
EditText et;
Button btn1;
public static String BString = "HappyHemingway";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast_receiver);
et = (EditText)findViewById(R.id.et1);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String message = et.getText().toString();
send(message);
}
});
}
/*
* This function creates an intent and
* sends a broadcast from the message
* parameter passed in.
*/
protected void send(String msg)
{
Log.i("msg", msg);
Intent i = new Intent();
i.putExtra("message",msg);
i.setAction(BString);
sendBroadcast(i);
}
}
Receiver class that creates notification:
public class Receiver extends BroadcastReceiver
{
// #SuppressLint("NewApi")
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action!=null&&action.equals("HappyHemingway"))
{
String msg = intent.getStringExtra("message");
Log.i("Received",msg);
Intent i = new Intent(context,ViewNotification.class);
i.putExtra("message",msg);
PendingIntent pi = PendingIntent.getActivity(context, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context).
setSmallIcon(0).setAutoCancel(true).setTicker(msg).
setWhen(System.currentTimeMillis()).setContentTitle("New Notification!").
setContentText(msg).setContentIntent(pi);
NotificationManager mgr = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = builder.build();
mgr.notify(0, n);
Log.i("Received again",msg);
}
}
}
notification viewer class that is never launched
public class ViewNotification extends Activity
{
String text;
TextView txttext;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.viewnotification);
NotificationManager notificationmanager;
notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationmanager.cancel(0);
Intent i = getIntent();
text = i.getStringExtra("message");
txttext = (TextView) findViewById(R.id.text);
txttext.setText(text);
Log.i("made it", "made it made it made it");
}
}
manifest
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".BroadcastReceiverActivity"
android:label="#string/app_name" >
<action android:name="android.intent" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<activity android:name=".ViewNotification"></activity>
<receiver android:name="Receiver">
<intent-filter>
<action android:name="HappyHemingway">
</action>
</intent-filter>
</receiver>
</application>
</manifest>
Hopefully its just a simple error I'm overlooking.This is my first time using Android Studio instead of Eclipse but I dont see how that could make any difference under than my unfamiliarity with the IDE.
Anything helps
thanks.
I'm not sure why I had setSmallIcon(0.)
When I changed it to setSmallIcon(R.drawable.ic_launcher) everything worked fine.

Login in Android app from web server and save registrationId of the device

I am very new in android and web services. I am trying to login into my android app where the data is coming from web service and at the same time I want to register the Id of android device using GCM in web server database. Until now I have done so far. If possible please give me your time to assets me.
Config.Java
public class Config {
static final String SERVER_URL = "http://example/stich/wsTest/?c=profile&func=login";
static final String GOOGLE_SENDER_ID = "499319758496";
static final String TAG = "GCM";
static final String DISPLAY_MESSAGE_ACTION = "com.google.android.gcm.demo.app.DISPLAY_MESSAGE";
static final String EXTRA_MESSAGE = "message";
}
Controller.java
public class Controller extends Application {
private final int MAX_ATTEMPTS = 5;
private final int BACKOFF_MILLI_SECONDS = 2000;
private final Random random = new Random();
/**
* Creating post request and store GCM RegistrationID, email and password in
* database on our web server for later use.
*
* #param context
* #param email
* #param password
* #param RegistrationID
*/
void register(final Context context, String email, String password,
final String RegistrationID) {
Log.i(Config.TAG, "registering device (RegistrationID = "
+ RegistrationID + ")");
String serverUrl = Config.SERVER_URL;
Map<String, String> params = new HashMap<String, String>();
params.put("androidToken", RegistrationID);
params.put("email", email);
params.put("password", password);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
// Once GCM returns a RegistrationID, we need to register on our server.
// As the server might be down, we will retry it a couple of times.
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(Config.TAG, "Attempt #" + i + "to register");
try {
// Send Broadcast to Show message on screen
displayMessageOnScreen(context, context.getString(
R.string.server_registering, i, MAX_ATTEMPTS));
// Post registration values to web server
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
// Send Broadcast to Show message on screen
String message = context.getString(R.string.server_registered);
displayMessageOnScreen(context, message);
return;
} catch (IOException e) {
// Here we are simplifying and retrying on any error; in a real
// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(Config.TAG, "Failed to register on attempt " + i + ":"
+ e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(Config.TAG, "Sleeping for " + backoff
+ " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(Config.TAG,
"Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return;
}
// increase backoff exponentially
backoff *= 2;
}
}
String message = context.getString(R.string.server_register_error,
MAX_ATTEMPTS);
// Send Broadcast to show message on screen
displayMessageOnScreen(context, message);
}
/**
* Unregister device from GCM server and also creating a post request on
* server to delete stored RegistrationID from database on our web server.
*
* #param context
* #param RegistrationID
*/
void unregister(final Context context, final String RegistrationID) {
Log.i(Config.TAG, "unregistering device (regId =" + RegistrationID
+ ")");
String serverUrl = Config.CLIPME_SERVER_URL + "/unregister";
Map<String, String> params = new HashMap<String, String>();
params.put("regId", RegistrationID);
try {
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, false);
String message = context.getString(R.string.server_unregistered);
displayMessageOnScreen(context, message);
} catch (IOException e) {
// At this point the device is unregistered from GCM, but still
// registered in the our server.
// We could try to unregister again, but it is not necessary:
// if the server tries to send a message to the device, it will get
// a "NotRegistered" error message and should unregister the device.
String message = context.getString(
R.string.server_unregister_error, e.getMessage());
displayMessageOnScreen(context, message);
}
}
/**
* Create HTTP Post request to server, requested url is defined in
* Config.java.
*
* #param endpoint
* #param params
* #throws IOException
*/
private void post(String endpoint, Map<String, String> params) throws IOException {
URL url;
try {
url = new URL(endpoint);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid url: " + endpoint);
}
StringBuilder bodyBuilder = new StringBuilder();
Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
// constructs the POST body using the parameters
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
bodyBuilder.append(param.getKey()).append('=')
.append(param.getValue());
if(iterator.hasNext()){
bodyBuilder.append('&');
}
}
String body = bodyBuilder.toString();
Log.v(Config.TAG, "Posting'" +body + "'to"+url);
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try{
Log.e("URL",">" + url);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
//Post the request
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
//handle the response
int status = conn.getResponseCode();
//If response is not success
if(status != 200){
throw new IOException("Get failed with error code" + status);
}
}finally{
if (conn != null){
conn.disconnect();
}
}
}
/**
* Checks internet connectivity.
* #return false
*/
public boolean isConnectingToInternet(){
ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if(connectivity != null){
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if(info != null){
for(int i = 0; i < info.length; i++)
if(info[i].getState() == NetworkInfo.State.CONNECTED);
{
return true;
}
}
}
return false;
}
/**
* Send broadcast to show message on activity, broadcast receiver mHandleMessageReceiver
* defined in Login.java.
* #param context
* #param message
*/
void displayMessageOnScreen(Context context, String message) {
Intent intent = new Intent(Config.DISPLAY_MESSAGE_ACTION);
intent.putExtra(Config.EXTRA_MESSAGE, message);
// Send Broadcast to Broadcast receiver with message
context.sendBroadcast(intent);
}
/**
* It displays the simple Alert dialog
* #param context
* #param title
* #param message
* #param status
*/
#SuppressWarnings("deprecation")
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
//Set Dialog Title
alertDialog.setTitle(title);
//Set Dialog Message
alertDialog.setMessage(message);
if(status != null)
//set alert dialog icon
alertDialog.setIcon((status) ? R.drawable
.ic_launcher : R.drawable.ic_launcher);
//Set OK button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(final DialogInterface dialog, final int which) {
}
});
alertDialog.show();
}
private PowerManager.WakeLock wakeLock;
/**
* Device wakeup when any push notification reveived.
* #param context
*/
#SuppressWarnings("deprecation")
#SuppressLint("Wakelock")
public void acquireWakeLock (Context context){
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "WakeLock");
wakeLock.acquire();
}
public void releaseWakeLock(){
if (wakeLock != null) wakeLock.release();
wakeLock =null;
}
}
LoginActivity.java
public class LoginActivity extends Activity {
EditText inputEmail;
EditText inputPassword;
Button loginBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
final Controller controller = (Controller) getApplicationContext();
// Check if the internet coneection is present
if (!controller.isConnectingToInternet()) {
// Internet connection is not present
controller.showAlertDialog(LoginActivity.this,
"Internet Connection Error!!", "Please connect your"
+ "device to internet.", false);
// Stop executing code by return
return;
}
// Check if GCM configuration is set
if (Config.SERVER_URL == null || Config.GOOGLE_SENDER_ID == null
|| Config.SERVER_URL.length() == 0
|| Config.GOOGLE_SENDER_ID.length() == 0) {
// GCM sender id / server url is missing
controller.showAlertDialog(LoginActivity.this,
"Configuration Error!",
"Please set your Server URL and GCM Sender Id", false);
// Stop executing code by return
return;
}
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.password);
loginBtn = (Button) findViewById(R.id.btnLogin);
loginBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Get data from EditText
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
// Check if the user filled the form
if (email.trim().length() > 0 && password.trim().length() > 0) {
// Launch MainActivity
Intent i = new Intent(getApplicationContext(), MainActivity.class);
// Registering user to our server
// Sending registration details to MainActivity
i.putExtra("email", email);
startActivity(i);
finish();
} else {
// User don´t filled that data
controller.showAlertDialog(LoginActivity.this,
"Login Error",
"Please enter your full details", false);
}
}
});
}
}
GCMIntentService.java
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
private Controller controller = null;
public GCMIntentService() {
// Call extended class Constructor GCMBaseIntentService
super(Config.GOOGLE_SENDER_ID);
}
/**
* Method called on Error
**/
#Override
protected void onError(Context context, String errorId) {
if(controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Received error: " + errorId);
controller.displayMessageOnScreen(context,
getString(R.string.gcm_error, errorId));
}
/**
* Method called on Receiving a new message from GCM server
**/
#Override
protected void onMessage(Context context, Intent intent) {
if(controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("price");
controller.displayMessageOnScreen(context, message);
// notifies user
generateNotification(context, message);
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
if(controller == null)
controller = (Controller) getApplicationContext();
// log message
Log.i(TAG, "Received recoverable error: " + errorId);
controller.displayMessageOnScreen(context,
getString(R.string.gcm_recoverable_error,
errorId));
return super.onRecoverableError(context, errorId);
}
/**
* Create a notification to inform the user that server has sent a message.
*/
#SuppressWarnings("deprecation")
private void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, MainActivity.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
//notification.flags |= Notification.FLAG_AUTO_CANCEL;
// Play default notification sound
// notification.defaults |= Notification.DEFAULT_SOUND;
//notification.sound = Uri.parse(
// "android.resource://"
// + context.getPackageName()
// + "your_sound_file_name.mp3");
// Vibrate if vibrate is enabled
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);
}
/**
* Method called on device registered
**/
#Override
protected void onRegistered(Context context, String RegistrationID) {
// Get Global Controller Class object (see application tag in
// AndroidManifest.xml)
if (controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Device registered: regId = " + RegistrationID);
controller.displayMessageOnScreen(context,
"Your device registred with GCM");
Log.d("NAME", MainActivity.email);
controller.register(context, MainActivity.password, MainActivity.email,
RegistrationID);
}
/**
* Method called on device unregistred
**/
#Override
protected void onUnregistered(Context context, String RegistrationID) {
if (controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Device unregistered");
controller.displayMessageOnScreen(context,
getString(R.string.gcm_unregistered));
controller.unregister(context, RegistrationID);
}
}
MainActivity.java
public class MainActivity extends Activity {
// label to display gcm message
TextView lblMessage;
Controller controller;
// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;
static String email;
static String password;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
controller = (Controller) getApplicationContext();
// Check if Internet present
if (!controller.isConnectingToInternet()) {
// Internet Connection is not present
controller.showAlertDialog(MainActivity.this,
"Internet Connection Error",
"Please connect to Internet connection", false);
// stop executing code by return
return;
}
// Getting email from intent
Intent i = getIntent();
email = i.getStringExtra("email");
password = i.getStringExtra("password");
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest permissions was properly set
GCMRegistrar.checkManifest(this);
lblMessage = (TextView) findViewById(R.id.lblMessage);
// Register custom Broadcast receiver to show messages on activity
registerReceiver(mHandleMessageReceiver, new IntentFilter(
Config.DISPLAY_MESSAGE_ACTION));
// Get GCM registration id
final String regId = GCMRegistrar.getRegistrationId(this);
// Check if regid already presents
if (regId.equals("")) {
// Register with GCM
GCMRegistrar.register(this, Config.GOOGLE_SENDER_ID);
} else {
// Device is already registered on GCM Server
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
Toast.makeText(getApplicationContext(),
"Already registered with GCM Server", Toast.LENGTH_LONG)
.show();
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// Register on our server
// On server creates a new user
controller.register(context, email, regId, regId);
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
// execute AsyncTask
mRegisterTask.execute(null, null, null);
}
}
}
private BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String newMessage = intent.getExtras().getString(
Config.EXTRA_MESSAGE);
// Waking up mobile if it is sleeping
controller.acquireWakeLock(getApplicationContext());
// Display message on the screen
lblMessage.append(newMessage + "");
Toast.makeText(getApplicationContext(),
"Got Message: " + newMessage, Toast.LENGTH_LONG).show();
// Releasing wake lock
controller.releaseWakeLock();
}
};
#Override
protected void onDestroy() {
// Cancel AsyncTask
if (mRegisterTask != null) {
mRegisterTask.cancel(true);
}
try {
// Unregister Broadcast Receiver
unregisterReceiver(mHandleMessageReceiver);
// Clear internal resources.
GCMRegistrar.onDestroy(this);
} catch (Exception e) {
Log.e("UnRegister Receiver Error", "> " + e.getMessage());
}
super.onDestroy();
}
}
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appname"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--
Creates a custom permission so only this app can receive its messages.
NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
where PACKAGE is the application's package name.
-->
<permission
android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name ="com.example.appname.Controller"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.appname.LoginActivity"
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.intent.action.VIEW" />
<action android:name="android.intent.action.DELETE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="com.idrivecare.familypro" />
</intent-filter>
</activity>
<activity android:name="com.example.appname.MainActivity" />
<!--
BroadcastReceiver that will receive intents from GCM
services and handle them to the custom IntentService.
The com.google.android.c2dm.permission.SEND permission is necessary
so only GCM services can send data messages for the app.
-->
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<!-- <category android:name="com.google.android.gcm.demo.app" /> -->
<category android:name="com.example.appname" />
</intent-filter>
</receiver>
<service android:name="com.example.appname.gcm.GCMIntentService" />
</application>
After I login I get this in LogCat;
05-03 12:02:06.386: D/GCMRegistrar(20407): resetting backoff for com.example.appname
05-03 12:02:06.386: V/GCMRegistrar(20407): Registering app com.example.appname of senders 499319758496
05-03 12:02:06.456: V/GCMBroadcastReceiver(20407): onReceive: com.google.android.c2dm.intent.REGISTRATION
05-03 12:02:06.456: V/GCMBroadcastReceiver(20407): GCM IntentService class: com.example.appname.GCMIntentService
05-03 12:02:06.456: V/GCMBaseIntentService(20407): Acquiring wakelock
Help me if you find any problems in the code.
You are using the old way of registering to GCM, which is deprecated. The new way of registering simply requires calling GoogleCloudMessaing.register method, which is blocking, and therefore you don't have to get the result in the intent service.
You can follow the official GCM demo app if you wish to use the new way.
If you wish to stick with the old way, it can still work, but you'll have to make some fixes :
If your app's package name is com.example.appname, the manifest should use it consistently. Therefore, instead of :
<permission
android:name="com.example.clipme.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
you should have
<permission
android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
In addition, your intent service class com.example.appname.gcm.GCMIntentService is in the package com.example.appname.gcm, but the broadcast receiver you are using - com.google.android.gcm.GCMBroadcastReceiver - looks for it by default in the main package (com.example.appname.GCMIntentService). Therefore it doesn't find it. You shuold either move the service class to the main package or override the broadcast receiver class to change where it expects to find the intent service class.

NFC on Android doesn't work

I've found an example of how NFC works. But when I'm attaching the NFC card onResume/OnPause calls. Why?
the function: onNewIntent hasn't called.
The code of Activity:
public class AMain extends Activity {
public static final String MIME_TEXT_PLAIN = "text/plain";
public static final String TAG = "NfcDemo";
private TextView mTextView;
private NfcAdapter mNfcAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.amain);
mTextView = (TextView) findViewById(R.id.tv);
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()) {
mTextView.setText("NFC is disabled.");
} else {
mTextView.setText("NFC is enabled.");
}
handleIntent(getIntent());
}
#Override
protected void onResume() {
super.onResume();
/*
* It's important, that the activity is in the foreground (resumed). Otherwise
* an IllegalStateException is thrown.
*/
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
/*
* Call this before onPause, otherwise an IllegalArgumentException is thrown as well.
*/
stopForegroundDispatch(this, mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
/*
* This method gets called, when a new Intent gets associated with the current activity instance.
* Instead of creating a new activity, onNewIntent will be called. For more information have a look
* at the documentation.
*
* In our case this method gets called, when the user attaches a Tag to the device.
*/
handleIntent(intent);
}
private void handleIntent(Intent intent) {
String action = intent.getAction();
Log.d(TAG,action);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (MIME_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} 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
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
/**
* #param activity The corresponding {#link Activity} requesting the foreground dispatch.
* #param adapter The {#link NfcAdapter} used for the foreground dispatch.
*/
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);
}
/**
* #param activity The corresponding {#link BaseActivity} requesting to stop the foreground dispatch.
* #param adapter The {#link NfcAdapter} used for the foreground dispatch.
*/
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
/**
* Background task for reading the data. Do not block the UI thread while reading.
*
* #author Ralf Wondratschek
*
*/
private class NdefReaderTask extends AsyncTask<Tag, Void, String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
mTextView.setText("Read content: " + result);
}
}
}
}
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.nfc.AMain"
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"/>
<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.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
</application>
</manifest>
You should add NfcAdapter.ACTION_TAG_DISCOVERED to your intent filter. Your current intent filter( filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);) only catches NFC tag containin NDEF messages.
by changing your filter to
filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
you should get what you want.
Hi have you set the <uses-permission android:name="android.permission.NFC" /> in your ,manifest?

Categories

Resources