Posted: Mon Nov 30, 2009 5:08 pm Post subject: Simple Problem With Intent Extras
Hello,
I'm working on an app widget for the home screen. I'm trying to make it so when a user taps on the widget it changes the data being displayed in the widget. However, I'm also allowing multiple instances of widgets open with different data. So in order to tell my method which widget to update, I'm adding an extra to the intent that is launched to change the data.
Here's the intent I have:
Java:
Intent changeData = new Intent("com.tonycosentini.mintdroid.CHANGE_DATA");
changeData.putExtra("widget_id", currentWidgetId);
PendingIntent changeDataPendingIntent = PendingIntent.getBroadcast(this, 0, changeData, 0);
//This will return the correct value, but if I call it in my onreceive() method it won't.
Log.v(TAG, "stored id is: " + changeData.getIntExtra("widget", 0);
This correctly stores the widget id, but when the change data method is called, the widget id that is read from the intent is the first widget instance. That is, there is is a for loop that generates all of the widgets and no matter what widget you tap, the widget id that is recieved is always the first widget id in the first widget.
Anyone have an idea on how to solve this? Hopefully I didn't word it too poorly.
Thanks for reading,
Tony
This is a known issue with PendingIntents; when Android compares PendingIntents it does not compare Intent extras, so you can't schedule the same basic Intent multiple times with only different extras. Right now, you can only solve this by making the Intent unique in some way other than extras, such as adding extra information to the Intent data.
There's a little bit of discussion of this on the Google Android Group: http://groups.google.com/group/android-developers/browse_thread/thread/81100da6ddb21136
Related
My application hosts user installed widgets, same as a launcher application.
Once I bind the widget, everything works fine. Widgets are created, updated automatically, I can click to navigate inner views.
Everything keeps working fine, until I update my application from Play store (or manually with a signed APK).
After the update, the widgets still show but they won't update anymore. Some widgets function when I click on them but the view is stuck and never gets updated until I re-create the widget (get a new ID and bind it).
I tried forcing an update using
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setComponent(appWidgetInfo.provider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]
{appWidgetId});
context.sendBroadcast(intent);
but that doesn't help...
I wanted to try a forced update on click but I couldn't find any way to get the widget's RemoteViews (as this is not my widget, I just host it).
RemoteViews views =
new RemoteViews(context.getPackageName(),R.layout.mywidget_layout);
Intent updateIntent = new Intent();
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateIntent.putExtra(myWidgetProvider.WIDGET_IDS_KEY, ids);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.view_container, pendingIntent);
Also implemented an AppWidgetProvider to listen to widgets' ID changes (APPWIDGET_HOST_RESTORED) but it doesn't get called on my application update.
My next step would be to re-create all widgets after application update, but I really prefer not to do so.
Would appreciate any help!
Solved.
The last thing I wanted to do, was probably the first thing I should have tried.
I moved on to re-creating the widgets and I found that I don't have to fully re-create them, just re-call bindAppWidgetIdIfAllowed() with the same Widget ID I already have.
The method will return true if everything is still OK and if not, the widget may not be installed anymore or you need to trigger its configuration screen.
Certain Android functionality will break if the widget is installed on the SD Card. Try moving it to the device storage and re-test.
make sure you use unique keys with putExtra(MyWidgetProvider.WIDGET_ID_KEY, ids);
Do not use putExtra(AppWidgetManager.EXTRA_WIDGET_IDS, ids);
Im developing an application where in I have 2 text views and a button.
when I click the button, it should open default system contacts application and upon selecting a contact, it should display the name and number in the text fields respectively.
Now I have implemented ContactsContract and getContentResolver. But, I have seen other apps having this feature, which is quite easy because you need not create a list view and stuffs.
Now how do I start? how do I invoke default contact app and retrieve data from it.
I don't know the details about your problem, but I am pretty sure that you need to use an Implicit Intent (because the Contacts app may be different on different devices). Hopefully this page will help.
You may need to start by using this code:
Intent i = new Intent(); // Declare intent
// Start the intent
startActivity(i);
You may want to use ACTION_GET_CONTENT.
Thanks for the replies. I found out that this is what i need.
Intent localIntent = new Intent("android.intent.action.PICK",ContactsContract.Contacts.CONTENT_URI);
This question already has answers here:
What is an Intent in Android?
(14 answers)
Closed 8 years ago.
I dont know much about intent (or android) so.. Can someone please explain me what is it exactly? i have search on the internet, A LOT.
Also what does each line of this code do?
Intent intent = new Intent (this, DisplayMessageActivity.class);
intent.putExtra("a", "b");
Thanks in advance
I suggest reading Android Intents
You couldn't have search for very long, since this is very basic topic.
I suggest you read more of Android's API guides.
Line 1 = Create message that describes what to do, in this case start "DisplayMessagActivity"
Line 2 = Add content to the message
Intent intent = new Intent (this, DisplayMessageActivity.class);
For this line, its function is to create a navigation from the current activity/page to the displaymessageactivity page.
it is like from here to there.
For this intent.putExtra("a", "b"); the purpose of this is to put like a temp storage/variable to pass to the next page for retrieval. In this case, you put the value "b" in the variable "a". With this method, you can use the value on the other activity or page.
All the above are just storing of info, it is not executed yet. if you want to execute the intent do the following
startActivity(intent);
The best example to state the behavior of Intent is it behaves like a POSTMAN that delivers message to the stated address.
Whether it may be calling service ,BroadCastRecivers ,Activity they are used in number of occassion.
Intents are asynchronous messages which allow application components
to request functionality from other Android components. Intents allow
you to interact with components from the same applications as well as
with components contributed by other applications. For example, an
activity can start an external activity for taking a picture.
Intents are objects of the android.content.Intent type. Your code can
send them to the Android system defining the components you are
targeting. For example, via the startActivity() method you can define
that the intent should be used to start an activity.
An intent can contain data via a Bundle. This data can be used by the
receiving component.
Intents can be used to start Service, call Activty, call Sub Activity, transfer the data between Activity or retrieve the data from Activity
I have an app that has a notification generator. I'm able to receive and generate multiple notifications. my problem now is how can I know which notification that was clicked by user? each notification might act differently, and there might be at most 5 notifications at the same time in my app. I've searched online and found nothing about onClick event with notification....
I found thatonNewIntent can help, but it is not stable...since the activity might get killed by system before user clicks the notification.
can someone please help??
thanks!!
I suggest you make add data to the intent you add to the notification's intent.
For example.
intent.putExtra("Notification_id", id) //You can make this id the system time or some unique identifier.
(Or you can add this to your bundle of extras instead of just putting the extra.)
Then when you go to open the intent you can check the id.
id = intent.getExtra("Notification_id")
Hope this helps. Let me know if you have any questions or need more details.
UPDATE: You have to add data for in the intent and read it later both in your onNewIntent() and onResume(). You then remove the extra from the intent after you did whatever it is you need to do. Also adding some kind of unique data like System.currentTimeMillis() then it will prevent the intent from being reused.
Well this is driving me crazy. I have developed an App-widget. Everything is working fine.
I have a configuration activity which launches every time a widget is added on the home screen and works beautiful. I save the user settings per widget id etc.
The widget has some buttons, one of them launches an activity with about information, the "About Activity".
The "About Activity" has a button which I want to use to launch the configuration activity for the widget id that launched the "About Activity". The reason I want to do that is because I want the user to be able to configure the contents of any instance of my widget without having it removed and added again (in order to launch the configuration activity).
The configuration activity needs the AppWidgetManager.EXTRA_APPWIDGET_ID in order to make the job (save the user settings for this specific widgetid) so I must somehow pass this extra when I 'm calling it from another activity. The obvious think to do is this:
startActivity(new Intent(context,act_configure.class).putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, ??? ));
Now my question is where is the widgetid? I found a million ways to get the widgetids (the array) but not a single clue on how to get the specific widgetid which launched the "About Activity"
Any help about this will make the hours I spent to find a solution, worth something. Thank you in advance.
p.s. Please forgive my English as they are not my native language...
Thanks to Cory Chaltron here is the solution to my problem.
In the widget provider onUpdate method I should create a "unique" intent to pass to the pending intent which handles the launch of the about activity. Because of the way Android compares Intents, passing the WidgetID in the extras IS NOT ENOUGH, you should also pass it as data to the intent in order to be unique. So here is the code:
Intent aboutIntent = new Intent(cx, act_about.class);
aboutIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetIds[i]);
// Make this unique for this appWidgetId
aboutIntent.setData(Uri.withAppendedPath(Uri.parse("customuri://widget/id/"), String.valueOf(widgetID)));
PendingIntent aboutPendingIntent = PendingIntent.getActivity(cx, 0, aboutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.cmdabout, aboutPendingIntent)
Although I answer my own question I am not accepting it because it is based on Cory's answer. Thank you all for the help...
How are you setting your widget views? I have an app where I iterate over the active widgets and configure set the RemoteView there. You could set your widget id in the onClick you are attaching to the "About" button.
final AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
final ComponentName widgetName = new ComponentName(this, WidgetProvider.class);
final int[] widgetIds = widgetManager.getAppWidgetIds(widgetName);
for (int widgetId : widgetIds) {
final RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.widget);
// This is the important part :-D
remoteViews.findViewById(R.id.your_about_button).setOnClickListener(... a listener to start your about activity that puts the widget id in the extra like you suggest in your question ...);
widgetManager.updateAppWidget(widgetId, remoteViews);
}