I'm a little confused with Android app widgets. I understand that I can create a button to start an activity, but I don't see how I can create a button to edit the text of a TextView inside the widget.
Can someone please tell me what I'm missing?
Thanks a lot in advance.
EDIT:
I don't mean for the user to input the new text, I mean for the application to change the text automatically, without any UI (i.e., dialog boxes or activities).
EDIT:
OK, so you set a getBroadcast PendingIntent on your button with setOnClickPendingIntent and perform your update (or call your update method) with the new text from the receiver. Your AppWidgetProvider class can be your receiver (you can catch your intent in onReceive), otherwise you create a new class that extends BroadcastReceiver.
EDIT2 (sample code):
I didn't run/compile this code so hopefully it will not have errors.
This is a simple helper method to get a basic update pending intent with a custom action:
public PendingIntent getRefreshPendingIntent(Context context, int appWidgetId){
Intent intent = new Intent("my.package.ACTION_UPDATE_WIDGET");
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Catch the custom action in onReceive in your overridden AppWidgetProvider class
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
//handle other appwidget actions
if (intent.getAction().equals("my.package.ACTION_UPDATE_WIDGET")) {
//some code here that will update your widget
}
//handle other appwidget actions
}
You will also need to add an IntentFilter for the custom action to your manifest in the appwidget receiver declaration
<receiver
android:name="my.package.MyWidgetProviderClass"
android:label="MyWidget">
<intent-filter>
<action android:name="my.package.ACTION_UPDATE_WIDGET"/>
<!-- other intent filters -->
</intent-filter>
<!-- meta data pointing to widget xml file -->
</receiver>
Finally you apply the pending intent to your RemoteViews where ever you are building it so when the button is clicked it will send the my.package.ACTION_UPDATE_WIDGET action, which will be caught by your AppWidgetProvider, where you can (or call a method to) perform your AppWidget update
myRemoteViews.setOnClickPendingIntent(R.id.id_of_update_button, getRefreshPendingIntent(context, appWidgetId);
This code updates the widget when you click on it , you can edit it and change the listener to your button :
public class MyWidgetProvider extends AppWidgetProvider {
private static final String ACTION_CLICK = "ACTION_CLICK";
#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);
}
}
}
the complete tutorial is here.
Related
How can i go to my App when i click on AppWidget
I saw no. of questions how to create widget in android home,but after craeting widget how to go to my app while clicking on that i didn't get from anyone of that.Please give me the guidelines to achieve this.
Thanks,
Since it is an AppWidget setting an onClickListener won't work. Instead you have to set an onClickPendingIntent on a specific view.
See the following code for the necessary steps (you should put this code into your onUpdate() method):
// Inflate the Widget layout
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.your_widget_layout);
// Create and set the Intent
Intent intent = new Intent(context, MyClass.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
// Add intent to a view (like a button)
remoteViews.setOnClickPendingIntent(R.id.your_button, pendingIntent);
Please note: The code only shows the relevant parts
As greenapps say :
Add a listener in your widged's view (e.g : click)
Create an intent and put extra information (e.g witch item is clicked)
Then start your activity.
e.g
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//...
Intent intent = new Intent(context, YourActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setOnClickPendingIntent(R.id.widget_layout, pendingIntent);
//...
}
}
I want to combine my widget and one of my android application..
Is it possible to do that?
My plan is, once user open up my android widget, the widget will directly open up my android application?
Is there any way how?
I made some method here from my widget class:
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
Intent intent = startActivity(new Intent("com.xxx.yyy.widget.FlamingoActivity"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget1);
views.setOnClickPendingIntent(R.id.Image, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
I tried to call the second app, FlamingoActivity, but its failing.. :(
NOT THE FULL SOLUTION:
I should change this line
Intent intent = startActivity(new Intent("com.xxx.yyy.widget.FlamingoActivity"));
to this:
Intent intent = new Intent(context, FlamingoActivity.class);
You need to set an onClickpendingIntent on your widget
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);
And also See this question Launching activity from widget
The activity that you are trying to call needs to be public (exported) in the manifest of its app. There is nothing special about starting activities from a widget, other than the fact that you use a PendingIntent to allow the widget to work as a part of your app (it runs inside the launcher app).
public class ExampleAppWidgetProvider extends AppWidgetProvider {
#Override
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];
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
Intent intent = new Intent(context, Fragment_testActivity.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);
views.setOnClickPendingIntent(R.id.button1, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app
// widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Why doesn't the button1 trigger onUpdate (nor onReceive) when the widget is added to the homescreen and button1 is clicked? Adding/removing the widget triggers those events, but not clicking the button.
Manifest, widget declaration, widget layout declaration
First thing I see:
new Intent(context, Fragment_testActivity.class);
You specify an activity as the receiving component. The activity has nothing to do with the update process. Try to set ExampleAppWidgetProvider as the component of the intent or don't specify a component at all (e.g. by using new Intent()).
I have a widget that has a refresh button and a textview. Refresh updates the content and when user clicks on textview it starts a new activity.
Problem is it works fine for a few hours and then onclick and refresh button doesn't do anything. Nothing is captured in logcat. Also If user deletes widget and put a new one it starts working for a few hours and then the same story :(...what am I doing wrong!
Broadcast receiver.
onUpdate
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
long interval = getrefresInterval();
final Intent intent = new Intent(context, UpdateService.class);
final PendingIntent pending = PendingIntent.getService(context, 0, intent, 0);
final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pending);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),interval, pending);
// Build the intent to call the service
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
// To react to a click we have to use a pending intent as the
// onClickListener is excecuted by the homescreen application
Intent ClickIntent = new Intent(context.getApplicationContext(),widgetHadith.class);
Intent UpdateIntent = new Intent(context.getApplicationContext(),UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context.getApplicationContext(), 0, ClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntentUpdate = PendingIntent.getService(context.getApplicationContext(), 0, UpdateIntent,
PendingIntent.FLAG_UPDATE_CURRENT); //use this to update text on widget. if use this put UpdateService.class to intent
remoteViews.setOnClickPendingIntent(R.id.widget_textview, pendingIntent);
remoteViews.setOnClickPendingIntent(R.id.widget_refresh, pendingIntentUpdate);
// Finally update all widgets with the information about the click listener
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
// Update the widgets via the service
context.startService(intent);
}
onReceive
public void onReceive(Context context, Intent intent) {
// v1.5 fix that doesn't call onDelete Action
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
final int appWidgetId = intent.getExtras().getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
this.onDeleted(context, new int[] { appWidgetId });
}
} else {
super.onReceive(context, intent);
}
}
onDelete
public void onDeleted(Context context, int[] appWidgetIds) {
// Toast.makeText(context, "onDelete", Toast.LENGTH_SHORT).show();
super.onDeleted(context, appWidgetIds);
}
Service onstart where I am updating
#Override
public void onStart(Intent intent, int startId) {
RemoteViews updateViews = new RemoteViews(this.getPackageName(),R.layout.widget);
processDatabase();
Spanned text = LoadHadith();
String hadith = text.toString();
Log.d("BR", "service---> ");
// set the text of component TextView with id 'message'
updateViews.setTextViewText(R.id.widget_textview, text);
//Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(this, HelloWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
The problem is that you can't do a partiall update for a widget, you must set all the widget features, such as the set of PendingIntent's every time you push a new remoteView.
(Partiall updates are only available for API14 and up...).
The reason your widgets are loosing their pendingIntents is that the android system saves the remoteView, and rebuilds your widget with it, in case it resets the widget (shortage of memmory, TaskManager/taskKiller in use, etc...), so you must set all the update code for the widget in the remoteView in your updateService.
Otherwise, it's just won't set the pendingIntents again.
So just add the code setting the pendingIntents to the service and your problem will be solved =]
I want to be able to click on a widget and launch a dialog box. I have read the official documentation as some of the unofficial ones. I initially wanted to launch a new activity but even this fails. I get the following in Logcat but I cant really see anything.
11-14 21:28:47.929: INFO/ActivityManager(116): Starting: Intent { flg=0x10000000 cmp=com.android.app/.Execute bnds=[179,89][300,160] } from pid -1
I guess the above means that the intent was passed... But the activity was actually not started. Should the activity to be started be a normal one?
The code used is:
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);
}
}
}
Any thoughts?
The most likely cause of the problem would be that you haven't declared ExampleActivity in your Manifest.
<UPDATE>
You could also try using a unique number for argument 2 of your PendingIntent creation and also put a sensible flag in argument 4:
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT );