Updating extras in an intent in app Widget in Android - 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()

Related

Android widget send Data to onRecive via intent

I'm creating an android widget that by clicking, every instance of the widget will go to a different url.
I'm having a problem sending the url from the 'onUpdate' to the 'onReceive' method.
The onUpdate code:
List<String> urls = Arrays.asList("google.com", "yahoo.com", "bing.com", "msn.com");
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
int cnt = 0;
// Get all ids
ComponentName thisWidget = new ComponentName(context,MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// create some random data
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
Log.w("WidgetExample", urls.get(cnt));
// Set the text
remoteViews.setTextViewText(R.id.urlData, urls.get(cnt));
// Register an onClickListener
Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
intent.putExtra("url",urls.get(cnt));
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.open, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
cnt++;
}
}
The onReceive code:
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String TAG = "onReceive";
Bundle extras = intent.getExtras();
if(extras!=null) {
String url = extras.getString("url");
Log.d(TAG, "url is : "+url);
}else {
Log.d(TAG, "no url");
}
}
The problem is that i allwas get the same url (the last one in the list - 'msn.com').
Thank's allot
Avi
I think that this append because you override everytime the intent storage in PendingIntent because the requestCode doesn't change.
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,**0**, intent, PendingIntent.FLAG_UPDATE_CURRENT);
If you want set more PendingIntent you must change the requestCode (0 in your case)
Try
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, cnt, intent, PendingIntent.FLAG_UPDATE_CURRENT);
In this way all PendingIntents are different...
You're using PendingIntent.FLAG_UPDATE_CURRENT which, as the documentation states, "[...]if the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent[...]"
So since you're trying to create multiple instances of the same class (PendingIntent) that flag is causing the unwanted behaviour. It is updating the previously instantiated object (the first time you called PendingIntent.getBroadcast(...) method) and changes the field(s) of that object and returns it. So that all your calls end up with the last extra (last URL you supplied) .

Android Problems with Widget and Multiple Pending Intents

I have a widget I am working on that controls a media player service. I have 4 buttons on my widget:
Previous
Play/Pause
Stop
Forward
The four buttons are assigned a pending intent which sends a Broadcast to the player service with the required action contained in it as an extra.
The problem I am having is that when I assign the pending intents to the buttons as below, they all seem to have the same broadcast value. For example, with the code below all 4 buttons seem to send Globals.PlaybackActions.SKIP_FORWARD. However, if I comment out the code that assigns the pending intents except for the "Play" button then pressing "Play" broadcasts the correct value.
Is there something I'm not aware of with using multiple pending intents as broadcasts on a widget or have I made a silly mistake in my code that I cannot spot? Or secret option C?
I'm hopelessly lost and confused and would be very grateful for any help. Thanks.
public class PlayerWidget extends AppWidgetProvider {
private boolean serviceIsPlaying = false;
private PendingIntent pendingIntentPrev = null;
private PendingIntent pendingIntentNext = null;
private PendingIntent pendingIntentStop = null;
private PendingIntent pendingIntentPlay = null;
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals(Globals.BROADCAST_WIDGET_UPDATE)) {
return;
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), PlayerWidget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
this.updateViews(context, appWidgetManager, appWidgetIds);
}
private void updateViews(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_player);
this.setClickIntents(context);
if (this.serviceIsPlaying) {
remoteViews.setImageViewResource(R.id.btnPlay, R.drawable.ic_action_pause);
}
else {
remoteViews.setImageViewResource(R.id.btnPlay, R.drawable.ic_action_play);
}
remoteViews.setTextViewText(R.id.txtArtistName, currentTrack.getArtistName());
remoteViews.setTextViewText(R.id.txtSongName, currentTrack.getSongTitle());
remoteViews.setTextViewText(R.id.txtAlbumName, currentTrack.getAlbumName());
remoteViews.setImageViewBitmap(R.id.imgAlbumArt, BitmapFactory.decodeFile(currentTrack.getAlbumArtPath()));
remoteViews.setOnClickPendingIntent(R.id.btnPrev, pendingIntentPrev);
remoteViews.setOnClickPendingIntent(R.id.btnNext, pendingIntentNext);
remoteViews.setOnClickPendingIntent(R.id.btnStop, pendingIntentStop);
remoteViews.setOnClickPendingIntent(R.id.btnPlay, pendingIntentPlay);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
private void setClickIntents(Context context) {
Intent intentPrev = new Intent(Globals.BROADCAST_PLAYBACK_ACTION);
Intent intentNext = new Intent(Globals.BROADCAST_PLAYBACK_ACTION);
Intent intentStop = new Intent(Globals.BROADCAST_PLAYBACK_ACTION);
Intent intentPlay = new Intent(Globals.BROADCAST_PLAYBACK_ACTION);
intentPrev.putExtra(Globals.EXTRA_PLAYBACK_ACTION, Globals.PlaybackActions.SKIP_BACKWARD);
intentNext.putExtra(Globals.EXTRA_PLAYBACK_ACTION, Globals.PlaybackActions.SKIP_FORWARD);
intentStop.putExtra(Globals.EXTRA_PLAYBACK_ACTION, Globals.PlaybackActions.STOP);
if (this.serviceIsPlaying) {
intentPlay.putExtra(Globals.EXTRA_PLAYBACK_ACTION, Globals.PlaybackActions.PAUSE);
}
else {
intentPlay.putExtra(Globals.EXTRA_PLAYBACK_ACTION, Globals.PlaybackActions.PLAY);
}
pendingIntentPrev = PendingIntent.getBroadcast(context, 0, intentPrev, 0);
pendingIntentNext = PendingIntent.getBroadcast(context, 0, intentNext, 0);
pendingIntentStop = PendingIntent.getBroadcast(context, 0, intentStop, 0);
pendingIntentPlay = PendingIntent.getBroadcast(context, 0, intentPlay, 0);
}
}
I think the problem is a second parameter in PendingIntent.getBroadcast() method. The second parameter is requestCode and it should be different for all 4 PendingIntent-s you are using.For example:
pendingIntentPrev = PendingIntent.getBroadcast(context, 0, intentPrev, 0);
pendingIntentNext = PendingIntent.getBroadcast(context, 1, intentNext, 0);
pendingIntentStop = PendingIntent.getBroadcast(context, 2, intentStop, 0);
pendingIntentPlay = PendingIntent.getBroadcast(context, 3, intentPlay, 0);
I have the same problem few days ago and this helped me. Hope it will help you too.

