activity is not being called from broadcast receiver - android

I am using an alarmmanger with broadcast receiver and when a specified time occurs, i need to update the MainActivity with extra parameter but its behaving randomly.
here is code in the broadcast receiver
public void onReceive(Context context, Intent intent){
//calculate time
//check time
if(isTime){
Log.d("tag", "sleep");
//set value in shared preference
editor = (context.getSharedPreferences("uniqueId", 0)).edit();
editor.putBoolean("sleepmode",false);
editor.apply();
Intent gotoSmileyScreen = new Intent(context, MainActivty.class);
gotoSmileyScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
context.startActivity(gotoSmileyScreen);
}
}
In logcat, i am able to see "sleep" , so i know the method is being called at the right time
Here is code in MainActivity
//inside on create
//get value from shared preference and check
if(!isSleepMode){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}else{
//do nothing
}
The user will most likely be already in that activity but not necessarily.
The activity is being called for some devices and the screen turns off as expected but for some others, the activity is never called from the intent and screen wont turn off.
From the documentation, Intent.FLAG_ACTIVITY_CLEAR_TASK, should clear the activity before calling it again or am i missing something?
Is there a better way to update the activity from the receiver without calling it again?
Edit: My app is a launcher, does it in any way effect calling the intent?

I found a workaround using Intent.FLAG_ACTIVITY_SINGLE_TOP and overriding onNewIntent in the MainActivity. If the activity is already in the top, it calls onNewIntent otherwise creates a new instance of the activity. So the new code is like this
gotoSmileyScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP );
and it works. Hope it helps someone.

Change your intent as below and try
Intent gotoSmileyScreen = new Intent();
gotoSmileyScreen.setClassName("com...<Your broadcast receiver name>", "com.....MainActivty.class");
gotoSmileyScreen.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(gotoSmileyScreen);
For Broadcast receiver try like above.

Another way to update the activity is by using Dynamic Broadcast receiver
To acheive this inside the onReceive Method use sendBroadcast to send the data to activity ad inside the activity
register the broadcast Receiver to receive the data
Register your dynamic broadvast Receiver inside onCreate() and unregister inside onDestroy()

Related

Activity Listen for broadcast receiver

So I have broadcast receiver that is getting started on boot. I have an activity that using the information being collected by the broadcast receiver. I want the activity to be able to update its recycler view every time the broadcast receiver is called, the problem is the activity has no reference to the broadcast receiver. Is there a way that I can have my activity listen for the broadcasts and update itself?
The only thing I can think of is having the activity run a repeating task that will try to update itself with new information. This doesn't seem like a good solution to me.
the best approach is to register a BroadcastReceiver - see documentation on this. In your case you'd want to Programmatically register a broadcast receiver so that the onReceive(Context context, Intent intent) from inside the Activity class. In this way, you can then update the Recyclerview as you desire. Something like:
public void onCreate(Bundle savedInstanceState){
...
IntentFilter filter = new IntentFilter();
//you may want to set whatever filters here...
//define the broadcast receiver
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//here you can update the RecyclerView as you desire using intent's data
}
};
//register the broadcast receiver
registerReceiver(receiver, filter);
}
I strongly recommend that you go through this nice BroadcastReceiver tutorial.
Enjoy.
The broadcast receiver registered for BOOT_COMPLETED action has nothing to do with the activity, it's a separate component. So, yes, you don't have a reference to your activity and you should not run any periodical task.
What I would do is to write the collected data to the database or shared preferences and then read it when your activity is actually on the screen.
If you use an SQLite database you can use a ContentObserver to notify your activity about changes to the underlying data. This works great with loaders.
In case of shared preferences you can use a OnSharedPreferenceChangeListener registered in your activity.

Refreshing activity on receiving gcm push notification

