Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service does not restart after "Clear Memory" + appWidget crashes

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();
  }
like image 577
GalDude33 Avatar asked Dec 27 '22 12:12

GalDude33


2 Answers

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 =]

like image 156
GalDude33 Avatar answered Jan 03 '23 00:01

GalDude33


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.

like image 29
Klamer Schutte Avatar answered Jan 02 '23 23:01

Klamer Schutte