Widget stops receiving data after app crashes or user kills the app?

I have an app which plays music in a Service. There is also a Widget to control the music player. Everything works fine.
Now after the user closes the app or if it crashes or if I use System.exit(); or getActivity().finish(); to close it there are some problems. Everything seems to work fine, but somehow the widget doesn't receive broadcasts anymore even though another Activity still receives them.
The widget is still able to send broadcasts, it is only unable to receive them.
Could somebody please help me out?
Code from my widget:
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
ma = (GlobalSongList)context.getApplicationContext();
context.getApplicationContext().registerReceiver(broadcastCoverReceiver, new IntentFilter(Music_service.BROADCAST_COVER));
context.getApplicationContext().registerReceiver(broadcastPlayPause, new IntentFilter(BROADCAST_PLAYPAUSE));
context.getApplicationContext().registerReceiver(checkagain, new IntentFilter("xyz"));
context.getApplicationContext().registerReceiver(intentshuttingdown, new IntentFilter("shutdown"));
RemoteViews controlButtons = new RemoteViews(context.getPackageName(),R.layout.widget);
Intent playIntent = new Intent(BROADCAST_PLAYPAUSE);
PendingIntent playPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, playIntent, PendingIntent.FLAG_UPDATE_CURRENT);
controlButtons.setOnClickPendingIntent(R.id.bPlay, playPendingIntent);
Intent previousIntent = new Intent(why);
PendingIntent previousPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, previousIntent, PendingIntent.FLAG_UPDATE_CURRENT);
controlButtons.setOnClickPendingIntent(R.id.bprev, previousPendingIntent);
if(ma.NP_List.size()>0) {
controlButtons.setTextViewText(R.id.song, ma.NP_List.get(ma.position).song);
controlButtons.setTextViewText(R.id.artist, ma.NP_List.get(ma.position).getArtist());
Intent open_activityIntent = new Intent(BROADCAST_open_activity);
PendingIntent openactivityPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, open_activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
controlButtons.setOnClickPendingIntent(R.id.parent, openactivityPendingIntent);
if(ma.boolMusicPlaying1 == true) {
controlButtons.setImageViewResource(R.id.bPlay, R.drawable.pause2);
} else {
controlButtons.setImageViewResource(R.id.bPlay, R.drawable.play);
}
} else if(ma.NP_List.size() == 0) {
controlButtons.setTextViewText(R.id.song, "");
controlButtons.setTextViewText(R.id.artist, "");
}
Intent nextIntent = new Intent(BROADCAST_SWAP);
nextIntent.putExtra("nextprev", 1);
PendingIntent nextPendingIntent = PendingIntent.getBroadcast(context, 0, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
controlButtons.setOnClickPendingIntent(R.id.bNext, nextPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, controlButtons);
}
public BroadcastReceiver broadcastCoverReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent serviceIntent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
ComponentName thisWidget = new ComponentName(context.getApplicationContext(), MyWidget.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
if (appWidgetIds != null && appWidgetIds.length > 0) {
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
};
You should use android app widget and not use broadcasts since it is the most conventional way of doing it....which is also mentioned in the docs
You should bind and unbind background service on onResume and onPause respectively in Activity.
Visit Android Activity and Service relationship - after Pause, after Stop to get to know relationship between Service and Activity

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 AppWidget: new instance freezing old one

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

Categories

Resources