Using sendBroadcast for update android widgets - android

I am creating a appwidget which needs to update when some changing in app's database.
What I do:
1. Create working widget
2. Override onReceive method:
public static final String DATABASE_CHANGED = " utimetable.DATABASE_CHANGED";
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equals(DATABASE_CHANGED) || action.equals(Intent.ACTION_DATE_CHANGED))
{
AppWidgetManager gm = AppWidgetManager.getInstance(context);
int[] ids = gm.getAppWidgetIds(new ComponentName(context, widget_provider.class));
this.onUpdate(context, gm, ids);
}
else
{
super.onReceive(context, intent);
}
}
In AndroidManifest:
<receiver android:name=".widget_provider" android:label="#string/widget_today_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="utimetable.DATABASE_CHANGED" />
<action android:name="android.intent.action.DATE_CHANGED" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget_row" />
</receiver>
Add Broadcast sending into all DB changing functions:
public static void sendUpdateIntent(Context context)
{
Intent i = new Intent(context, widget_provider.class);
i.setAction(widget_provider.DATABASE_CHANGED);
context.sendBroadcast(i);
}
But widget still not updated when I make changes in DB.
What should I do?

just guessing looking at your code, but that space after the first " looks wrong
.... DATABASE_CHANGED = " utimetable.DATABASE_CHANGED";

Related

appwidget Never go to onUpdate

my Application widget Never go to the onUpdate function
i add 3000 mili for testings but except the first time you add it,
it never goes to the onUpdate function.
what am i doing wrong ?
my manifest file:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="layout.ClockWidgetClass">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/clock_widget_class_info" />
</receiver>
</application>
my clockWidget:
/**
* Implementation of App Widget functionality.
*/
public class ClockWidgetClass extends AppWidgetProvider {
static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager,
final int appWidgetId) {
//getting shered prefrences
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String name = preferences.getString("randomString", "");
if(!name.equalsIgnoreCase(""))
{
name = name; /* Edit the value here*/
}
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.clock_widget_class);
//set chosen design visible
//set all visibility to 0
views.setViewVisibility(R.id.AnalogClock0, View.INVISIBLE);
views.setViewVisibility(R.id.AnalogClock1, View.INVISIBLE);
views.setViewVisibility(R.id.AnalogClock2, View.INVISIBLE);
views.setViewVisibility(R.id.AnalogClock3, View.INVISIBLE);
//turning on the correct clock
if (name.equals("1")) {
views.setViewVisibility(R.id.AnalogClock0, View.VISIBLE);
} else if (name.equals("2")) {
views.setViewVisibility(R.id.AnalogClock1, View.VISIBLE);
} else if (name.equals("3")) {
views.setViewVisibility(R.id.AnalogClock2, View.VISIBLE);
} else {
views.setViewVisibility(R.id.AnalogClock3, View.VISIBLE);
}
// views.setTextViewText(R.id.appwidget_text, name);
//updateting the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#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);
}
}
#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 onReceive(Context context, Intent intent) {
// Chain up to the super class so the onEnabled, etc callbacks get dispatched
super.onReceive(context, intent);
// Handle a different Intent
Log.d("reciving", "onReceive()" + intent.getAction());
}
}
my Widget xml file:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="#layout/clock_widget_class"
android:initialLayout="#layout/clock_widget_class"
android:minHeight="110dp"
android:minWidth="250dp"
android:previewImage="#drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="3000"
android:widgetCategory="home_screen"></appwidget-provider>
Never might not be correct. It just doesn't happen in the time you expect it to happen. With the documentation for updatePeriodMillis you'll find an important note:
Note: Updates requested with updatePeriodMillis will not be delivered more than once every 30 minutes.
So you might have to wait for this 30 minutes before another call to onUpdate() happens.

Can't click on Android widget after app process dies

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>

Why my widget doesn't notice when Screen turn on?

I developed an Android Widget like this:
<receiver android:name=".MyWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.intent.action.ACTION_SCREEN_ON" />
<action android:name="android.intent.action.ACTION_SCREEN_OFF" />
</intent-filter>
In my widget
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
playNotification(context, true);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
playNotification(context, true);
}
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
[...]
The updateAppWidget works perfectly. The notification instead doesn't work neither if the screen is turned on, nor if it is turned off.
What's wrong with that?
This is because
Intent.ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF" // not ACTION_SCREEN_OFF
Intent.ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON" // not ACTION_SCREEN_ON
When you fix the intent filter in manifest, everything should work fine.

One class for few widgets

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);
}
}

Android widget can't receive the DATE_CHANGED message

I am developing a calendar widget, and I can't receive the DATE_CHANGED message when I changed the date MANUALLY.
What is the problem?
My code in Manifest is :
<receiver android:name="com.widget.calendar.CalendarWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.intent.action.DATE_CHANGED"/>
</intent-filter>
<!-- This specifies the widget provider info -->
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widgetinfo" />
</receiver>
And I tried to receive it like this:
#Override
public void onReceive(Context ctx, Intent intent) {
final String action = intent.getAction();
if (action.equalsIgnoreCase("android.intent.action.DATE_CHANGED")) {
Log.e(TAG, "Date changed.....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
super.onReceive(ctx, intent);
}
But the log is not print when I change the system date manually.
Thanks!
UPDATE:
I solved this with Intent.ACTION_TIME_CHANGED, It's really a bug of DATE_CHANGED.
Use this intent:
<intent-filter>
<action android:name="android.intent.action.TIME_SET"/>
</intent-filter>
And receive:
#Override
public void onReceive(Context ctx, Intent intent) {
final String action = intent.getAction();
if (action.equalsIgnoreCase("android.intent.action.TIME_SET")) {
Log.e(TAG, "Date changed.....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
super.onReceive(ctx, intent);
}

Categories

Resources