Android AppWidget: new instance freezing old one - android

I use the following:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, ConfigureActivity.class);
configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
configIntent.setAction(ACTION_UPDATE);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, PendingIntent.FLAG_CANCEL_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.config_button, configPendingIntent);
Intent smsIntent = new Intent(context, TurboSMSWidget.class);
smsIntent.putExtra(APP_ID, appWidgetId);
smsIntent.setAction(ACTION_SEND);
PendingIntent smsPendingIntent = PendingIntent.getBroadcast(context, 0, smsIntent, PendingIntent.FLAG_CANCEL_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.send_button, smsPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
The widget creation works great, but every time i run a new widget the old one is disabled. I can't use buttons anymore, it is like frozen on the home screen. What's wrong with this code?

I think the problem is in PendingIntent. The new instance of PendingIntent overwrite the old one. You should use unique Intent for inialization of PendingIntent. Here is the discussions that may help you: Multiple Instances Of Widget Only Updating Last widget, How can I correctly pass unique extras to a pending intent?, android pending intent notification problem

Related

Changing Widget Image by OnClick (or PendingIntent ?)

I would like my Appwidget in addition to the main function nor (Widget)images changed.
When calling the function PendingIntent pendingIntent = PendingIntent.getActivity(context, 1001, new Intent(context, Counter.class), 0); should also change the widget to the new image.
Then, when the requested activity exits, the widget will switch to the old image. The Counter.class itself has no layout - so I can still see the homescreen with the widget when activity is running. Why would that the widget displays through changing the picture that the activity is running or rather not.
But I have no idea how to do it.
My WidgetProvider code:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int i = appWidgetIds.length; --i >= 0;) {
int appWidgetId = appWidgetIds[i];
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, Counter.class), 0);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.count_widget);
remoteViews.setOnClickPendingIntent(R.id.countWidget, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
P.S. Sorry for my English :)

Only update the current Android widget ID in update method

I'm making a widget in android which produces a random number when clicked. When the widget is alone on the home screen it works perfectly, however when you add multiple of them they start to generate random numbers at the same time. Whats happening is when an individual widget is clicked it updates all of them; resulting in many random numbers. What i want is each widget to be isolated from the others; basically when a widget is clicked it only updates itself and non of the others around it. I think this is achievable by getting the ID of the current widget and update that one only, as apposed to the update method updating all the widgets; how do i do this?
My code
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context,
MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// Create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_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, MyWidgetProvider.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);
}
}
Summary:
This code is the update method and is called when a widget is clicked. I want this method to only update the widget ID that called it, not for this method to update all the widgets ID's on the home screen.
I had the same problem and I found this way to solve it:
1.To be able to distinguish between multiple instances of the same AppWidgetProvider, when registering the “onClick” event (intent) you must add an extra value with the widget ID (appWidgetId):
Intent clickIntent = new Intent(context, DigiStation.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, clickIntent, 0);
2.Update only the views of the current instance:
appWidgetManager.updateAppWidget(appWidgetId, views);
3.Android reuses intents, so when you create an intent, make sure you put an unique ID, or else the same intent used before will be triggered for all instances:
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, clickIntent, 0);
4.When handling the click event, get the appWidgetId from the “extras” payload of the intent.
You can found more useful details here.

Start activity by clicking on widget

