I have an widget and I must update the widget when action android.media.RINGER_MODE_CHANGED occurs. I have the folowing broadcast receiver:
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
ComponentName thisWidget = new ComponentName(context.getApplicationContext(), ExampleAppWidgetProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
if (appWidgetIds != null && appWidgetIds.length > 0) {
for (int widgetId : appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context
.getApplicationContext().getPackageName(),
R.layout.widget1);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
}
and this si code for my widget
public class ExampleAppWidgetProvider extends AppWidgetProvider {
DateFormat df = new SimpleDateFormat("hh:mm:ss");
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
int appWidgetId = appWidgetIds[i];
//my pudate widget code
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
<receiver android:name=".ExampleAppWidgetProvider" android:label="demo widget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget1_info" />
</receiver>
so my problem is that even if the instruction appWidgetManager.updateAppWidget(widgetId, remoteViews); from my broadcast receiver is executed, the update method inside the widget is not executed. Does anybody knows why?
it seems that AppWidgetProvider extends BroadcastReceiver so here is my code :
public class ExampleAppWidgetProvider extends AppWidgetProvider {
DateFormat df = new SimpleDateFormat("hh:mm:ss");
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//my update code here
}
#Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
ComponentName thisWidget = new ComponentName(context.getApplicationContext(), ExampleAppWidgetProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
if (appWidgetIds != null && appWidgetIds.length > 0) {
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
<receiver android:name=".ExampleAppWidgetProvider" android:label="demo widget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<intent-filter>
<action android:name="android.media.RINGER_MODE_CHANGED"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget1_info"/>
</receiver>
Related
i need make activity for choose widget
Widget1.java
public class Widget1 extends AppWidgetProvider{
Context context;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
if (appWidgetIds != null) {
int N = appWidgetIds.length;
for (int mAppWidgetId : appWidgetIds) {
Intent intent = new Intent(context, UpdateWidgetService.class);
intent.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
intent.setAction("FROM WIDGET PROVIDER");
context.startService(intent);
}
}
}
public static class UpdateWidgetService extends IntentService {
public UpdateWidgetService() {
// only for debug purpose
super("UpdateWidgetService");
}
#Override
protected void onHandleIntent(Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(UpdateWidgetService.this);
int incomingAppWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID,
INVALID_APPWIDGET_ID);
if (incomingAppWidgetId != INVALID_APPWIDGET_ID) {
try {
updateNewsAppWidget(appWidgetManager, incomingAppWidgetId,
intent);
} catch (NullPointerException e) {
}
}
}
public void updateNewsAppWidget(AppWidgetManager appWidgetManager,
int appWidgetId, Intent intent) {
Log.v("String package name", this.getPackageName());
RemoteViews views = new RemoteViews(this.getPackageName(),
R.layout.widget1);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Widget2.java
public class widget2 extends AppWidgetProvider{
Context context;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
if (appWidgetIds != null) {
int N = appWidgetIds.length;
for (int mAppWidgetId : appWidgetIds) {
Intent intent = new Intent(context, UpdateWidgetService.class);
intent.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
intent.setAction("FROM WIDGET PROVIDER");
context.startService(intent);
}
}
}
public static class UpdateWidgetService extends IntentService {
public UpdateWidgetService() {
// only for debug purpose
super("UpdateWidgetService");
}
#Override
protected void onHandleIntent(Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(UpdateWidgetService.this);
int incomingAppWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID,
INVALID_APPWIDGET_ID);
if (incomingAppWidgetId != INVALID_APPWIDGET_ID) {
try {
updateNewsAppWidget(appWidgetManager, incomingAppWidgetId,
intent);
} catch (NullPointerException e) {
}
}
}
public void updateNewsAppWidget(AppWidgetManager appWidgetManager,
int appWidgetId, Intent intent) {
Log.v("String package name", this.getPackageName());
RemoteViews views = new RemoteViews(this.getPackageName(),
R.layout.widget2);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
widget1.xml
<AnalogClock
android:id="#+id/analogClock1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:dial="#drawable/hand_dial"
android:hand_minute="#drawable/hand_minute"
android:hand_hour="#drawable/hand_hour"/>
widget2.xml
<AnalogClock
android:id="#+id/analogClock2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:dial="#drawable/hand_dial2"
android:hand_minute="#drawable/hand_minute2"
android:hand_hour="#drawable/hand_hour2"/>
widget1_config.xml
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="140dip"
android:minHeight="140dip"
android:previewImage="#drawable/preview"
android:initialLayout="#layout/widget1"
android:updatePeriodMillis="1800000"
android:resizeMode="horizontal|vertical"/>
AndroidManifest.xml
<receiver android:name=".Widget1" android:label="Analog Clock">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget_config" />
</receiver>
<receiver android:name=".widget2" android:label="Analog Clock2">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget2_config" />
i can make ten widget in one app every widget Single , But this is not good
so i need Launching activity when a widget is dropped for choose widget
How can I do this ?
Finally, I apologize for my English is not good
Thank you.
You need to add the android:configure attribute to you widget provider XML. See https://github.com/slightfoot/android-note-widget/blob/master/res/xml/appwidget_note.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.demondevelopers.notewidget.ConfigActivity"
android:initialKeyguardLayout="#layout/appwidget_note"
android:initialLayout="#layout/appwidget_note"
android:minHeight="110dp"
android:minWidth="180dp"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:updatePeriodMillis="0"
/>
For full example check out my project:
https://github.com/slightfoot/android-note-widget
I want to do a widget with a list inside, I have to implement a class that extends of RemoteViewsService, but this class never execute, my code is the following:
MyWidgetProvider
public class MyWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget);
Intent updateIntent = new Intent(context, WidgetService.class);
for (int appWidgetId : appWidgetIds) {
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
updateIntent.setData(Uri.parse(updateIntent.toUri(Intent.URI_INTENT_SCHEME)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
views.setRemoteAdapter(appWidgetId, updateIntent);
else
views.setRemoteAdapter(appWidgetId, R.id.events_list, updateIntent);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.events_list);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
WidgetService
public class WidgetService extends RemoteViewsService {
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new WidgetFactory(getApplicationContext(), intent);
}
}
And the Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.widget.example"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".MyWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/appwidget_info" />
</receiver>
<service android:name=".WidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false">
</service>
</application>
Edit;
I have found the error, i have to use:
views.setRemoteAdapter(R.id.events_list, updateIntent);
instead of
views.setRemoteAdapter(appWidgetId, updateIntent);
See RemoteViews.html#setRemoteAdapter
The SetRemoteAdapter function with 3 parameters is deprecated in API level 14+, and even if you called the 3 parameters one, the widget id parameter is ignores. So the function always receive only 2 valid parameters, i.e. view_id and intent.
This function basically says I'm going to use the intent as a data source for the view (indicated by view_id).
for me this works
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int widgetId : appWidgetIds) {
RemoteViews mView = initViews(context, appWidgetManager, widgetId);
appWidgetManager.updateAppWidget(widgetId, mView);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
private RemoteViews initViews(Context context,
AppWidgetManager widgetManager, int widgetId) {
RemoteViews mView = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
Intent intent = new Intent(context, WidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
mView.setRemoteAdapter(widgetId, R.id.widgetCollectionList, intent);
return mView;
}
I've followed a bunch of tutorials, search on google and on stack overflow and came up with this code to update my widget when i touch it:
public class WidgetService extends Service{
#Override
public void onStart(Intent intent, int startId) {
Log.i("WidgetService", "Called");
String fakeUpdate = null;
Random random = new Random();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
int[] appWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds.length > 0) {
for (int widgetId : appWidgetIds) {
int nextInt = random.nextInt(100);
fakeUpdate = "Random: " + String.valueOf(nextInt);
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.widget);
remoteViews.setTextViewText(R.id.txt_updated, fakeUpdate);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
stopSelf();
}
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
And for widget provider:
public class Widget extends AppWidgetProvider{
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget);
Intent intent = new Intent(context.getApplicationContext(),
WidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getService(
context.getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.cnt_widget, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
context.startService(intent);
}
}
In manifest:
<receiver
android:label="#string/next_trip_text"
android:name=".widget.Widget" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
And xml:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="272dp"
android:minHeight="72dp"
android:updatePeriodMillis="0"
android:initialLayout="#layout/widget"
android:configure="se.webevo.basttrafik.widget.WidgetConfigActivity" >
</appwidget-provider>
The service doesn't seem to be called at all. Any ideas? :)
Thanks!
add this to manifest:
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/-- ur appwidgetprovider location here--">
</meta-data>
also try adding:
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_ENABLED"/>
</intent-filter>
see if it works
I'm trying to make an Android widget, to show some info from my app.
I have succeed to show some info, but know i what to have a feature to "switch page" in my app. It means pressing a button, and new info is showing. But how do i do it? I have tried different thing, and I'm ending up with the following code:
public class HelloWidget extends AppWidgetProvider {
RemoteViews remoteViews;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Toast.makeText(context, "onUpdate", Toast.LENGTH_SHORT).show();
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Intent intent = new Intent();
intent.setAction(TestReceiver.TEST_INTENT);
intent.setClassName(TestReceiver.class.getPackage().getName(), TestReceiver.class.getName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.bbutton1, pendingIntent);
remoteViews.setTextViewText(R.id.widgetTxt, "The textview");
appWidgetManager.updateAppWidget(appWidgetIds[0], remoteViews);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public class TestReceiver extends BroadcastReceiver {
public static final String TEST_INTENT = "MyTestIntent";
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "You reached the TestReceiver", Toast.LENGTH_SHORT).show();
if (intent.getAction() == TEST_INTENT) {
remoteViews.setTextViewText(R.id.widgetTxt, "Is changed");
}
}
}
#Override
public void onReceive(Context context, Intent intent) {
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);
}
}
#Override
public void onDeleted(Context context, int[] appWidgetIds) {
Toast.makeText(context, "onDelete", Toast.LENGTH_SHORT).show();
super.onDeleted(context, appWidgetIds);
}
}
Toast are showing "onUpdate" and then i remove it at "onDeleted". The textview also change in the onUpdate, but nothing happens when i press the button.
My Manifest look like this:
<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/hello_widget_provider" />
</receiver>
<receiver android:name=".TestReceiver" android:label="#string/app_name">
<intent-filter>
<action android:name="MyTestIntent">
</action>
</intent-filter>
</receiver>
What am i doing wrong?
Thanks
Is your TestReceiver an inner class of HelloWidget?
Then you didn't specify the correct name in the manifest.
I have a widget that lets you select from 2 sizes, it also has a config. For some reason after some time goes by, the buttons on my widget will unbind and you will not be able to click anything. I dont know why this is happening. Could it be the super.onReceive(context, intent) in my OnRecieve method? Would that cause it to unbind possibly? Also what would the sure fire way to make sure the buttons are ALWAYS binded be?
AppWidgetProvider
public class mWidget extends AppWidgetProvider {
public static String ACTION_WIDGET_REFRESH = "Refresh";
public static final String PREFS_NAME = "mWidgetPrefs";
#Override
public void onEnabled(Context context) {
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
RemoteViews remoteViews = buildLayout(context);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews views = buildLayout(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
public static RemoteViews buildLayout(Context context) {
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_4x2);
Intent intent = new Intent(context, mWidget.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
intent = new Intent(context, mWidget.class);
intent.setAction(ACTION_WIDGET_REFRESH);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteView.setOnClickPendingIntent(R.id.refresh, pendingIntent);
return remoteView;
}
#Override
public void onReceive(Context context, Intent intent) {
RemoteViews remoteView = null;
remoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_4x2);
if (intent.getAction().equals(ACTION_WIDGET_REFRESH)) {
Toast.makeText(context, "here", Toast.LENGTH_LONG).show();
} else {
super.onReceive(context, intent);
}
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".mwidgetConfig" android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity android:name=".mwidgetConfigSmall"
android:label="#string/app_name" android:theme="#android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<!-- BEGIN 4X4 WIDGET -->
<receiver android:label="Test Widget 4x4"
android:name="com.test.mwidget.mWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action
android:name="com.test.mwidget.mWidget.ACTION_WIDGET_REFRESH" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_4x4_provider" />
</receiver>
<!-- BEGIN 4X2 WIDGET -->
<receiver android:label="Test Widget 4x2"
android:name="com.test.mwidget.mWidgetSmall">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action
android:name="com.test.mwidget.mWidgetSmall.ACTION_WIDGET_REFRESH" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_4x2_provider" />
</receiver>
</application>
You should bind your pending intent on each onUpdate event.
You should iterate through all appWidgerIds.
Usually, I implement widget stuff as the following:
public void onUpdate(Context context,
AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
updateAllWidgetsInternal(context, appWidgetManager, appWidgetIds);
}
private static void updateAllWidgetsInternal(Context context,
AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final RemoteViews views = buildLayout(context);
final int N = appWidgetIds.length;
for (int i=0; i<N; ++i) {
appWidgetManager.updateAppWidget(appWidgetIds[i], views);
}
}
// This function can be executed anywhere in any time to update widgets
public static void updateAllWidgets(Context context) {
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, mWidget.class));
updateAllWidgetsInternal(context, appWidgetManager, appWidgetIds);
}
I don't understand why you implemented onReceive().
It's only necessary if your widget is configured to catch other broadcasts than the standard widgets broadcast which are ACTION_APPWIDGET_DELETED, ACTION_APPWIDGET_DISABLED, ACTION_APPWIDGET_ENABLED and ACTION_APPWIDGET_UPDATE.
If not necessary, try without onReceive().