I have few widgets in my application with different sizes. And for each widget I need set receiver android:name to different values (otherwise Android show only one first widget). So I need to create separate class with identical code for each widget. That is uneasily. How I can avoid this? May be I can create one parent class and inherit it for other widget classes?
My code:
Manifest:
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_1x1" />
</receiver>
<receiver android:exported="false"
android:name=".WidgetHandler_4x4"
android:label="Widget 4x4" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_4x4" />
</receiver>
And WidgetHandler_1x1 / WidgetHandler_4x4:
public class WidgetHandler_4x4 extends AppWidgetProvider {
public static String ACTION_WIDGET_EDIT = "ActionWidgetEdit";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent editIntent = new Intent(context, this.getClass());
editIntent.setAction(ACTION_WIDGET_EDIT);
PendingIntent editPendingIntent = PendingIntent.getBroadcast(context, 0, editIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.edit_button, editPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_WIDGET_EDIT)) {
Toast.makeText(context, "edit", Toast.LENGTH_SHORT).show();
}
super.onReceive(context, intent);
}
}
Related
I've coded an Android widget with two buttons. If i start the "Activity" all works fine and i can click on those buttons. But if i lock the phone, the process dies after a few seconds
and i try to click on those buttons again, nothing happens, except the LOGCAT:
I/ActivityManager: filter receiver for action = ButtonRefresh
updateAppWidget, called via #Override onUpdate(...):
private final static String BUTTON_REFRESH = "ButtonRefresh";
public static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager,
final int appWidgetId) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.myclasslayout);
//Click listener depending on #this (getPendingSelfIntent)
views.setOnClickPendingIntent(R.id.button_refresh, getPendingSelfIntent(context, BUTTON_REFRESH));
[...]
appWidgetManager.updateAppWidget(appWidgetId, views);
}
getPendingSelfIntent():
private static PendingIntent getPendingSelfIntent(Context context, String action) {
Intent intent = new Intent(context, MyClass.class);
intent.setAction(action);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
onReceive():
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (BUTTON_REFRESH.equals(intent.getAction())) {
Log.i("MyLogtag", "Refresh"); //This never shows up in LOGCAT
}
}
AndroidManifest.xml:
[...]
<receiver android:name=".MyClass">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/myclass_info" />
</receiver>
[...]
onReceive never gets called when app process is dead...
I got it...
i have to change
private final static String BUTTON_REFRESH = "ButtonRefresh";
to
private final static String BUTTON_REFRESH = "com.example.mypackage.BUTTON_REFRESH";
and AndroidManifest:
<receiver android:name=".MyClass">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.example.mypackage.BUTTON_REFRESH"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/myclass_info" />
</receiver>
I have got the issue that is very popular on Stackoverflow and there are a lot of recipes how to fix it. But unfortunately, all of them don`t fit me.
I created appWidget with collection (StackView), added ConfigActivity for configuration and permanent update mechanism with assigned time interval. Widget is displayed in a proper way, update works fine but when I want to run Config Activity and click on widget - nothing happens!
Maybe, I've missed some important details and hope you'll suggest me. Here are some of code snippets:
Manifest
<uses-sdk android:minSdkVersion="11"
android:targetSdkVersion="22"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".FinApp"
android:allowBackup="true"
android:icon="#mipmap/ic_fin"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".widget.WidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/fin_app_widget_info" />
</receiver>
<activity android:name=".ConfigActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<service
android:name=".widget.WidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"/>
</application>
AppWidgetProvider
public class WidgetProvider extends AppWidgetProvider {
private static final String TAG = WidgetProvider.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive");
super.onReceive(context, intent);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.w(TAG, "onUpdate: appWidgetIds - " + Arrays.toString(appWidgetIds));
for (int id : appWidgetIds) {
updateAppWidgetInstance(context, appWidgetManager, id);
}
}
public static void updateWidgetsOnDataSetChanged (Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context.getPackageName(), WidgetProvider.class.getName()));
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list);
}
private static void addWidgetListener(Context context, int appWidgetId, RemoteViews widget) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent runConfigActivity = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
widget.setOnClickPendingIntent(R.id.widget_container, runConfigActivity);
}
private static void setupWidgetService(Context context, int appWidgetId, RemoteViews widget) {
Intent adapterIntent = new Intent(context, WidgetService.class);
adapterIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
adapterIntent.setData(Uri.fromParts("content", String.valueOf(appWidgetId), null));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
widget.setRemoteAdapter(R.id.widget_list, adapterIntent);
} else {
//noinspection deprecation
widget.setRemoteAdapter(appWidgetId, R.id.widget_list, adapterIntent);
}
}
private static void updateAppWidgetInstance(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
Log.e(TAG, "updateAppWidgetInstance");
RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget_collection_layout);
setupWidgetService(context, appWidgetId, widget);
addWidgetListener(context, appWidgetId, widget);
appWidgetManager.updateAppWidget(appWidgetId, widget);
}
}
widget_collection_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/widget_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<StackView
android:id="#+id/widget_list"
android:loopViews="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
As I understand the point is in the method addWidgetListener
private static void addWidgetListener(Context context, int appWidgetId, RemoteViews widget) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent runConfigActivity = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
widget.setOnClickPendingIntent(R.id.widget_container, runConfigActivity);
}
but I have no idea what's wrong...
After some investigation I came to a conclusion that if I use collection in appWidget and want to open Config Activity tapping on whole widget container that the best practice is using setPendingIntentTemplate method, even if you dont't want to handle item click but the whole list instead (list container).
private static void addWidgetListener(Context context, int appWidgetId, RemoteViews widget) {
Intent intent = new Intent(context, ConfigActivity.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent runConfigActivity = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
widget.setPendingIntentTemplate(R.id.widget_list, runConfigActivity);
}
and add 2 lines in WidgetFactory in method getViewAt(int position)
Intent intent = new Intent();
views.setOnClickFillInIntent(R.id.widget_item_container, intent);
I've created a simple widget have only a button and textView. When I add my widget first time to the homescreen a FC message coming and widget will added. And button click toast message won't work. Only i need to have a toast message when clicking the widget button. I've gone through lots of tutorials but couldn't figure out whats the problem. Any genius who'd like to help..really appriciate the help..Thanks..
widgetProvider.java
public class widgetProvider extends AppWidgetProvider{
#Override
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];
Intent intent = new Intent(context, widgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
views.setOnClickPendingIntent(R.id.button1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {
Toast.makeText(context, "Button Clicked", Toast.LENGTH_SHORT).show();
}
}
}
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".widgetProvider" 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/widgetprovider" />
</receiver>
</application>
your onUpdate is never called since you overriden the onReceive method.
I tried a lot to change my widget view's image when i click on it but it doesn't work. It's my code:
public class myAppWidgetProvider extends AppWidgetProvider {
public static String ACTION_WIDGET_REFRESH = "ActionReceiverRefresh";
//...
#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];
Intent intent = new Intent(context, myAppWidgetProvider.class);
intent.setAction(ACTION_WIDGET_REFRESH);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
rv.setOnClickPendingIntent(R.id.imageView, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, rv);
}
And in onReceive i want to receive it when i click widget's view, but it doesn't work:
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
RemoteViews rmv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
//and this change doesn't work :(( \/
rmv.setImageViewResource(R.id.imageView, R.drawable.button_power_on_small);
}
}
It's my android manifest receiver:
<receiver android:name="myAppWidgetProvider" android:exported="false" android:icon="#drawable/button_power_off">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.xxx.xxx.myAppWidgetProvider.ACTION_WIDGET_REFRESH"/>
<action android:name="android.appwidget.action.APPWIDGET_DELETED"/>
<action android:name="android.media.RINGER_MODE_CHANGED"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_info_provider" />
</receiver>
I will be grateful if someone suggest me some solution.
Change
<action android:name="com.xxx.xxx.myAppWidgetProvider.ACTION_WIDGET_REFRESH"/>
to
<action android:name="ActionReceiverRefresh"/>
Your BroadcastReceiver is looking for the wrong action string. Remember that AndroidManifest is an XML file. You have to put the actual value of the String; pointing to a Java constant doesn't work.
I have developed an application that makes use of a widget. The widget could be added in the homescreen and used as a button. I have recently downgraded the version to <uses-sdk android:minSdkVersion="7" /> and no errors were spotted. However, now when i reinstall the, the widget is not responsive. In addition when I try to install the app on another phone running android 4.0.3, widget is not available anywhere, so i cannot even add it to the homescreen. Here is my code for the widget:
public class MyWidget extends AppWidgetProvider {
#Override
public void onUpdate(Context c, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
final int N = appWidgetIds.length;
//for each of the instances of the widget
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(c.getPackageName(), R.layout.widget_layout);
Intent fireDialog = new Intent(c,Execute.class);
PendingIntent pendingIntent = PendingIntent.getActivity(c, 0, fireDialog, 0);
views.setOnClickPendingIntent(R.id.myButton, pendingIntent); //when the button is clicked, an activity is launched
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onReceive(Context c, 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(c,new int[]{appWidgetId});
}
}else{
super.onReceive(c, intent);
}
}
}
Here is the manifest.xml:
<application>
<receiver android:name=".myButton"
android:icon="#drawable/icon"
android:label="myWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/my_xml" />
</receiver>
</application>