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
Related
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.
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
}
hi friends enter link description here
this link to create list view widget for my app, but here i want to add a button below the list view ,which on click will open my app,
using the below code to acheive this,because it worked for me on other app, but not with this example, how to do that .
class widgetprovider
public class WidgetProvider extends AppWidgetProvider {
// String to be sent on Broadcast as soon as Data is Fetched
// should be included on WidgetProvider manifest intent action
// to be recognized by this WidgetProvider to receive broadcast
public static final String DATA_FETCHED = "com.wordpress.laaptu.DATA_FETCHED";
/*
* this method is called every 30 mins as specified on widgetinfo.xml this
* method is also called on every phone reboot from this method nothing is
* updated right now but instead RetmoteFetchService class is called this
* service will fetch data,and send broadcast to WidgetProvider this
* broadcast will be received by WidgetProvider onReceive which in turn
* updates the widget
*/
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// which layout to show on widget
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
Intent informationIntent = new Intent(context,info.class);
PendingIntent infoPendingIntent = PendingIntent.getActivity(context,0, informationIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.btnSeeMore,infoPendingIntent);
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
Intent serviceIntent = new Intent(context, RemoteFetchService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);
context.startService(serviceIntent);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
manifest added a activity
<activity android:name=".info" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.INFO" />
</intent-filter>
</activity>
when on click it should open my app,how to do that please help, thank you
finaly i solved what i want to get,
just wrote a button click code onReceive & it worked
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(DATA_FETCHED)) {
Log.i("inside action", "DATA_FETCHED");
int appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
RemoteViews remoteViews = updateWidgetListView(context, appWidgetId);
Intent informationIntent = new Intent(context,MainActivity.class);
PendingIntent infoPendingIntent = PendingIntent.getActivity(context,0, informationIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.txtSeeMore,infoPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
You need to define how the PendingIntent you are setting will be handled, by overriding the onReceive method inside your provider :
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(ACTION_NAME)) {
// Open your activity here.
}
}
If every item in your ListView needs a different extra to help the onReceive create the proper Intent, you can use a FillInIntent for each item of the ListView, in getViewAt :
// Set the onClickFillInIntent
final Intent fillInIntent = new Intent();
final Bundle extras = new Bundle();
extras.putInt(YourWidgetProvider.ACTION_EXTRA_ITEM, event.getId()); // retrieve this in onReceive with intent.getIntExtra(ACTION_EXTRA_ITEM, -1)
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.listview_main_layout, fillInIntent);
return rv;
Also, don't forget to add your Provider and your RemoteViewsService to your Manifest :
<receiver
android:name="com.example.YourWidgetProvider"
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/provider_definition_in_xml" />
</receiver>
<service android:name="com.example.YourRemoteViewsService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
EDIT :
To handle clicks on buttons in the main widget (not in the collection view), it's even easier :
rv.setOnClickPendingIntent(R.id.button_id, PendingIntent.getBroadcast(context, 0,
new Intent(context, YourWidgetProvider.class)
.setAction(ACTION_NAME),
PendingIntent.FLAG_UPDATE_CURRENT));
The ACTION_NAME needs to be different from the name you use for the clicks on the collection view, of course, since it needs to produce a different Intent.
I hope this helps !
Please bear with me because I am new to Android development.
I am building a widget that opens up a Configuration Activity upon placement on the home screen. When I am finished configuration and have pressed "done", the widget provider (onUpdate) is supposed to call the widget service class to bind a list of drawables to a gridview. However, the service class is not being called and the gridview is coming up empty. Any help on this is appreciated, code is included below:
*Note: i have a main.xml that has the gridview in it and another xml that has the template (imageView and textView) the gridview cell.
Manifest:
<service android:name=".WidgetService" android:permission="android.permission.BIND_REMOTEVIEWS" android:exported="false" />
<receiver android:name=".WidgetProvider" android:label="#string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/button_widget_provider" />
</receiver>
Provider:
public class WidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int i=0; i < appWidgetIds.length; i++){
Intent intent = new Intent(context, WidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
remoteViews.setRemoteAdapter(appWidgetIds[i], R.id.gridview, intent);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
......(omitted code)}
Service:
public class WidgetService extends RemoteViewsService {
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent){
return new VZRemoteViewsFactory(this.getApplicationContext(), intent);
}
}
class VZRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory{
public VZRemoteViewsFactory(Context context, Intent intent){
thisContext = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
public void onCreate(){
// code to add drawables to list here
}
public RemoteViews getViewAt(int position){
RemoteViews remoteView = new RemoteViews(thisContext.getPackageName(), R.layout.vzwidget_item);
// setting the image view resource this way for now just for testing
remoteView.setImageViewResource(R.id.launcher_icon, R.drawable.vzicon);
remoteView.setTextViewText(R.id.textview, "test");
return remoteView;
}
.....(omitted code)}
Thank You!
From my experience (and looking at my own just written widget) - OnUpdate is called right when the configuration activity is launched, and after you publish the results from this activity, the following intent action is given to the appWidgetProvider - android.appwidget.action.APPWIDGET_UPDATE_OPTIONS (tested on jellybean).
This might not be the most proper way to handle this, but this is how I am handling this -
when the configuration activity publishes the result - I start up my remote view service and start sending views with the proper widgetid.
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");