I have a homescreenwidget in Android with two buttons. Both buttons should call the same activity ( class ) just use a different intent plus intent extras, to know which button called the class.
For now only button1 is working and calling the activity. I also receive the keyvalue in the called Activity.
How can i make the second button work?
Here's my code:
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for ( int i =0; i<appWidgetIds.length ; i++){
int appWidgetId = appWidgetIds[i];
Intent intent2 = new Intent(context, Main.class);
Intent intent1 = new Intent(context, Main.class);
// Intent put extras Button 1
String bread1 = "secure";
Bundle basket1 = new Bundle();
basket1.putString("key", bread1);
intent1.putExtras(basket1);
// Intent put extras Button 2
String bread2 = "insecure";
Bundle basket2 = new Bundle();
basket2.putString("key", bread2);
intent2.putExtras(basket2);
PendingIntent pending1 = PendingIntent.getActivity(context,0,intent1, 0);
PendingIntent pending2 = PendingIntent.getActivity(context, 0, intent2, 0);
RemoteViews views1 = new RemoteViews(context.getPackageName(),R.layout.maina);
RemoteViews views2 = new RemoteViews(context.getPackageName(),R.layout.maina);
views1.setOnClickPendingIntent(R.id.button1, pending1);
views2.setOnClickPendingIntent(R.id.button2, pending2);
appWidgetManager.updateAppWidget(appWidgetId, views1);
appWidgetManager.updateAppWidget(appWidgetId, views2);
here is the maina.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1" android:orientation="vertical">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:id="#+id/tvWidget" android:textAppearance="?android:attr/textAppearanceLarge"></TextView>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1" android:orientation="horizontal">
<Button android:text="#string/button1" android:id="#+id/button1" android:layout_height="wrap_content" android:layout_width="wrap_content"></Button>
<Button android:text="#string/button2" android:id="#+id/button2" android:layout_height="wrap_content" android:layout_width="wrap_content"></Button>
</LinearLayout>
</LinearLayout>
#Arnold you have created 2 PendingIntent which are....
PendingIntent pending1 = PendingIntent.getActivity(context,0,intent1, 0);
PendingIntent pending2 = PendingIntent.getActivity(context, 0, intent2, 0);
Where PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags) has 4 parameters. You have to send different "requestCode" for different PendingIntents.
Your code should be....
PendingIntent pending1 = PendingIntent.getActivity(context,0,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pending2 = PendingIntent.getActivity(context, 1, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
in the main class you need to create this...
String value;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle b=intent.getExtras();
try{
value=b.getString("key");
}
catch (Exception e) {
// TODO: handle exception
}
super.onReceive(context, intent);
}
with the onUpdate code....
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context,
main.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// Create some random data
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.main);
// Register an onClickListener for 1st button
Intent intent = new Intent(context, main.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,allWidgetIds);
intent.putExtra("key", "1st Button");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.button1, pendingIntent);
// Register an onClickListener for 2nd button............
Intent intent2 = new Intent(context, main.class);
intent2.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,allWidgetIds);
intent2.putExtra("key", "2nd Button");
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context,
1, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.button2, pendingIntent2);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
Then you can check whether value=1st Button or value=2nd Button to know which Button has been clicked.
It should work... IF it does not work please let me know what is the problem...
I had a similar problem with using 2 buttons on a widget. I set OnClickPendingIntents on both of them, distinguished by different setExtra() calls. But only the latter intent was called, even when clicking the first button.
I found 2 solutions:
- assign different actions to both PendingIntents
- on the second PendingEvent set the PendingEvent.FLAG_CANCEL_CURRENT flag
I am quite unfamiliar with PendingEvents and Widgets, so I can't see the pros and cons and will stick to the first solution.
Maybe that might help you with your problem, too.
Your widget will only have 1 remote view. Try changing the end of your code snippet to:
RemoteViews remoteView = new RemoteViews(context.getPackageName(),R.layout.maina);
remoteView.setOnClickPendingIntent(R.id.button1, pending1);
remoteView.setOnClickPendingIntent(R.id.button2, pending2);
appWidgetManager.updateAppWidget(appWidgetId, remoteView);
Failing that, it would be useful to see your layout in R.layout.maina.
In my case:
remoteViews.setOnClickPendingIntent(R.id.widget_head, touch_man(context));
remoteViews.setOnClickPendingIntent(R.id.widget_head2, touch_woman(context));
public static PendingIntent touch_man(Context context) {
Intent intent = new Intent();
intent.setAction("touch_man");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static PendingIntent touch_woman(Context context) {
Intent intent = new Intent();
intent.setAction("touch_woman");
return PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
In AndroidManifest
<receiver
android:name="Receiver"
android:label="widgetBroadcastReceiver" >
<intent-filter>
<action android:name="touch_man" />
<action android:name="touch_woman"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/demo_widget_provider" />
</receiver>
It's working.
Related
The Problem
I've implemented this code AppWidgetListView and I've tried to attach clicks.
What's going well: so, clicks from buttons from widget but outside the ListView, works. You can see the click result from that buttons on OnReceive method from a class (WordWidget) that implemented AppWidgetProvider.
what does not work: when you click an item (or an element from that item) from ListView, it doesn't show a thing.
Attempts:
Example 1
Intent configIntent = new Intent(context, typeof(WordWidget));
configIntent.PutExtra("appWidgetId", ids[i]);
PendingIntent configPendingIntent = PendingIntent.GetActivity(context, 0, configIntent, 0);
remoteViews.SetOnClickPendingIntent(Resource.Id.button, configPendingIntent);
Example 2
Intent active = new Intent(context, typeof(WordWidget));
active.SetAction("aaa");
PendingIntent actionPendingIntent = PendingIntent.GetBroadcast(context, 0, active, 0);
remoteViews.SetOnClickPendingIntent(Resource.Id.button, actionPendingIntent);
Example 3
var intent = new Intent(context, typeof(WordWidget));
intent.SetAction(AppWidgetManager.ActionAppwidgetUpdate);
intent.PutExtra(AppWidgetManager.ExtraAppwidgetIds, ids);
var piBackground = PendingIntent.GetBroadcast(context, 0, intent, PendingIntentFlags.UpdateCurrent);
remoteViews.SetOnClickPendingIntent(Resource.Id.button, piBackground);
Example 4
var intent = new Intent(context, typeof(WordWidget));
intent.SetAction("test");
remoteViews.SetOnClickPendingIntent(Resource.Id.button, PendingIntent.GetBroadcast(context, 0, intent, 0));
Example 5
Intent intent = new Intent(Intent.ActionView, Android.Net.Uri.Parse("https://google.com"));
remoteViews.SetOnClickPendingIntent(Resource.Id.button, intent);
I've tried to replace typeof(WordWidget) with typeof(MainActivity) and it does not work. and I've tried to put that codes on public RemoteViews GetViewAt(int position) from ListProvider where the item layout is built and it does not work.
As a test, I implemented the following function: When clicking on the ListView, enter the main page of the APP.
You can refer to the following code:
We need to call SetOnClickFillInIntent to differentiate the item on-click behavior.
In ListProvider.cs
public RemoteViews GetViewAt(int position)
{
RemoteViews remoteView = new RemoteViews(
context.PackageName, Resource.Layout.list_row);
ListItem listItem = listItemList[position];
remoteView.SetTextViewText(Resource.Id.heading, listItem.heading);
remoteView.SetTextViewText(Resource.Id.content, listItem.content);
// add code here
Bundle extras = new Bundle();
extras.PutInt("position", position);
Intent fillInIntent = new Intent();
fillInIntent.PutExtras(extras);
// Make it possible to distinguish the individual on-click
// action of a given item
remoteView.SetOnClickFillInIntent(Resource.Id.item_frame, fillInIntent);
return remoteView;
}
Note: Here item_frame is the id of root element of list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:id="#+id/item_frame"
android:background="#android:color/darker_gray" >
In WidgetProvider.cs
Here,we set the pending intent in OnUpdate method
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
base.OnUpdate(context, appWidgetManager, appWidgetIds);
int N = appWidgetIds.Length;
for (int i = 0; i < N; i++)
{
RemoteViews remoteViews = updateWidgetListView(context, appWidgetIds[i]);
// we add code here
Intent activityIntent = new Intent(context, typeof(MainActivity));
// activityIntent.SetPackage(context.PackageName);
// Set the action for the intent.
// When the user touches a particular view.
//activityIntent.PutExtra(AppWidgetManager.ExtraAppwidgetId, appWidgetIds[i]);
//activityIntent.SetData(Android.Net.Uri.Parse(activityIntent.ToUri(Android.Content.IntentUriType.AndroidAppScheme)));
PendingIntent pendingIntent = PendingIntent.GetActivity(context, appWidgetIds[i], activityIntent, PendingIntentFlags.UpdateCurrent);
remoteViews.SetPendingIntentTemplate(Resource.Id.listViewWidget, pendingIntent);
appWidgetManager.UpdateAppWidget(appWidgetIds[i], remoteViews);
}
}
I am having trouble making my Widget clickable. The following code is working partially. My Widget shows a ListView with Items. When clicking into the Widget where no Item is displayed, the Intent works and the Activity starts. But when clicking on an Item of the ListView nothing happens.
Here is the Code:
WidgetProvicer:
public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
for (final int iD : appWidgetIds) {
final RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout
.widget_layout);
final Intent intent = new Intent(context, TickWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, iD);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setRemoteAdapter(R.id.WidgetItem, intent);
remoteViews.setEmptyView(R.id.WidgetItem, R.id.empty_view);
final Intent activityIntent = new Intent(context, MainActivity.class);
final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, activityIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.Widget, pendingIntent);
appWidgetManager.updateAppWidget(iD, remoteViews);
appWidgetManager.notifyAppWidgetViewDataChanged(iD, R.id.WidgetItem);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
widget_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Widget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#+id/WidgetItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#D3D3D3"
android:dividerHeight="1dp"/>
<TextView
android:id="#+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="#string/emptytext"
android:visibility="gone"/>
</LinearLayout>
The ListViewItems have no Buttons or anything.
Thanks for your help!
finally it is working:
in the Profider onUpdate:
final Intent activityIntent = new Intent(context, MainActivity.class);
final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setPendingIntentTemplate(R.id.WidgetItem, pendingIntent);
and in the ViewsFactory getViewAt:
Bundle infos = new Bundle();
infos.putInt(TickWidgetProvider.WIDGET_LISTID, this.listId);
final Intent activityIntent = new Intent();
activityIntent.putExtras(infos);
remoteView.setOnClickFillInIntent(R.id.widgetListItemLayout, activityIntent);
Do not know where I found it, but this example helped me making it work:
https://github.com/commonsguy/cw-advandroid/tree/master/AppWidget/LoremWidget
I'm using the RemoteViewsService.RemoteViewsFactory (link)
to display a listview in a homescreen widget. Everything works fine and I can capture the clicks on the listview items. Now I want to add a button above the listview to allow the user to jump to a config activity:
This is my widget layout xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dip"
android:background="#drawable/widget_frame"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<ListView android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:layout_marginLeft="0dp"/>
</LinearLayout>
This is my onUpdate method within the WidgetProvider.java class:
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.w(LOG, "onUpdate method called");
for (int i=0; i<appWidgetIds.length; i++) {
Intent svcIntent=new Intent(context, WidgetService.class);
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
// http://stackoverflow.com/questions/13199904/android-home-screen-widget-remoteviews-setremoteadapter-method-not-working
Random generator = new Random();
int randomNumber = generator.nextInt(1000);
svcIntent.putExtra("random", randomNumber);
svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteviews=new RemoteViews(context.getPackageName(), R.layout.widget_layout);
//------------------------------------------------------------------------------------
// trying to capture the button click ... ?
RemoteViews btn_remoteviews=new RemoteViews(context.getPackageName(), R.id.button1);
Intent btn_clickIntent = new Intent(context, Config.class);
btn_clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
//PendingIntent btn_pendingIntent = PendingIntent.getBroadcast(context, appWidgetIds[i], btn_clickIntent, 0);
PendingIntent btn_pendingIntent = PendingIntent.getActivity(context, 0, btn_clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
btn_remoteviews.setPendingIntentTemplate(R.id.button1, btn_pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], btn_remoteviews);
//------------------------------------------------------------------------------------
remoteviews.setRemoteAdapter(appWidgetIds[i], R.id.listview, svcIntent);
Intent clickIntent=new Intent(context, LoremActivity.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
PendingIntent clickPI=PendingIntent.getActivity(context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteviews.setPendingIntentTemplate(R.id.listview, clickPI);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteviews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
How do I capture the button click ???
All the clicks on my listview are captured but I can't capture the click on the button just above the listview ???
Thanks a lot for your help!
As stated in the page provided by you:
This AppWidgetProvider defines only the onUpdate() method for the
purpose of defining a PendingIntent that launches an Activity and
attaching it to the App Widget's button with
setOnClickPendingIntent(int, PendingIntent). Notice that it includes a
loop that iterates through each entry in appWidgetIds, which is an
array of IDs that ide
Also:
As described in Using the AppWidgetProvider Class, you normally use
setOnClickPendingIntent() to set an object's click behavior—such as to
cause a button to launch an Activity. But this approach is not allowed
for child views in an individual collection item (to clarify, you
could use setOnClickPendingIntent() to set up a global button in the
Gmail app widget that launches the app, for example, but not on the
individual list items). Instead, to add click behavior to individual
items in a collection, you use setOnClickFillInIntent(). This entails
setting up up a pending intent template for your collection view, and
then setting a fill-in intent on each item in the collection via your
RemoteViewsFactory.
What about that example from the link that you provided? I didn't read that page carefully (you definitely should), but shouldn't you setOnClickPendingIntent() or setOnClickFillInIntent()?:
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(context, ExampleActivity.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 views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
This is what I ended up doing ...
for (int i=0; i<appWidgetIds.length; i++) {
Intent svcIntent=new Intent(context, WidgetService.class);
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
// http://stackoverflow.com/questions/13199904/android-home-screen-widget-remoteviews-setremoteadapter-method-not-working
Random generator = new Random();
int randomNumber = generator.nextInt(1000);
svcIntent.putExtra("random", randomNumber);
svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteviews=new RemoteViews(context.getPackageName(), R.layout.widget_layout);
//------------------------------------------------------------------------------------
// trying to capture the button click ... ?
Intent btn_clickIntent = new Intent(context, Config.class);
btn_clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
PendingIntent btn_pendingIntent = PendingIntent.getActivity(context, 0, btn_clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteviews.setOnClickPendingIntent(R.id.button1, btn_pendingIntent);
Intent btn2_clickIntent = new Intent(context, Config2.class);
btn2_clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
PendingIntent btn2_pendingIntent = PendingIntent.getActivity(context, 0, btn2_clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteviews.setOnClickPendingIntent(R.id.button2, btn2_pendingIntent);
remoteviews.setRemoteAdapter(appWidgetIds[i], R.id.listview, svcIntent);
Intent clickIntent=new Intent(context, LoremActivity.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
PendingIntent clickPI=PendingIntent.getActivity(context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteviews.setPendingIntentTemplate(R.id.listview, clickPI);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteviews);
}
I am building a widget that has multiple buttons, each one sending off its own intent to a broadcast receiver. The broadcast receiver is suppose to display a Toast message based on which button was pushed. The code currently looks like this:
public class WidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
ComponentName thisWidget = new ComponentName(context, WidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Set the text of the buttons
remoteViews.setTextViewText(R.id.widgetPreset1Button, prefs.getString("widget1", "Not set"));
remoteViews.setTextViewText(R.id.widgetPreset2Button, prefs.getString("widget2", "Not set"));
remoteViews.setTextViewText(R.id.widgetPreset3Button, prefs.getString("widget3", "Not set"));
remoteViews.setTextViewText(R.id.widgetPreset4Button, prefs.getString("widget4", "Not set"));
// Register the buttons with an OnClick event
Intent intent1 = new Intent("myapp.SendWidgetPreset");
intent1.putExtra("Widget", 1);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widgetPreset1Button, pendingIntent1);
Intent intent2 = new Intent("myapp.SendWidgetPreset");
intent2.putExtra("Widget", 2);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widgetPreset2Button, pendingIntent2);
Intent intent3 = new Intent("myapp.SendWidgetPreset");
intent3.putExtra("Widget", 3);
PendingIntent pendingIntent3 = PendingIntent.getBroadcast(context, 0, intent3, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widgetPreset3Button, pendingIntent3);
Intent intent4 = new Intent("myapp.SendWidgetPreset");
intent4.putExtra("Widget", 4);
PendingIntent pendingIntent4 = PendingIntent.getBroadcast(context, 0, intent4, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widgetPreset4Button, pendingIntent4);
new WidgetBroadcastReceiver();
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
}
and the BroadcastReceiver:
public class WidgetBroadcastReceiver extends BroadcastReceiver{
public WidgetBroadcastReceiver(){
}
#Override
public void onReceive(Context context, Intent arg1) {
int widget = arg1.getIntExtra("Widget", -1);
Toast.makeText(context, "Widget pressed: " + widget, Toast.LENGTH_SHORT).show();
}
}
My problem is it always displays Widget pressed: 4 regardless of which button is pressed. If I put the four lines intent4, intent4.putExtra(), pendingIntent4, and remoteViews.setOnClickPendingIntent() above all of the other intents, it will then always say Widget pressed: 3. In other words, whatever the last intent registration is, that is the widget displayed in the Toast message.
Anyone know why this isn't working how I want it?
you need to provide seperate request code for each pendingintent ex:
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 1/*request code*/, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
Your PendingIntents are being overwritten by the next one. THis is because they compare the Intent being encapsulated, and extras are not considered when comparing Intents. Do this for each intent:
Intent intent1 = new Intent("myapp.SendWidgetPreset");
intent1.putExtra("Widget", 1);
// This line makes your intents different
intent1.setData(Uri.parse(intent1.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widgetPreset1Button, pendingIntent1);
Seems like PendingIntent.getBroadcast() will ignore requestCode (unlike PendingIntent.getActivity).
Thus, to make unique PendingIntents you could supply Data for the Intent.
Example:
public static Intent makeUniqueIntent(String action, int requestCode) {
Intent intent = new Intent(action);
intent.setData(Uri.parse("http://"+ String.valueOf(requestCode)));
return intent;
}
Then make your Pending Intent as per usual, including the requestCode.
PendingIntent.getBroadcast(ctx, request_code,
makeUniqueIntent(NotificationReceiver.INTENT, request_code),
PendingIntent.FLAG_CANCEL_CURRENT);
With a Data element in an Intent, a matching Intent Filter within AndroidManifest.xml must also have a Data element:
<receiver android:name=".service.NotificationReceiver">
<intent-filter>
<action android:name="my.package.my_action_string"/>
<data android:scheme="http"/>
</intent-filter>
</receiver>
The above intent-filter works as only a scheme (i.e. "http") was identified. So any Uri with that scheme will match this filter's "data" element and the corresponding Receiver class will be called.
Notes:
NotificationReceiver is my class, extending BroadcastReceiver
NotificationReceiver.INTENT is a String constant I declared in NotificationReceiver. In this example it would equal "my.package.my_action_string";
request_code can be anything. Make it unique & save it if you want to reference this same Pending Intent in the future (say for canceling an alarm that uses it).
More info on Data test with Intent Filters:
http://developer.android.com/guide/components/intents-filters.html#DataTest
i have a widget to my application that is refreshed every 10 sec. If i change the language of the phone, the widget stops working. I mean, the textviews do not load the texts until they are refreshed (so after 10sec). I added a functionality that the user can open the app by clicking on the widget (an ImageView). This problem still stays.
This whole problem appears also when I restart the phone. I have to wait 10 secs for the textviews to load the texts, but I cannot click on the widget. I may change this interval to 1 sec, what would solve this issue (making it almost invisible for the user). But like I said, I still cannot click on the widget.
Here is the full AppWidgetProvider class:
public class HelloWidget extends AppWidgetProvider {
public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
private static final int REQUEST_CODE_ONE = 10;
String elso;
public static String MY_WIDGET_UPDATE = "MY_OWN_WIDGET_UPDATE";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
updateAppWidget(context, appWidgetManager, appWidgetId);
Toast.makeText(context, "onUpdate(): " + String.valueOf(i) + " : " + String.valueOf(appWidgetId), Toast.LENGTH_SHORT).show();
}
Intent intent = new Intent(context, UpdateService.class);
context.startService(intent);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.setAction(ACTION_WIDGET_CONFIGURE);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, REQUEST_CODE_ONE, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.ImageView01, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
Intent myIntent = new Intent(context, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(System.currentTimeMillis());
calendar2.add(Calendar.SECOND, 1);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar2.getTimeInMillis(), 50*1000, pendingIntent);
}
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(MY_WIDGET_UPDATE.equals(intent.getAction())){
Bundle extras = intent.getExtras();
if(extras!=null) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), HelloWidget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
if (appWidgetIds.length > 0) {
new HelloWidget().onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
}
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId){
}
}
From this code this is the part that serves for opening the MainActivity.class of the app when the user clicks on the widget:
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.setAction(ACTION_WIDGET_CONFIGURE);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, REQUEST_CODE_ONE, configIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.ImageView01, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
This is the Manfiest part:
<receiver android:name=".HelloWidget" 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/widget_provider" />
</receiver>
And this is the widget_provider.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dip"
android:minHeight="72dip"
android:updatePeriodMillis="86400000"
android:initialLayout="#layout/main"
/>
I have a widget to my application that is refreshed every 10 sec [...]
I may change this interval to 1 sec [...]
In short: That's very bad practice. You should (at maximum) only update every 30 minutes.
By refreshing your Widget every 10 seconds, you kill the battery so fast that nobody will use it. Instead, you could add an "refresh"-button which then manually refreshes the Widget.
Also, in the onUpdate-method, you don't need to call the super-method.
And the onReceive-method does not need to be overridden! The onUpdate-method is automatically called when you use an AppWidgetProvider (not if you use a normal BroadcastReceiver). See here.
Last but not least, you should check if your "call-Activity"-code gets reached and try to debug it with the Log-class. The LogCat-Output might also help solving this.
Can you add this flag
PendingIntent configPendingIntent = PendingIntent.getActivity(context, REQUEST_CODE_ONE, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Also check Logcat for any exception it throws when you click on the widget.