8

let's say I want to implement an app which exposes services to other apps (like Google Play Services..).

potential apps would register to my special events associated with my services, and would be notified at the right time.

I was thinking to implement this exactly like Google did with the Google Play services:

thanks to Android Inter-Process Communication, other apps could bind to my app Service, and by that - pass to my app PendingIntent "callback" that I could execute for them at the right time.

now, I'll get to the problem:

  • my app process currently running (in background) and holding reference to PendingIntent provided by other app.

  • now, from some reason (System decisions/ user explicitly) my process been stopped.

  • my process cumming back in some point, and come back to "do it's thing.."

in that point - I lost reference to the PendingIntent provided to me before, and I don't see any way in the API to retrieve back reference to it.

also I don't see any way to save persistently(database/sharedPreferences/file system) saving the pending intent for latter on usage

my questions are:

  • is it possible to store pending intent persistently somehow?

  • is it possible to "get back" reference to the same pending intent I already got before?

  • if not, is there any other suggestion to implement such thing as I described?

Tal Kanel
  • 10,475
  • 10
  • 60
  • 98

2 Answers2

4

is it possible to store pending intent persistently somehow?

No.

is it possible to "get back" reference to the same pending intent I already got before?

Not from the OS. If you have some other "bootstrap" communications method, you could ask the original app to re-supply a PendingIntent. For example, you could send a broadcast stating that you need apps to re-register; apps using your service would listen for such broadcasts and give you a fresh PendingIntent.

Or, skip the PendingIntent entirely and use something else. For example, apps could export a BroadcastReceiver. Where they would register a PendingIntent in your current plan, they would simply provide you the ComponentName of the BroadcastReceiver. That information (package name and class name) could be persisted, and you could then send a broadcast to that specific ComponentName as needed.

Note that with any strategy that involves persistence, you will need to deal with the cases where the client app has been upgraded and the old stored details are now incorrect (e.g., they refactored their code, and the old ComponentName is now invalid).

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I thought about this solutions, but they are suffering form two main problems: (1) I would like to avoid from making my clients life hard with complex API requires handling re-registration. (2) if I'll let my clients to register directly to my broadcasts, then they would have access to the action name and type, and by that - "spread" this information to others, and I'll lost the ability to control who can get this broadcast – Tal Kanel Jan 12 '14 at 20:56
  • @TalKanel: Then skip the `PendingIntent` and use something else. – CommonsWare Jan 12 '14 at 20:58
  • @TalKanel, you can still control who can get this broadcast by broadcasting it to a specific ComponentName that properly registered to your service. This way you can manage quotas and limit your broadcast only to the ones your service approved. – MikeL Apr 19 '15 at 10:42
  • @michael Liberman: yes, I know. Actually this is exactly what I ended up doing – Tal Kanel Apr 19 '15 at 18:05
0

I say Yes,it is possible to save pending intent for using right time but not as usual there is possibility something already happened with pending intent or another application maybe removed so pending intent is no more useful...But if pending intent is not destroyed yet then you save it for a right time.And fire pending intent as usual..

CODE:

public void savePendingIntent(Context context,PendingIntent pendingIntentYouWantToSave)
{
    int YEAR=2015;
    int MONTH=10; //remember month start from 0
    int DATE=25;
    int HOUR=12;
    int MINUTE=10;
    int SECOND=0;
    Calendar righttime = Calendar.getInstance();
    righttime.setTimeInMillis(System.currentTimeMillis());
    righttime.set(YEAR, MONTH,DATE, HOUR, MINUTE, SECOND);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    intent.putExtra("SAVED_PI", pendingIntentYouWantToSave);
    PendingIntent pi = PendingIntent.getBroadcast(context, 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.set(AlarmManager.RTC_WAKEUP, righttime.getTimeInMillis(),pi);
}

HERE IS AlarmBroadcastReceiver

public class AlarmBroadcastReceiver extends BroadcastReceiver 
{    
     @Override
     public void onReceive(Context context, Intent intent) 
     {   //your saved pending intent
         PendingIntent  SAVED_PI = (PendingIntent) intent.getParcelableExtra("SAVED_PI");
        //Fire it if need or save it again for later use
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            SAVED_PI.send(context, 0, intent);
        } catch (PendingIntent.CanceledException e) {
            Log.d("ERROR_ON_FIRE", "ERROR_ON_FIRE");
        }
     }
}

Hope this will help someone

Ashish Sahu
  • 1,538
  • 17
  • 22
  • saving the pending intent with the AlramManger is still not persistent. in the minute the operating system will shout down/reboot then this pending intent reference will be lost also from the alarm manager. – Tal Kanel Jan 29 '15 at 13:54
  • I totally agree with you but this is only way to doing this yet...Maybe upcoming api provide better way to handle this type of situation...And there is also possibility destroyed pendingintent will re-create by system after rebooting... – Ashish Sahu Jan 29 '15 at 16:05