I would like to create a pending intent for my app widget view that will launch a sharing intent. The problem is that there is no reference to any activity in the android.appwidget.AppWidgetProvider class. The code below does not work because I don't have access to the MainMenuActivity class. Any ideas, is this even possible?
Intent shareIntent = ShareCompat.IntentBuilder.from(MainMenuActivity.this)
.setText("Some text")
.setType("text/plain")
.getIntent();
PendingIntent actionPendingIntent = PendingIntent.getActivity(context, 0, shareIntent, 0);
views.setOnClickPendingIntent(R.id.widget_layout, actionPendingIntent);
Pass in the Context supplied as a parameter to your onUpdate() method to the from() method on ShareCompat.IntentBuilder.
UPDATE
Sorry, it looks like ShareCompat.IntentBuilder will only work with Activity, not a generic Context like most other things in Android. Hence, you will not be able to use it from an app widget.
Related
I can't find a way to pass extras from widget to Activity properly.
I wan't to open activity on button click with some extras passed.
Intent intent = new Intent(context, CreateOperationsActivity.class);
intent.putExtra("someKey", true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, Constants.RequestCodes.CREATE_OPERATIONS, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.add_expense_button, pendingIntent);
Activity is opened, but there is no extra in the Intent.
The only way I was able to pass that extra was seting PendingIntent flag to PendingIntent.FLAG_ONE_SHOT but then widget button works only wonce, clicking it further takes no action.
How to do that so the extra is intercepted by Activity and the button works each time?
You're probably missing setAction() for your Intent ;) See this one for a better explanation: https://stackoverflow.com/a/3128271/515423
I've got some weird behavior and I can only assume is because of the Pending intents I am using.
Scenario
I have a widget (4x1) which has 4 buttons. Within onUpdate of the widget, I add an pending intent for each button. My intents fires a Service with a bundeled parameter and depending on this parameter starts something. I attach intents as this:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Bundle b = new Bundle();
b.putString("myVariable", someVariable);
Intent intent = new Intent(context, AppStarterService.class);
intent.putExtras(b);
PendingIntent pendingIntent = PendingIntent.getService(context, buttopnPosition, intent, 0);
views.setOnClickPendingIntent(R.id.btnOne, pendingIntent);
The problem
The code works just fine, until the user decides to update the content of the button. Then, a new Pending Intent is done. So, when I press again the button, sometimes it still executes the old intent and not the new one. I don't know how to explain this better. Let's say for my first intent the parameter is "TestOne", after my update, the new intent has parameter "TestX". When the user clicks on the button, on my service I get in intent extras still "TestOne" instead "TestX". So, my guess is that somehow, I need to cancel the previous intent, when the widget button content changes.
Is this the issue ? Am I doing something wrong ? How do I cancel the old intent, I need to recreate it and then cancel it ?
Thank you for your time.
I you keep having this problem even with FLAG_UPDATE_CURRENT, try defining a different requestCode each time, with something like this:
private static int request = 0;
...
PendingIntent pendingIntent = PendingIntent.getService(context, request++, intent, 0);
So each time a new PendingIntent is created, a new requestCode is used, at least during class life.
I hope it helps.
I think you want to set the flag http://developer.android.com/reference/android/app/PendingIntent.html#FLAG_UPDATE_CURRENT as the last parameter to PendingIntent.getService
I get this exception in my code:
...IllegalArgumentException...Cant use FLAG_RECEIVER_BOOT_UPGRADE here...
Looking into the android source code seems like you can't set flags to an Intent that will be fired through:
PendingIntent.getBroadcast(...);
Here the Android source code:
...
if (type == INTENT_SENDER_BROADCAST) {
if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
throw new IllegalArgumentException("Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
}
}
...
Here my code:
Intent myIntent = new Intent(context, MyReceiver.class);
//myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if i remove the comment it doesn't work
PendingIntent pending = PendingIntent.
getBroadcast(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
The reason is not clear to me, anyone could clarify it for me please?
When you get a PendingIntent using getBroadcast(), this Intent will be broadcast to BroadcastReceivers. It will NOT be used to start an Activity. So you cannot set any of the Activity-related flags. They wouldn't make any sense in that context anyway.
Why would you want to set FLAG_ACTIVITY_NEW_TASK in an Intent that will be broadcast? That makes no sense.
Android uses Intents for 3 completely different purposes:
Starting/Communicating with Activity
Starting/Communicating with Service
Broadcast to BroadcastReceiver
The PendingIntent class offers 3 different methods to get a PendingIntent for each of these different purposes:
getActivity()
getService()
getBroadcast()
You need to make sure that you use the right method for the right purpose.
And yes, you can can set Activity-related Intent flags in a PendingIntent, as long as you call getActivity() to get the PendingIntent.
How do i launch an activity from an AppWidget? I want to give the user the ability to edit its settings.
All the AppWidget methods have a Context: you can use that to create an Intent to launch your Activity.
EDIT: strictly speaking, you don't even need the Context (just create an Intent and then call startActivity).
you can find a lot of examples around the internet this example is excellent courtesy of Mark Murphy
https://github.com/commonsguy/cw-advandroid/tree/master/AppWidget
You have to do something like this:
Intent intent = new Intent(context, MainWidgetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.appwidget);
rv.setOnClickPendingIntent(R.id.button, pendingIntent);
while MainWidgetActivity.class is the Activity you want to launch
I have a WidgetProvider and an Configure Activity
When the Widget is started it starts with the configure activity and I set it up by making a custom call to the widgetprovider
(which you will notice is from the sdk tutorial examples)
// Push widget update to surface with newly set prefix
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
AwarenessWidget.updateAppWidget(context, appWidgetManager,
mAppWidgetId, position);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
I pass the Widget ID to the function.... inside the widget I create a Intent like this:
Intent configIntent = new Intent(context, Configure.class);
configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity
(context, 0, configIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.MainImage,pendingIntent);
views.setImageViewResource(R.id.MainImage, lv_images[version]);
appWidgetManager.updateAppWidget(appWidgetId, views);
I am always referencing the widget ID and even add it as a extra on the intent
but when I get two of these widgets on the home screen the widget ID is always referencing the last placed widget ID
I had a similar problem. Just add this to your config activity, where you set your PendingIntent:
Uri data = Uri.withAppendedPath(
Uri.parse(URI_SCHEME + "://widget/id/")
,String.valueOf(appWidgetId));
intent.setData(data);
The variable URI_SCHEME is a String, and can be whatever you'd like.. ie - "ABCD" This causes each widget to have a unique PendingIntent.
Here is a more in-depth explanation of why your code doesn't work and how to fix it. From the Android SDK Documentation:
A PendingIntent itself is simply a reference to a token maintained by
the system describing the original data used to retrieve it. This
means that, even if its owning application's process is killed, the
PendingIntent itself will remain usable from other processes that have
been given it. If the creating application later re-retrieves the same
kind of PendingIntent (same operation, same Intent action, data,
categories, and components, and same flags), it will receive a
PendingIntent representing the same token if that is still valid, and
can thus call cancel() to remove it.
Because of this behavior, it is important to know when two Intents are
considered to be the same for purposes of retrieving a PendingIntent.
A common mistake people make is to create multiple PendingIntent
objects with Intents that only vary in their "extra" contents,
expecting to get a different PendingIntent each time. This does not
happen. The parts of the Intent that are used for matching are the
same ones defined by Intent.filterEquals. If you use two Intent
objects that are equivalent as per Intent.filterEquals, then you will
get the same PendingIntent for both of them.
Note that specifying differing "extra" contents isn't enough for the PendingIntents to be considered unique, but setting a unique URI with setData is. That is why Snailer's URI solution "magically" fixes the problem.
The documentation also offers a different (arguably simpler) solution to the problem. Instead of creating a custom URI just set a unique requestCode when you call getActivity:
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Source: http://developer.android.com/reference/android/app/PendingIntent.html
In my testing, using the setData(...) on the PendingIntent doesn't fix the issue on a Verizon Thunderbolt running Android 4.0.4. It works on my other test devices and emulator.
I tested the use of the requestCode instead, and it works in all cases. I just set the requestCode to be the widget ID:
pendingIntent = PendingIntent.getService(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);