I newbie at programming Android and I try to do a widget which has be able get some data from ISP about my account. There are a lot of unknown things how to do it, but I have did a few things - I've got a widget with configure activity, where user should type login and password. Widget stores the data in SharedPerferences, and when it's time to update widget I use a Service to start an AsyncTask to getting it from ISP an account data. Now I want to do start an activity by click on widget. I've tried all advice which I found on this site and widget can't start activity. My widget based on another widget which placed here https://github.com/Arturus/MetrikaWidget. I dont understand what and where I should change to start activity by clicking on my widget. Thanks.
UPDATE:
My update function, where I suggest I should place PendingIntent
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
Log.d(TAG, "onUpdate");
for (int appWidgetId : appWidgetIds)
{
updateAppWidget(context, appWidgetManager, appWidgetId);
}
/* An updateAppWidget functions looks like as:
Intent intent = new Intent(context, UpdateWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
context.startService(intent);
*/
Intent intent = new Intent(context, DetailedStatActivity.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.layout);
views.setOnClickPendingIntent(R.id.layout, pendingIntent);
ComponentName componentName = new ComponentName(context.getPackageName(), WidgetProvider.class.getName());
appWidgetManager.updateAppWidget(componentName, views);
}
Use this snippet in onUpdate() method of your widget AppWidgetProvider class:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
Intent configIntent = new Intent(context, Activity.class);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
Here widgetlayout is name of your widget layout and R.id.widget is it's parent layout id.
Edit:
Now,I see your code that you added to your question.You would to do:
PendingIntent.getActivity(context, 0, configIntent, 0);
(that start's activity) instead of
PendingIntent.getService(...);
that attempt to starts service.Good luck.
References:
doityourselfandroid.com
helloandroid.com
Intent inet = new Intent(your_action);
inet.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntentNetworkInfo = PendingIntent.getActivity(context, 2,
inet, Intent.FLAG_ACTIVITY_NEW_TASK);
remoteViews.setOnClickPendingIntent(you_component_when_the_user_pressing_this_activity_should_start, pIntentNetworkInfo);
I don't know about "Creating widget from another widget". This is out of my knowledge but I suggest you to build your own widget.
Apart from that, calling activity from widget should be using PendingIntent
Here is simple example to do it
Intent iSetting = new Intent(this, MyConfig.class);
PendingIntent piSetting = PendingIntent.getActivity(this, 0, iSetting, 0);
views.setOnClickPendingIntent(R.id.IdComponent, piSetting);
Or you might need to see this link and this link
In order to initiate the launcher activity, I have integrated the addCategory() and setAction() methods into the onUpdate() method.
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.addCategory("android.intent.category.LAUNCHER");
configIntent.setAction("android.intent.action.MAIN");
PendingIntent configPendingIntent = PendingIntent.getActivity(context, Values.REQ_CODE, configIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
views.setOnClickPendingIntent(R.id.btn_widget, configPendingIntent);

Android Click on Widget not working after adding widget

prefs.java
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, resultValue);
Context context = getApplicationContext();
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, Prefs.class);
configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.callbackwidget, pendingIntent);
AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, views);
widget.xml
Problem is when i add widget IT IS NOT CLICKABLE. after rebooting phone it is working ok. also after deploying new build version, widget IS CLICKABLE
any ideas?
great. problem was on NOT SENDING ACTION_APPWIDGET_UPDATE. so before closing preferences i send broadcast:
Intent updateIntent = new Intent(this, CallBackWidget.class);
updateIntent.setAction("PreferencesUpdated");
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
sendBroadcast(updateIntent);
and in onreceive method of widget i check for broadcast
if ("PreferencesUpdated".equals(action)) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
appWidgetManager.updateAppWidget(appWidgetId, views);
int[] appWidgetIds = new int[] {appWidgetId};
onUpdate(context, appWidgetManager, appWidgetIds);
}
now it works like a charm ;)
It might be that you have a config screen setup for your widget. If so then the widget is NOT built for you the first time it is added. Hard to tell from the code provided.
see http://developer.android.com/guide/topics/appwidgets/index.html.
Specifically this sentence
The onUpdate() method will not be
called when the App Widget is created
(the system will not send the
ACTION_APPWIDGET_UPDATE broadcast when
a configuration Activity is launched).
It is the responsibility of the
configuration Activity to request an
update from the AppWidgetManager when
the App Widget is first created.
However, onUpdate() will be called for
subsequent updates—it is only skipped
the first time.

Updating extras in an intent in app Widget in Android

My code:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Intent active = new Intent(context, DialerWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
active.putExtra("com.anirudha.android.appwidget.Number", currentNumber);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context,
0, active, 0);
views.setOnClickPendingIntent(R.id.one,
actionPendingIntent);
views.setTextViewText(R.id.number, currentNumber);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) {
currentNumber = intent.getStringExtra("Number");
currentNumber += "1";
Intent active = new Intent(context, DialerWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
active.putExtra("com.anirudha.android.appwidget.Number", CurrentNumber);
active.putExtra("com.anirudha.android.appwidget.Key", "1");
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context,
0, active, 0);
views.setOnClickPendingIntent(R.id.one,
actionPendingIntent);
views.setTextViewText(R.id.number, currentNumber);
ComponentName cn = new ComponentName(context.getPackageName(),
DialerWidget.class.getName());
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(cn, views);
Toast.makeText(context, currentNumber, Toast.LENGTH_SHORT).show();
}
super.onReceive(context, intent);
}
So, basically i want to change the extras i should receive with the Intent. But whenever the button is pressed i receive the same value with the Intent. I'm new to android development. Any help would be appreciated. Thanks
If you want to update an existing pending intent, you have to use the FLAG_UPDATE_CURRENT flag when you create it.
PendingIntent actionPendingIntent =
PendingIntent.getBroadcast(context, 0, active, PendingIntent.FLAG_UPDATE_CURRENT);
What type is currentNumber? It's not shown but from the code I guess it's an int.
You are putting it into the extra as an int, but you are reading it out as a string. The string will always we empty because there is no string extra with that name so currentnumber will also be 0, then increased by 1, so always be 1.
Also you are writing it with "com.anirudha.android.appwidget.Number" but reading with "Number". This must be the same key for writing and reading.
Solution: use getIntExtra()

Categories

Resources