Android - AppWidget's pending intent does not fire - android

I have an app widget with a Button in it's layout.
When clicking the button, an intent is fired which calls my broadcast receiver.
It works just fine, but occasionally, after using the "Clear memory" button in the Task Manager, the widget gets stuck - clicking on it does nothing. But it can still receive updates from my app, if its running.
I'm not sure if the fact that the pending intent isn't fired is the memory clearing fault, or my fault.
Anyway, here's the code:
Registering the pending intent (onUpdate method of the app widget)
Intent intent = new Intent(context, ServiceControl.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget);
views.setOnClickPendingIntent(R.id.appwidgetbutton, pendingIntent);
and then updating the widgets with the views.
Here is the decleration of the app widget provider:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="72dp"
android:minHeight="72dp"
android:initialLayout="#layout/appwidget"
android:updatePeriodMillis="0">
</appwidget-provider>
I don't want the system to call widget updates, I only update it from my app itself.
So why does the pending intent stop firing?
Thanks in advance.

#Jong
#CommonsWare
Hi guys, I figured it out. Ofc this is an Android issue, the receiver should ALWAYS receive.
Now how to get around it? Obviously all the widgets are working, so there must have been a simple out there.
I read on SO somewhere (trying to find the guy) reminding us all that the widget class is actually extending a BroadcastReceiver.
So, you could register the widget (in the manifest) to receive the threats itself. Thus the entire system is self-contained in the class instance of AppWidgetProvider.
Now, for communicating back with the app, you can in the onReceive call any static class of your app, and LocalBroadcastManager won't fail you if the app is active. If it's not active, your buttons should be starting activities anyway!
Should you want the code, I can detail it.

Related

Android - Not able to start multiple activities from background

I am facing a problem.
This is the code I have in my BroadcastReceiver extender class:
#Override
public void onReceive(Context context, Intent intent) {
// other
Intent myIntent = new Intent(context, ShowMessageActivity.class);
myIntent.putExtra(Utils.SHOW_MESSAGE_OPTION, messageToDisplay);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(lockScreenMessage);
}
which starts a new activity when a broadcast is raised.
When the application is in foreground and receives a broadcast, it starts a new Activity as many times as the code executes, but it is not the case when the app is in background. In that case it starts an Activity only once, and not each time a broadcast is received. Why? Is it possible to fix that?
that very depends on what do you expect in that receiver, is it any system-side call (declared in manifest) or your own? who an when calls it, thats very important
starting Android 10 there are some restrictions for starting Activity from onReceive, check out official DOC. basically you shouldn't start any Activity from there, and when it works for you I bet it works only for few secs after PendingIntent creation. check out exceptions list under link above, possible reasons would be:
The app has an activity in the back stack of an existing task on the Recents screen.
The app has an activity that was started very recently.
The app called finish() on an activity very recently.
you may check out your code on some emulator with Android 9, all your broadcast calls should work "always"

Android home screen widget mysteriously fails to receive touch events

