I have been looking for a solution for this problem for a week by now.
When my app is running in background, the onclicks event on the widget work as expected.
But when the application is closed (killed by task manager), the widget's PendingIntents stop working.
How is it possible?
I think I have created the widget provider correctly.
Something is missing?
Can someone help me?
Here is my code:
- compileSdk 31
- minSdk 23
- targetSdk 31
- gradle -> "com.android.tools.build:gradle:7.0.4"
Provider class:
public class GPWidgetProvider extends AppWidgetProvider {
private static RemoteViews getRemoteViews(Context context) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent intentHome = new Intent(context, Home.class);
intentHome.setData(Uri.parse(intentHome.toUri(Intent.URI_INTENT_SCHEME)));
intentHome.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent homePendingIntent = PendingIntent.getActivity(context, 13, intentHome, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_image, homePendingIntent);
return views;
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews views = getRemoteViews(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public static void updateWidget(Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName widget = new ComponentName(context, GPWidgetProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(widget);
for (int appWidgetId : appWidgetIds) {
RemoteViews views = getRemoteViews(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Manifest:
<receiver
android:name="<myPackage>.GPWidgetProvider"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.appwidget.action.APPWIDGET_DISABLED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
Thanks in advance.
If an app is killed by e.g. the user force-stopping, all of the services, activities, notifications, and PendingIntents from the app are cancelled. You'll only have an opportunity to recover the next time your app runs (from activity launching, receiving broadcast, etc).
This is why the system warns the user that apps may not behave properly if force-stopped.
Related
I have made an app consisting of 5 activities . I just wanted to know how I could update a widget only when I press a button in the present in an activity in the main app
You need a reciever for your widget declared in the manifest.xml:
<receiver
android:label="MyIP Widget"
android:icon="#drawable/ic_launcher"
android:name="Widget" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/example_appwidget_info" />
</receiver>
That block should be inside the application block.
In my example the widget updates upon connectivity state change. You can replace that with a custom intent. And, from your activity, you need to send that intent to update the widget, something like this:
Intent i = new Intent();
i.setAction(CUSTOM_INTENT);
context.sendBroadcast(i);
where
public static final String CUSTOM_INTENT = "jason.wei.custom.intent.action.TEST";
you can pick the name that you want.
And make sure to add the same name in the reciever:
<action android:name="jason.wei.custom.intent.action.TEST" />
UPDATE:
to receive you broadcast, you need this method in your Widget class
public class Widget extends AppWidgetProvider {
...
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context,intent);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
ComponentName thisWidget = new ComponentName(context.getApplicationContext(), Widget.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
if (appWidgetIds != null && appWidgetIds.length > 0) {
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
The code above may look a bit complex but it is needed to update all the instances of your widget (the user may have your widget on different home screens or even at one screen).
As you can see, it calls the onUpdate method, where you set the actions you want to be executed to update the widget:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
//your update code here
}
I am for the first time checking how to make a widget app. The first thing I want to do is add a widget to the home screen, a basic textview with a static text. Nothing else.
After reading the guide I tried to construct one. I get to the point that the widget is listed by the system, I run normally the configuration activity. But when I drag and drop the widget to the homescreen, nothing happens. I don't know where to debug, when I do debug my Widgetprovider class all looks fine (resources are not null, view gets updated) so I don't know where to look for an error message.
What is wrong?
At least some direction on where to look would be very appreciated!
Here's the manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tizanacode.ExJakdojade">
<application android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/ic_launcher"
android:theme="#style/AppTheme">
<activity
android:name="WidgetConfigurationActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:icon="#drawable/ic_launcher"
android:label="Watched Line"
android:name="ExJakdoJade" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/ex_jakdojade_info" />
</receiver>
</application>
Here is the provider class:
public class ExJakdoJade extends AppWidgetProvider {
private static final String ACTION_CLICK = "ACTION_CLICK";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context,
ExJakdoJade.class);
/*int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {*/
for (int widgetId : appWidgetIds) {
// Create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.layout);
Log.w("WidgetExample", String.valueOf(number));
// Set the text
remoteViews.setTextViewText(R.id.update, String.valueOf(number));
// Register an onClickListener
Intent intent = new Intent(context, ExJakdoJade.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
}
I am trying to test my app Widget and have registered the receiver in the manifest as follows:
<receiver android:name=".MyUtilityWidget" android:label="#string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget_config" />
</receiver>
The MyUtility code:
public class MyUtilityWidget extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
my Main Code here.... (widget stuff)
}
My widget starts and executes once fine (hence I leave the code out of here). However the broadcast receiver is not working and I receive no broadcasts. In fact LogCat shows the intent is never executed. So, my code block only executes once on apk deployment and never again (widget text shows, but never updates every 30m as I have set).
Config here...
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dip"
android:minHeight="72dip"
android:updatePeriodMillis="1800000"
android:initialLayout="#layout/widget_message"
/>
Also updatePeriodMillis cannot be less than 30 minutes? This is a very annoying issue when debugging, as I have to wait around 30 minutes each run to check if the intent fired!
Any help appreciated.
You need to grab hold of your widget via RemoteViews and update it accordingly. It doesn't just update automatically.
Try something like this:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
ComponentName thisWidget = new ComponentName(getApplicationContext(),
MyWidgetProvider.class);
int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
final int N =allWidgetIds2.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = allWidgetIds2[i];
RemoteViews widgetView = new RemoteViews(getPackageName(), R.layout.widget_layout);
widgetView.setTextViewText(R.id.some_text_view, "some text");
I honestly have no idea what I'm doing wrong here. I had this working last night, I messed with the code and I'm pretty sure I have it back to where it was yet it simply doesn't do anything when clicked.
Here is my code
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d(LOG_TAG, "onUpdate(): ");
for (int appWidgetId : appWidgetIds) {
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("market://details?id=com.xx.xx"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT );
RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget);
remoteView.setOnClickPendingIntent(R.id.image, pendingIntent);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
I'm simply trying to take the user to the market when the widget is clicked but nothing at all happens.
Is this a simple fix?
OH MY GOD. I've spent about 4-5 hours on this.. just realized what I've done wrong.
I was missing 'appWidgetManager.updateAppWidget(appWidgetId, remoteView);' after my setOnClickPendingIntent.
The joys of programming.
For Handling Click on Home Screen Widget you will need Register an Custom Reviver in manifast as:
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.imranandroid.xxx.xxxx.ACTION_WIDGET_CLICK"/>
<action android:name="android.appwidget.action.APPWIDGET_DELETED"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
and Attach this action with Widget Layout or with Button:
public class SlientwidgetProvider extends AppWidgetProvider {
public static String ACTION_WIDGET_CLICK= "ActionReceiverClick";
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews rview = new RemoteViews(paramContext.getPackageName(), R.layout.widget_layoutmain);
Intent active = new Intent(paramContext, SlientwidgetProvider.class);
active.setAction(Globfilds.ACTION_WIDGET_CLICK);
///....
you can see full code here for handling click on Home Screen Widgets:
Silenttoggle
I have developed an application that makes use of a widget. The widget could be added in the homescreen and used as a button. I have recently downgraded the version to <uses-sdk android:minSdkVersion="7" /> and no errors were spotted. However, now when i reinstall the, the widget is not responsive. In addition when I try to install the app on another phone running android 4.0.3, widget is not available anywhere, so i cannot even add it to the homescreen. Here is my code for the widget:
public class MyWidget extends AppWidgetProvider {
#Override
public void onUpdate(Context c, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
final int N = appWidgetIds.length;
//for each of the instances of the widget
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(c.getPackageName(), R.layout.widget_layout);
Intent fireDialog = new Intent(c,Execute.class);
PendingIntent pendingIntent = PendingIntent.getActivity(c, 0, fireDialog, 0);
views.setOnClickPendingIntent(R.id.myButton, pendingIntent); //when the button is clicked, an activity is launched
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onReceive(Context c, Intent intent)
{
final String action=intent.getAction();
if(AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)){
final int appWidgetId=intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID);
if(appWidgetId!=AppWidgetManager.INVALID_APPWIDGET_ID){
this.onDeleted(c,new int[]{appWidgetId});
}
}else{
super.onReceive(c, intent);
}
}
}
Here is the manifest.xml:
<application>
<receiver android:name=".myButton"
android:icon="#drawable/icon"
android:label="myWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/my_xml" />
</receiver>
</application>