I'm having trouble setting up a widget to my app, whenever I try to add a widget to my home screen onReceive is being called and right after that onUpdate is being called - but after onUpdate finishes - my custom RemoteViewsService is not called at all...
NotesWidgetProvider.class
public class NotesWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.notes_widget);
Intent intent = new Intent(context, NotesWidgetService.class);
views.setRemoteAdapter(R.id.widget_notes, intent);
Intent clickIntent = new Intent(context, NoteActivity.class);
PendingIntent clickPendingIntentTemplate = TaskStackBuilder.create(context)
.addNextIntentWithParentStack(clickIntent)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_notes, clickPendingIntentTemplate);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_notes);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
ComponentName cn = new ComponentName(context, NotesWidgetProvider.class);
mgr.notifyAppWidgetViewDataChanged(mgr.getAppWidgetIds(cn), R.id.widget_notes);
}
super.onReceive(context, intent);
}
public static void sendRefreshBroadcast(Context context) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setComponent(new ComponentName(context, NotesWidgetProvider.class));
context.sendBroadcast(intent);
}
}
NotesWidgetService.class
public class NotesWidgetService extends RemoteViewsService {
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new NotesRemoteViewsFactory(this.getApplicationContext(), intent);
}
public class NotesRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private Cursor mCursor;
public NotesRemoteViewsFactory(Context applicationContext, Intent intent) {
mContext = applicationContext;
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
if (mCursor != null) {
mCursor.close();
}
final long identityToken = Binder.clearCallingIdentity();
Uri uri = DBHandler.CONTENT_URI;
String [] projection = {Constants.TITLE_COL, Constants.CONTENT_COL, Constants.COLOR_COL, Constants.DATE_COL};
mCursor = mContext.getContentResolver().query(uri, projection, null, null, null);
Binder.restoreCallingIdentity(identityToken);
}
#Override
public void onDestroy() {
if (mCursor != null) {
mCursor.close();
}
}
#Override
public int getCount() {
return mCursor == null ? 0 : mCursor.getCount();
}
#Override
public RemoteViews getViewAt(int i) {
if (i == AdapterView.INVALID_POSITION || mCursor == null || !mCursor.moveToPosition(getCount() - 1 - i)) {
return null;
}
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
rv.setTextViewText(R.id.widget_note_title, mCursor.getString(mCursor.getColumnIndex(Constants.TITLE_COL)));
rv.setTextViewText(R.id.widget_note_content, mCursor.getString(mCursor.getColumnIndex(Constants.CONTENT_COL)));
rv.setInt(R.id.widget_note_body, "setBackgroundColor", Color.parseColor(mCursor.getString(mCursor.getColumnIndex(Constants.COLOR_COL))));
Intent fillInIntent = new Intent();
fillInIntent.putExtra(Constants.POSITION_COL, getCount() - 1 - i);
fillInIntent.putExtra("Code", NoteActivity.EDIT_CODE);
rv.setOnClickFillInIntent(R.id.widget_note_body, fillInIntent);
return rv;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public long getItemId(int i) {
return mCursor.moveToPosition(i) ? mCursor.getLong(0) : i;
}
#Override
public boolean hasStableIds() {
return true;
}
}
}
Manifest
<receiver
android:name=".widget.NotesWidgetProvider"
android:label="#string/your_notes">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/notes_widget_info" />
</receiver>
<service
android:name=".widget.NotesWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false"/>
notes_widget_info.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/notes_widget"
android:minHeight="180dp"
android:minWidth="110dp"
android:previewImage="#drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="3600000"
android:widgetCategory="home_screen"/>
What am I missing? Can someone help figure it out?
UPDATE
I figured out that the problem was that I used AppCompat.ImageButton instead of ImageButton, now onGetViewFactory is called - but when reaching onGetViewFactory the widget changes to "Problem loading widget".
It might be too late to answer, but I think your issue come from your notes_widget_info.xml, change it to the following:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/notes_widget"
android:minHeight="180dp"
android:minWidth="110dp"
android:previewImage="#drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="3600000"
android:widgetCategory="home_screen">
</appwidget-provider>
Related
I have an app with a widget showing a listview. I want to update the list based on the recipe that user opens in the app.
To do that first I send a broadcast with an extra integer when activity is open.
Then in widget provider I am setting remote adapter with an intent containing integer received from broadcast.
Now I would expect new RemoteViewsFactory to be created each time so I can extract an integer from an intent and load different list based on this number.
The problem is this only happens when an app is first open, every other time only onDataSetChanged() in MyWidgetRemoteViewsFactory is called so I cannot get the recipe number to update data correctly. The list in widget never gets updated.
How to force widget to recreate RemoteViewsFactory? Based on the other topic on stackoverflow I have tried passing null in appWidgetManager.updateAppWidget(appWidgetId1, null) - this didn't work.
MainListActivity.java - send a broadcast
#Override
public void onItemClickListener(int itemID) {
Intent recipeIntent = new Intent(this, BakingWidgetProvider.class);
recipeIntent.setAction(BakingWidgetProvider.UPDATE_WIDGET_RECIPE);
recipeIntent.putExtra(StepsListActivity.EXTRA_RECIPE_ID, itemID);
sendBroadcast(recipeIntent);
Intent intent = new Intent(MainListActivity.this, StepsListActivity.class);
intent.putExtra(StepsListActivity.EXTRA_RECIPE_ID, itemID);
startActivity(intent);
}
BakingWidgetProvider.java - Receive broadcast
#Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(UPDATE_WIDGET_RECIPE)) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.baking_widget);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
int viewIndex = intent.getIntExtra(StepsListActivity.EXTRA_RECIPE_ID, 0);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, BakingWidgetProvider.class));
for (int appWidgetId1 : appWidgetIds) {
//trying to pass null to clear the data ?
appWidgetManager.updateAppWidget(appWidgetId1, null);
}
Intent intent2 = new Intent(context, MyWidgetRemoteViewsService.class);
Bundle bundle = new Bundle();
bundle.putInt(StepsListActivity.EXTRA_RECIPE_ID,viewIndex );
intent2.putExtras(bundle);
remoteViews.setRemoteAdapter(R.id.list_view, intent2);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view);
//empty view
remoteViews.setEmptyView(R.id.list_view, R.id.empty_view);
for (int appWidgetId1 : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId1, remoteViews);
}
}
super.onReceive(context, intent);
}
MyWidgetRemoteViewsService.java - get an integer from an intent to update data properly
public class MyWidgetRemoteViewsService extends RemoteViewsService {
private static final String MyOnClick = "myOnClickTag";
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new MyWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
}
class MyWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
List<Recipe> recipeList;
private Context mContext;
private int mRecipeOpen;
public MyWidgetRemoteViewsFactory(Context context, Intent intent) {
mRecipeOpen = intent.getExtras().getInt(StepsListActivity.EXTRA_RECIPE_ID);
mContext = context;
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
recipeList = AppDatabase.getInstance(getApplicationContext()).recipeDao().getAll();
}
#Override
public void onDestroy() {
}
#Override
public int getCount() {
return recipeList.get(mRecipeOpen).ingredients.size();
}
#Override
public RemoteViews getViewAt(int position) {
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item);
rv.setTextViewText(R.id.quantity, recipeList.get(mRecipeOpen).ingredients.get(position).getQuantity());
rv.setTextViewText(R.id.measurement, recipeList.get(mRecipeOpen).ingredients.get(position).getMeasure());
rv.setTextViewText(R.id.ingredient, recipeList.get(mRecipeOpen).ingredients.get(position).getIngredient());
return rv;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return true;
}
}
}
In the end I had to change my approach.
I have placed MyWidgetRemoteViewsFactory in a separate class and extended BroadcastReceiver. Here in onReceive method I can retrieve the broadcast with the required integer that is sent from BakingWidgetProvider.
I saw similar questions here on SO, but nothing seems to work in my case...
I created an appwidget with an AdapterViewFlipper (Simple ViewAnimator that will animate between two or more views that have been added to it). The appwidget has a Next button that enables the user to navigate to the next view on the widget.
It all works fine when I first add the appwidget. But if the smartphone reboots, the Next button of the widget no longer works on my Samsung S4 (the method onReceive is called, but nothings happens, it doesn't navigate to the next view and is stuck at the first view). I have to delete the widget and add it again in order for it to work...
I suspect that it is a problem of Touchwiz since I tested it on another phone (Moto G) and it worked fine.
Here are some portions of my code :
AppWidgetProvider
public class AppWidgetProvider extends AppWidgetProvider {
public static final String NEXT_ACTION = VersionUtil.getPackageName() + ".action.NEXT";
private static final String TAG = DailyAppWidget.class.getSimpleName();
#Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
#Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId, colorValue);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, int primaryColor) {
Intent intent = new Intent(context, ViewFlipperWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
// When intents are compared, the extras are ignored, so we need to embed the extras
// into the data so that the extras will not be ignored.
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
// Instantiate the RemoteViews object for the app widget layout.
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.app_widget);
// open the activity from the widget
Intent intentApp = new Intent(context, MainActivity.class);
intentApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intentApp, 0);
rv.setOnClickPendingIntent(R.id.widget_title, pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
rv.setRemoteAdapter(R.id.adapter_flipper, intent);
} else {
rv.setRemoteAdapter(appWidgetId, R.id.adapter_flipper, intent);
}
// Bind the click intent for the next button on the widget
final Intent nextIntent = new Intent(context,
AppWidgetProvider.class);
nextIntent.setAction(AppWidgetProvider.NEXT_ACTION);
nextIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
final PendingIntent nextPendingIntent = PendingIntent
.getBroadcast(context, 0, nextIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.widget_btn_next, nextPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, mRemoteViews);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(NEXT_ACTION)) {
RemoteViews rv = new RemoteViews(context.getPackageName(),
R.layout.daily_app_widget);
rv.showNext(R.id.adapter_flipper);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
Log.e(TAG, "onReceive APPWIDGET ID " + appWidgetId);
AppWidgetManager.getInstance(context).partiallyUpdateAppWidget(
appWidgetId, rv);
}
super.onReceive(context, intent);
}
Service
public class FlipperRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
private static final String TAG = "FILPPERWIDGET";
public FlipperRemoteViewsFactory(Context context, Intent intent) {
mContext = context;
mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
//... get the data
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate()");
}
#Override
public void onDataSetChanged() {
Log.i(TAG, "onDataSetChanged()");
}
#Override
public void onDestroy() {
}
#Override
public int getCount() {
//... return size of dataset
}
#Override
public RemoteViews getViewAt(int position) {
Log.i(TAG, "getViewAt()" + position);
RemoteViews page = new RemoteViews(mContext.getPackageName(), R.layout.app_widget_item);
//... set the data on the layout
return page;
}
#Override
public RemoteViews getLoadingView() {
Log.i(TAG, "getLoadingView()");
return new RemoteViews(mContext.getPackageName(), R.layout.appwidget_loading);
}
#Override
public int getViewTypeCount() {
Log.i(TAG, "getViewTypeCount()");
return 1;
}
#Override
public long getItemId(int position) {
Log.i(TAG, "getItemId()");
return position;
}
#Override
public boolean hasStableIds() {
Log.i(TAG, "hasStableIds()");
return true;
}
}
Manifest
<receiver android:name=".AppWidgetProvider"
android:label="#string/app_name"
android:enabled="#bool/is_at_least_12_api">
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/app_widget_info" />
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
</receiver>
<!-- Service serving the RemoteViews to the collection widget -->
<service android:name=".ViewFlipperWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
app wigdet info
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="#layout/app_widget"
android:initialLayout="#layout/app_widget"
android:minHeight="110dp"
android:minWidth="250dp"
android:previewImage="#drawable/widget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="14400000"
android:widgetCategory="home_screen" />
Any help would be appreciated !
Depends on the launcher, there is no guarantee that your AppWidget will be updated immediately after the device started. It may be refreshed immeidately, or wait till the updatePeriodMillis passed after system started.
To solve your problem, define a BroadcastReceiver that will trigger the update of AppWidget after the reboot.
In AndroidManifest.xml, define the BootReceiver to get the boot_complete message.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And define the BootReceiver.java to start your AppWidgetUpdateService
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent){
//start appwidget update service
}
}
I have completed one task application in android.And now i create one widget for this application.In my widget i have display list of task for today,which is working correctly.My problem is when i go to my application and add some task in today and then back to the home screen the widget having only old data instead of new data and no modification...please any one help me....
My RemoteFactory class:
public class TaskItemStatus implements RemoteViewsService.RemoteViewsFactory {
Context context;
int appWidgetId;
String statusRemainingTask="false";
String[] items;
private final String TAG = "CalendarViewSample:"
+ this.getClass().getName();
public TaskItemStatus(Context context, Intent intent) {
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
getData();
}
#SuppressLint("SimpleDateFormat")
private void getData() {
List<String> listTask=new ArrayList<String>();
Taskdatabase objTaskDb = new Taskdatabase(this.context);
objTaskDb.Open();
Calendar calendarToday = Calendar.getInstance();
SimpleDateFormat simpledateFormat = new SimpleDateFormat("dd-MM-yyyy");
String dateToday = simpledateFormat.format(calendarToday.getTime());
listTask.addAll(objTaskDb.fetchTodayRemainTask(dateToday, statusRemainingTask));
Log.i(TAG,"ListTask:"+listTask.toString());
items=new String[listTask.size()];
items=listTask.toArray(items);
}
#Override
public int getCount() {
return (items.length);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public RemoteViews getViewAt(int position) {
RemoteViews row = new RemoteViews(context.getPackageName(),
R.layout.widgetrow);
row.setTextViewText(android.R.id.text1, items[position]);
Intent i = new Intent();
//Bundle extras = new Bundle();
//extras.putString(WidgetTaskSchedular.EXTRA_WORD, items[position]);
//i.putExtras(extras);
row.setOnClickFillInIntent(android.R.id.text1, i);
return (row);
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return (true);
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
}
#Override
public void onDestroy() {
}
}
WidgetProvider:
public class WidgetTaskSchedular extends AppWidgetProvider {
static int ID;
static final int[] sameid=new int[1];
public static String EXTRA_WORD=
"com.capsone.testing.calendar.WORD";
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getAction().equals("update_widget"))
{
Log.i(TAG,"AppWidgetIds:"+ID);
for(int i=0;i<1;i++)
{
sameid[i]=ID;
Log.i(TAG,"SameId:"+sameid[i]);
onUpdate(context, AppWidgetManager.getInstance(context),sameid);
}
}
}
#SuppressWarnings("deprecation")
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
ID=appWidgetIds[i];
for (int i=0; i<appWidgetIds.length; i++) {
Log.i("Widget","WidgetId:"+appWidgetIds.length);
Intent intentWidgetService=new Intent(context, WidgetService.class);
intentWidgetService.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intentWidgetService.setData(Uri.parse(intentWidgetService.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteView=new RemoteViews(context.getPackageName(),
R.layout.widgetlayout);
remoteView.setRemoteAdapter(appWidgetIds[i], R.id.listWidget,
intentWidgetService);
Intent clickIntent=new Intent(context, ActionBarActivity.class);
PendingIntent clickPendingIntent=PendingIntent
.getActivity(context, 0,
clickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.listWidget, clickPendingIntent);
ComponentName component=new ComponentName(context,WidgetTaskSchedular.class);
appWidgetManager.updateAppWidget(component, remoteView);
}
}
}
AppWidgetProvider class:
ComponentName component = new ComponentName(context, WidgetTaskSchedular.class);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.listWidget);
appWidgetManager.updateAppWidget(component, remoteView);
RemoteView class:
#Override
public void onDataSetChanged() {
// Just copy and paste you getdata() coding here
}
One way to achieve this is when you save the new task in your application just send a broadcast with a custom intent to indicate the change in the underlying database.
Add a receiver to this broadcast in your WidgetTaskSchedular class and in on receive method call the onUpdate method to re-populate data in the widget. Somewhat like this:
public void onReceive(Context context, Intent intent) {
System.out.println("On receive function");
if (intent.getAction().equals("com.android.myapp.myBroadcast")) {
System.out.println("There is an update from app ");
//re populate data or in onUpdate
onUpdate(context, AppWidgetManager.getInstance(context), IDs);
}
super.onReceive(context, intent);
}
PS:Save Ids as a static field or something.I took in the IDs in a static array of integers which I populatedin the onUpdate method,you can also try replacing that part with the following code:
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget);
// Update - here like for example as below
remoteViews.setTextViewText(R.id.yourTextID, "My updated text");
// Trigger widget layout update
AppWidgetManager.getInstance(context).updateAppWidget(
new ComponentName(context, Widget.class), remoteViews);
I have this widget that toggles sound on off but instead of that I want to call another activity (MYxz.class) please tell me what should I change here...
public class AppWidget extends AppWidgetProvider {
#Override
public void onReceive(Context ctxt, Intent intent)
{
if(intent.getAction()==null)
{
ctxt.startService(new Intent(ctxt,ToggleService.class));
}
else
{
super.onReceive(ctxt, intent);
}
}
#Override
public void onUpdate(Context context,AppWidgetManager appWidgetManager, int [] appWidgetIds)
{
context.startService(new Intent(context,ToggleService.class));
//RemoteViews buildUpdate(context);
}
public static class ToggleService extends IntentService
{
public ToggleService() {
super("AppWidget$ToggleService");
}
#Override
protected void onHandleIntent(Intent intent)
{
ComponentName me = new ComponentName(this,AppWidget.class);
AppWidgetManager mgr= AppWidgetManager.getInstance(this);
mgr.updateAppWidget(me,buildUpdate(this));
}
private RemoteViews buildUpdate(Context context)
{
RemoteViews updateViews=new RemoteViews(context.getPackageName(),R.layout.widget);
AudioManager audioManager=(AudioManager)context.getSystemService(Activity.AUDIO_SERVICE);
if(audioManager.getRingerMode()==AudioManager.RINGER_MODE_SILENT)
{
updateViews.setImageViewResource(R.id.phoneState,R.drawable.silent);
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
else {
updateViews.setImageViewResource(R.id.phoneState,R.drawable.phone123);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}
Intent i=new Intent(this, AppWidget.class);
PendingIntent pi= PendingIntent.getBroadcast(context,0, i,0);
updateViews.setOnClickPendingIntent(R.id.phoneState,pi);
return updateViews;
}
}
}
Yes possible see example:
Upadte your manifest.xml
<receiver android:name=".AppWidget"
android:label="Caller"
android:icon="#drawable/ic_launcher" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.app.example.MyWidget.ACTION_WIDGET_CLICK_RECEIVER"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_provider"
/>
</receiver>
<service android:name=".AppWidget$ToggleService" />
and Update your AppWidgetProvider:
public class MyWidget extends AppWidgetProvider {
public static String ACTION_WIDGET_CLICK_RECEIVER = "ActionReceiverWidget";
public static int appid[];
public static RemoteViews rview;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds){
updateWidgetState(context, "");
}
#Override
public void onReceive(Context paramContext, Intent paramIntent)
{
String str = paramIntent.getAction();
if (paramIntent.getAction().equals(ACTION_WIDGET_CLICK_RECEIVER)) {
updateWidgetState(paramContext, str);
}
else
{
if ("android.appwidget.action.APPWIDGET_DELETED".equals(str))
{
int i = paramIntent.getExtras().getInt("appWidgetId", 0);
if (i == 0)
{
}
else
{
int[] arrayOfInt = new int[1];
arrayOfInt[0] = i;
onDeleted(paramContext, arrayOfInt);
}
}
super.onReceive(paramContext, paramIntent);
}
}
static void updateWidgetState(Context paramContext, String paramString)
{
RemoteViews localRemoteViews = buildUpdate(paramContext, paramString);
ComponentName localComponentName = new ComponentName(paramContext, MyWidget.class);
AppWidgetManager.getInstance(paramContext).updateAppWidget(localComponentName, localRemoteViews);
}
private static RemoteViews buildUpdate(Context paramContext, String paramString)
{
// Toast.makeText(paramContext, "buildUpdate() ::"+paramString, Toast.LENGTH_SHORT).show();
rview = new RemoteViews(paramContext.getPackageName(), R.layout.widget_layout);
Intent active = new Intent(paramContext, MyWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
PendingIntent configPendingIntent = PendingIntent.getActivity(paramContext, 0, active, 0);
// upadte this R.id.buttonus1 with your layout or image id on which click you want to start Activity
Intent configIntent = new Intent(paramContext, Caller2.class);
configIntent.setAction((ACTION_WIDGET_CLICK_RECEIVER);
PendingIntent configPendingIntent = PendingIntent.getActivity(paramContext, 0, configIntent, 0);
rview.setOnClickPendingIntent(R.id.Phonestatexx, configPendingIntent);
if(parmString.equals(ACTION_WIDGET_CLICK_RECEIVER))
{
//open Activity here..
//your code for update and what you want on button click
//
}
return rview;
}
#Override
public void onEnabled(Context context){
super.onEnabled(context);
// Toast.makeText(context, "onEnabled() ", Toast.LENGTH_SHORT).show();
}
// Called each time an instance of the App Widget is removed from the host
#Override
public void onDeleted(Context context, int [] appWidgetId){
super.onDeleted(context, appWidgetId);
// Toast.makeText(context, "onDeleted() ", Toast.LENGTH_SHORT).show();
}
// Called when last instance of App Widget is deleted from the App Widget host.
#Override
public void onDisabled(Context context) {
super.onDisabled(context);
// Toast.makeText(context, "onDisabled() ", Toast.LENGTH_SHORT).show();
}
}
Instead of:
Intent active = new Intent(paramContext, AppWidget.class);
You use:
Intent active = new Intent(paramContext, YOURCLASS.class);
before you create the pending intent, #imran khan helped me but there are some tweaks you should do 2...this should fire up the Activity you need.
With using pendingIntents you can call an intent (to your activity or sth else) when a widget item clicked. this may help:
http://www.vogella.de/articles/AndroidWidgets/article.html
i want to create a widget that when clicked on to open a dialog with a autocompletetextview(FROM THE main.class) and execute functions from mainclass.. here is my widget class and please tell me what to put in android manifest also. thx
public class AppWidget extends AppWidgetProvider
{
#Override
public void onReceive(Context ctxt, Intent intent)
{
if(intent.getAction()==null)
{
ctxt.startService(new Intent(ctxt,ToggleService.class));
}
else
{
super.onReceive(ctxt, intent);
}
}
#Override
public void onUpdate(Context context,AppWidgetManager appWidgetManager, int [] appWidgetIds)
{
context.startService(new Intent(context,ToggleService.class));
//RemoteViews buildUpdate(context);
}
public static class ToggleService extends IntentService
{
public ToggleService() {
super("AppWidget$ToggleService");
}
#Override
protected void onHandleIntent(Intent intent)
{
ComponentName me = new ComponentName(this,AppWidget.class);
AppWidgetManager mgr= AppWidgetManager.getInstance(this);
mgr.updateAppWidget(me,buildUpdate(this));
}
private RemoteViews buildUpdate(Context context)
{
RemoteViews updateViews=new RemoteViews(context.getPackageName(),R.layout.widget);
Intent i=new Intent(this, AppWidget.class);
PendingIntent pi= PendingIntent.getBroadcast(context,0, i,0);
updateViews.setOnClickPendingIntent(R.id.phoneState,pi);
return updateViews;
}
}
}
widgetxml//
<?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="vertical" >
<ImageView
android:id="#+id/phoneState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:layout_centerInParent="true"
android:src="#drawable/ic_launcher"
/>
</RelativeLayout>
// and widget_provider.xml in res/xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="79px"
android:minHeight="79px"
android:updatePeriodMillis="1800000"
android:initialLayout="#layout/widget">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Loading..." />
// and part from my manifest
<receiver android:name=".AppWidget"
android:label="Caller"
android:icon="#drawable/ic_launcher" >
<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>
<service android:name=".AppWidget$ToggleService" />
Upadte your manifest.xml
<receiver android:name=".AppWidget"
android:label="Caller"
android:icon="#drawable/ic_launcher" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.app.example.MyWidget.ACTION_WIDGET_CLICK_RECEIVER"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_provider"
/>
</receiver>
<service android:name=".AppWidget$ToggleService" />
and Update your AppWidgetProvider:
public class MyWidget extends AppWidgetProvider {
public static String ACTION_WIDGET_CLICK_RECEIVER = "ActionReceiverWidget";
public static int appid[];
public static RemoteViews rview;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds){
updateWidgetState(context, "");
}
#Override
public void onReceive(Context paramContext, Intent paramIntent)
{
String str = paramIntent.getAction();
if (paramIntent.getAction().equals(ACTION_WIDGET_CLICK_RECEIVER)) {
updateWidgetState(paramContext, str);
}
else
{
if ("android.appwidget.action.APPWIDGET_DELETED".equals(str))
{
int i = paramIntent.getExtras().getInt("appWidgetId", 0);
if (i == 0)
{
}
else
{
int[] arrayOfInt = new int[1];
arrayOfInt[0] = i;
onDeleted(paramContext, arrayOfInt);
}
}
super.onReceive(paramContext, paramIntent);
}
}
static void updateWidgetState(Context paramContext, String paramString)
{
RemoteViews localRemoteViews = buildUpdate(paramContext, paramString);
ComponentName localComponentName = new ComponentName(paramContext, MyWidget.class);
AppWidgetManager.getInstance(paramContext).updateAppWidget(localComponentName, localRemoteViews);
}
private static RemoteViews buildUpdate(Context paramContext, String paramString)
{
// Toast.makeText(paramContext, "buildUpdate() ::"+paramString, Toast.LENGTH_SHORT).show();
rview = new RemoteViews(paramContext.getPackageName(), R.layout.widget_layout);
Intent active = new Intent(paramContext, MyWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
active.putExtra("msg", "Message for Button 1");
PendingIntent configPendingIntent = PendingIntent.getActivity(paramContext, 0, active, 0);
rmViews.setOnClickPendingIntent(R.id.buttonus1, configPendingIntent);
if(parmString.equals(ACTION_WIDGET_CLICK_RECEIVER))
{
//open a dialog with a autocompletetextview
//your code for update and what you want on button click
}
return rview;
}
#Override
public void onEnabled(Context context){
super.onEnabled(context);
// Toast.makeText(context, "onEnabled() ", Toast.LENGTH_SHORT).show();
}
// Called each time an instance of the App Widget is removed from the host
#Override
public void onDeleted(Context context, int [] appWidgetId){
super.onDeleted(context, appWidgetId);
// Toast.makeText(context, "onDeleted() ", Toast.LENGTH_SHORT).show();
}
// Called when last instance of App Widget is deleted from the App Widget host.
#Override
public void onDisabled(Context context) {
super.onDisabled(context);
// Toast.makeText(context, "onDisabled() ", Toast.LENGTH_SHORT).show();
}
}