I've built an appWidget which register some services on his onEnabled() method.
The problem is that after I use the built in Task Manager's Clean Memmory/Ram, the appWidget view crashes (all the appWidgets TextView's text is set to default (TextView)) and the Services stop running and never restarts.
This only happen after some time the widget is set, and if I Clean Memmory/Ram right after the widget is set the bug does'nt happen, but I guess this is related to the Task Manager's method of cleaning RAM.
So finally, my question is: Is there a way to tell the android system to reStart those services? as other appWidgets I've downloaded through the market is seem to continue working fine after this procedure.
Will be happy for ideas and solutions! Thanks advanced, Gal :)
some code that I use:
the onEnabled() method in the appWidget:
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
Intent newinIntent = new Intent(context, CallService_1x1.class);
context.startService(newinIntent);
newinIntent = new Intent(context, SmsService_1x1.class);
context.startService(newinIntent);
}
Some methods from one of the Services (others services are very similiar as this is from their abstract method):
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
Log.d("SERVICE-SMS","CallMonitorService - onStartCommand created");
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
context = this.getApplicationContext();
Log.d("SERVICE-SMS","CallMonitorService created");
registerObserver();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
unregisterObserver();
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Start the service to process that will run the content observer
*/
public static void beginStartingService(Context context) {
Log.d("SERVICE-SMS","CallMonitorService: beginStartingService()");
context.startService(new Intent(context, CallService.class));
}
/**
* Called back by the service when it has finished processing notifications,
* releasing the wake lock if the service is now stopping.
*/
public static void finishStartingService(Service service) {
Log.d("SERVICE-SMS","CallMonitorService: finishStartingService()");
service.stopSelf();
}
After a lot of research and some attempts, Solved it! :)
Just added BroadcastReciever listening to package changes and updates:
register receiver in the manifest file:
<receiver android:name=".receivers.onRestartReciever">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
<data android:scheme="package" android:path="my.Package.Path" />
</intent-filter>
- PACKAGE_REPLACED - called in particular to notify application update.
- PACKAGE_RESTARTED - called when most memmory cleaners are cleaning memmory.
- the "data" row is used to monitor action applied for the specific package.
Within this reciever I start my services again, and restarts the widget view (calling it's onUpdate() method in this case):
public class onRestartReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d("DEBUG", "onRestartReciever");
// Register Services
MyWidget_1x1.registerServices(context);
MyWidget_2x2.registerServices(context);
// reInitialize appWidgets
AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context);
MyWidget_1x1 widget1x1=new CallWidgi();
widget1x1.onUpdate
(context,
AppWidgetManager.getInstance(context),
widget1x1.getIDs(context, appWidgetManager));
MyWidget_2x2 widget2x2=new CallWidgi2();
widget2x1.onUpdate(context,
AppWidgetManager.getInstance(context),
widget2x2.getIDs(context, appWidgetManager));
}
}
registerServices(Context) is a static method in my AppWidgetProvider classes (MyWidget_1x1/MyWidget_2x2) which registers the needed services.
Hope it will help you too =]
The stuff above does catch the reboot event but fails to catch the clear memory event, because the android.intent.action.PACKAGE_RESTARTED is not sent to the package itself.
I solved this by adding a Service. This service gets its onCreate() called on a clear memory event. Note that you have to start the service with a startService call, which I call from the AppWidgetProvider.
Intent i= new Intent(context, CTService.class);
// potentially add data to the intent
i.putExtra("KEY1", "Value to be used by the service");
ComponentName name = context.startService(i);
The Service code is like:
@Override
public void onCreate()
{
Log.d(TAG,"onCreate");
ping();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"onStartCommand: "+intent.getAction());
//TODO do something useful
ping();
return Service.START_STICKY;
}
with ping
the actual stuff which makes the touch events on the widgets work.
Thanks for successfully researching your own solution. You pointed me in the right direction. I was having a similar problem where the appwidget would not update anymore after a reboot or power cycle, neither would it respond to button clicks anymore.
What I did was first add the following to the manifest:
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Then I created a BootReceiver.java file with something like the following. In my case I had to recreate the alarm and pending intents for the buttons.
public class BootReceiver extends BroadcastReceiver
{
/*
* after reboot widget appears to stop working and becomes unresponsive to clicks
* this broadcast receiver will create new alarm and refresh pending intents
*/
@Override
public void onReceive(Context context, Intent intent)
{
/* do your stuff here, mostly just copy&paste from other places */
}
}
Some credit for this also goes to: Proximity Alerts not working after phone reboot