I've got a somewhat graphically complex Android homescreen (via AppWidgetProvider) widget that I simply can't get to respond to touch events. The general idea is that tapping the widget should make it change modes for the next 4-5 seconds to display different information, but for the life of me it's showing no sign of ever receiving the Touch event.
The steps I've taken are as follows:
I've implemented an intent-filter within the Manifest.xml like so...
<action android:name="foo.kung.fancywidget.TOUCHED" />;
... and it's inside the <receiver /> container for the widget, right next to the expected APPWIDGET_UPDATE entry that Android Studio helpfully adds.
I've ensured that the Layout being used has the clickable attribute set to true on every single element (just to be thorough) including the top-level RelativeLayout itself.
I've defined the static string for the thing at the top of the ExtraFancyWidget.class, like so...
public static final String TOUCHED = "foo.kung.fancywidget.TOUCHED";
...and according to what I've been reading it should come through as the broadcast via the onRecieve handler when done like this...
if (TOUCHED.equals(intent.getAction())) {
Log.i("onReceive", "Touch event received");
}
...but with a Log.d entry at the top of the onReceive handler I can tell I'm not getting any sort of signals through there at all aside from the heartbeat coming from the system service every ten seconds.
Lastly, I'm assigning the intent just like I've been reading about
private PendingIntent createOnClickIntent(Context context) {
Intent intent = new Intent(context, ExtraFancyWidget.class);
intent.setAction(TOUCHED); // WHY DOESN'T THIS WORK?!?!?
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
...and it's literally the last thing happening in onUpdate before the view is updated
views.setOnClickPendingIntent(R.id.TheWholeWidget, createOnClickIntent(context));
appWidgetManager.updateAppWidget(appWidgetId, views);
What could I possibly be overlooking or not seeing at this point? I don't know of anything else I'm supposed to be doing or changing to make this work... it just mysteriously ignores the user. ADB never shows me any of the log entries (although it does show a number of other, silly log messages so I know that's working) that would indicate the widget ever sees me tapping it.
The problem is in step 5, where you're creating the intent. Do NOT set a specific class to the intent, rather create it with only an action, like this:
Intent intent = new Intent();
intent.setAction(TOUCHED); // this should work now
or the shorthand
Intent intent = new Intent(TOUCHED);
If it still doesn't work, consider putting a requestCode other than 0 when building the PendingIntent. Depending on the Android version you're building from, there were some bugs when using just 0.
return PendingIntent.getBroadcast(context, 1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Lastly, if this broadcast will be used only within your app (which is highly probable), consider using a LocalBroadcastManager.

Android addProximityAlert for all application

I want show Activity when device enter the fixed zone. I have startActivity in recivier(GpsAlarmRecivier). Code below works, but when I close Activity, it crash. I know it' s because i must unregister recivier.
But I want use addProximityAlart for all application, even after close my activity(for example, move to previous). Is it possible ?
Intent myIntent = new Intent("gpsup.namespace.ProximityAlert");
PendingIntent proximityIntent = PendingIntent.getBroadcast(cxt, 0, myIntent, 0);
locationManager.addProximityAlert(records.get(pos).x, records.get(pos).y, records.get(pos).r,
-1, proximityIntent);
IntentFilter filter = new IntentFilter("gpsup.namespace.ProximityAlert");
actv.getApplicationContext().registerReceiver(new GpsAlarmReceiver(), filter);
I want use addProximityAlert, even if I close activity, when i created recivier. Thanks for any advices.
I don't believe that there is a way to directly register a system GPSBroadcastReceiver in your application. If that was the case you could just put it in your manifest and it'll get resolved when an update comes out and then you can fire off you custom intent after performing your checks.
I believe that is actually the reason why they don't allow it (I may be wrong). It would be problematic if every application was woken up when a GPS update came out. They would be spanking the battery in the background.
A suggestion that I can give is to create a Service that listens for your GPS updates and then Broadcasts your intents. While you can have it running in the background forever, it certainly has a longer life cycle than an Activity does.

Android Widget PendingIntent Fails

There have been some similar issues discussed here, but my situation does work some of the time. I am developing a widget that when clicked should launch an activity that's part of the same package. This same activity can also be launched by a notification that may be posted. The widget updates and notification posting are done by a Service in the package. Here is the method that's called to issue the PendingIntent:
// Get pending intent for widget or notification
private PendingIntent getPendingIntent(int widgetId, int extraData) {
Intent clickIntent = new Intent(mCtx, OtdShowEvents.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
clickIntent.putExtra("OTDExtra", extraData);
clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendIntent = PendingIntent.getActivity(mCtx, 0, clickIntent,
0);
return pendIntent;
}
If I create an instance of the widget on a clean (rebooted) device, both the widget and notification launch the target activity as expected. However, if I remove the widget and create another instance, the Intent is no longer launched. Likewise, if I uninstall the widget altogether, then re-install it and create an instance, no Intent is fired off. However, if I power off and back on (leaving the widget in place), it works again when booted up.
One error that I saw along the way was from the PackageManager saying "Name not found", but indicating the package name "com.ghcssoftware.OTD.full", which is the correct name of my package!
Any ideas? And by the way, I have tried some of the PendingIntent flags such as FLAG_CANCEL_CURRENT and FLAG_UPDATE_CURRENT without affecting this behavior.
FWIW, I found that the code snippet provided in this article was exactly what I needed to figure out how to get this all working correctly, especially for multiple instances of my widget, etc.: PendingIntent in Widget + TaskKiller

Correct way of handling (pending) intents in AppWidgets

I have a question regarding AppWidget intent handling. I have a widget which is clickable, and on click I want to send an intent to the AppWidgetProvider itself for further processing.
The problem: I receive the intents initially in onReceive(), but after a while (not sure what causes it), onReceive() is no longer called.
I have the following code, all in MyWidgetProvider extends AppWidgetProvider.
a) register for receiving broadcasts:
in onEnabled(...):
context.getApplicationContext().registerReceiver(this, new IntentFilter(MY_ACTION));
b) set intent to be fired on click:
in onUpdate(...)
Intent intent= new Intent(MY_ACTION);
PendingIntent pendingIntent= PendingIntent.getBroadcast(context, 0/*notusedanyway*/, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_root, pendingIntent);
c) react to event and do something:
in onReceive(...)
if (MY_ACTION.equals(intent.getAction())
doSomething();
When I deploy + add a widget, it works fine. However, after a while - not sure what exactly causes the problem, but a phone call, for example, seems to affect it - I no longer get any notifications in onReceive().
I am completely stumped why this is the case. Can someone point out to me the correct way of doing this?
Thanks!
Tom
You should use a BroadcastReceiver registered in your AndroidManifest.xml file. When you register it in onEnable it is tied to the process. Whenever Android kills your process (for example, when a phone call is received) then your receiver no longer exists and (as you observed) no longer works.

Categories

Resources