Update: GCM is deprecated, use FCM
How to refresh activity on receiving gcm push notification if my app is open. I have an activity which contains listview filled with data from the server. I want to refresh my activity (here adding one more item to listview) , if I receive gcm push notification(which also contains some data).
One alternative is to add timer that periodically do server requests and update the list adapter data but I don't want these because it will take much resources.
Do I need to add broadcast receiver which will trigger on receiving gcm push which further request for newer server data and update my activity UI?
Dear commentors, please read the question carefully, I only need to refresh the list (if app is open and that particular activity is open) else no need for same.
Took me a few hours to figure it out. Posting here in case anyone anyone else has the same problem.
The idea is that you have to register your activity as a broadcast receiver. The easiest way to do this is like so:
//register your activity onResume()
#Override
public void onResume() {
super.onResume();
context.registerReceiver(mMessageReceiver, new IntentFilter("unique_name"));
}
//Must unregister onPause()
#Override
protected void onPause() {
super.onPause();
context.unregisterReceiver(mMessageReceiver);
}
//This is the handler that will manager to process the broadcast intent
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
//do other stuff here
}
};
The above code goes in the activity that you want to 'listen' for events.
Now, how do we send data to this 'listener'? Go to your push notification handler(or from where you want to update your activity) and when you receive a notification call this function:
// This function will create an intent. This intent must take as parameter the "unique_name" that you registered your activity with
static void updateMyActivity(Context context, String message) {
Intent intent = new Intent("unique_name");
//put whatever data you want to send, if any
intent.putExtra("message", message);
//send broadcast
context.sendBroadcast(intent);
}
When you call the above function, your activity should receive it.
Note: Your activity must be running/open to receive the broadcast intent
Note2: I switched to a library called 'otto'. It does actually the same thing but easier, 'broadcasts events' thoughout the app. Here's a link http://square.github.io/otto/
I'm assuming your GCMBroadcastReceiver is in it's own .java file?
As far as refreshing an activity, I would also like to know the answer to that question.
But for knowing if a particular activity is active or not, meaning on screen just add a boolean (call it something like "active") and set it to true in your activity's onResume() event, and to false in the onPause() event:
protected void onResume()
{
super.onResume();
active = true;;
}
protected void onPause()
{
super.onPause();
active = false;
}
Your active variable would be a boolean which is global or static. This way you know if a particular activity is in "front".
Hope that helps a bit.
The accept answer is indeed correct for the "Refreshing activity on receiving gcm push notification" (I've upvoted it too). But if you only want to update a ListView that's being displayed you don't need a broadcast receiver.
Your GCM listener service can update the database using a ContentProvider rather than inserting a direct sql query.
Then you can rely on the notifyChange method on the ContentResolver to do the trick.
Notify registered observers that a row was updated. To register, call
registerContentObserver(). By default, CursorAdapter objects will get
this notification. If syncToNetwork is true, this will attempt to
schedule a local sync using the sync adapter that's registered for the
authority of the provided uri. No account will be passed to the sync
adapter, so all matching accounts will be synchronized.
If your app is already running then try to override the onNewIntent method
Seems there is an easier way. In the OnMessageReceived method of the GCM Listener, you can just do the update from there instead of sending the notification. You can use the same code you would have used if processing the notification. If you're doing StartActivity from the listener, you have to use the ActivityFlags.NewTask flag.
To sum it up in single sentence:
If you want to refresh activity, broadcast your custom event when notification arrives and register your activity as broadcast receiver of that event
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setAction(Long.toString(System.currentTimeMillis()));
PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Getting an activity to start as soon as Android app is in the foreground

I'm using a running service to detect whether network is available or not. When it is not available, it calls an activity to start that displays a blank screen with "no network available" on it. When the network is back, it sends a broadcast to finish this activity.
The only problem is that this activity may start at any time (as a popup), even when using other apps. I want it to start (or be visible) only if the network is out and my app is in the foreground. Any help?
One option would be to have your foreground activity register for the broadcast, and then display the relevant notification from within the activity.
Alternatively you could start your service when your foreground activity starts/resumes (i.e, onResume), and stop it when your activity leaves the foreground.
You can use START_STICKY in your service to ensure it stays around until you stop it, like so:
#Override
public int onStartCommand(Intent intent, int flags, int startId){
//On start work here
return START_STICKY;
}
and then stop the service using stopService when your activity leaves the foreground (i.e onPause).
If you need the former behaviour across multiple activities you can register broadcast receivers programmatically:
BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(MY_ACTION.equals(intent.getAction()))
{
//show appropriate dialog
}
}
};
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction(MY_ACTION);
registerReceiver(myBroadcastReceiver,myIntentFilter);
You can unregister like so:
unregisterReceiver(myBroadcastReceiver);
You could extend Activity and make your own custom subclass that reuses similar code to register and unregister whilst entering/leaving the foreground. Or you can extract this into utility methods/classes and call from the appropriate places.
I think you need Shared Preference to do this. store one Boolean value on finish you activity (you can use onpause() or onStop()) and for showing popup check the value and do what you want
for understnding to use sharePreference see this and developer.android.com
Try the following:
Intent intent = new Intent(this, YourActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
This worked in the context of my own app already running, I'm not sure if it will start your app if it is not already running in the background
EDIT: Not sure if I understand your question entirely. If you only want this activity to come to the foreground while your app is in the foreground, get rid of the addFlags line, also you can do some boolean stuff to check if your app is in the foreground like so, this way your code won't even run if the app isn't in the foreground.
EDIT: There are a few ways to check if your app is in the foreground, the link I posted above has one such solution, another one is to create a static boolean isForeground variable: in the onResume() methods of your app set isForeground = true and in onPuase() set isForeground = false. This isn't the best practice, using ActivityManager is better, but for purposes of testing this should be ok.
Then have something like the following:
if(isForeground){
//Start your activity
}
This should be quick to write, if this is the behavior you want, I would recommend replacing the isForeground static variable with the test for foreground provided by ActivityManager in the link I posted.

Many PendingIntents, BroadcastReceiver and activity

I'm writing a simple reminder app. All reminders are stored in DB. I have a service that query DB and make a pendingIntents in AlarmManager with extras and different timestamps. Also I have a Broadcast Receiver to catch the Intents from AlarmManager. This Broadcast Receiver start a reminder Activity with options for reminder (dismiss, snooze, etc).
Now this scheme work, but not as good as I think it should. If I have a reminder activity in foreground, then new reminder activity starts upon it (current goes to background). I want to not override the current activity with new one and just notify the user, that there are some new reminders that will show after the current.
As I think, I've found a good solution for my task:
1) I've set in AndroidManifest that my reminder activity launchMode is "singleTop". More about launchMode is here http://developer.android.com/guide/topics/manifest/activity-element.html
In two word, if my Broadcast Receiver tries to start activity that already on foreground, it calls onNewIntent, not onCreate.
2) In my activity I've to override the onNewIntent method and store all incoming intents (from broadcast) in ArrayList .
3) Before finish() I've to remove current Intent from ArrayList and when it's size become zero I've actually finish() the activity.
One important addition. In broadcast receiver intent must have FLAG_ACTIVITY_SINGLE_TOP, like:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Without it if no main activity present onNewIntent will not be called. As I see, this is knows issue: http://code.google.com/p/android/issues/detail?id=4155
Bug found in Android 1.6 and still present. So now it is feature :)
Sorry for my English, it's easy for me to read, but hard to write :)

Showing an AlertDialog from Receiver

How do i show an AlertDialog from receiver class. My receiver class receives by time of my Alarm using AlarmManager. And, my alertdialog can show if my application is not opened also.
How can i achieve this? Thanks.
There is not possible to create AlertDialog from Broadcast Receiver.
But there is one way to accomplish this task.
Create a activity and set the theme as a dialog.
OnReceive() method of your Broadcast Receiver start the activity which you had create in 1st step
You have to set the flag Intent.FLAG_ACTIVITY_NEW_TASK to start the activity from the broadcast receiver.
So you code will looks like below
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, yourDialogActivity.class);
i .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
Yes, you can do like this. Just start one activity class from your receiver using Intent and in that activity class just use the code from this Blog
Change that class with whatever you needs for AlertDialog. This will display the when your application closed also. Hope this helps you.

Categories

Resources