0

A short introduction as I can: I have a MainActivity that implements SomeInterface, a headless state Fragment called HeadlessFragment. HeadlessFragment is setting an alarm (with compliance to API 18) on the onAttach method:

Fragment Code
----------------

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    try {
        mCallback = (SomeInterface) activity; //HERE IT WORKS!!!
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement SomeInterface");
    }

    //create the Intent for MyBroadCast
    mIntent= new Intent(activity, MyBroadCast.class);
    mPendingIntent = PendingIntent.getBroadcast(activity, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    //Set up the Alarm
    mAlarmManager = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
    mAlarmManager.cancel(mPendingIntent );
    mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 2000, 10000, mPendingIntent );


}

Now I would expect this activity variable to pass through as it is to MyBroadCast, so I implemented MyBroadCast's onReceive as the following:

BroadCast Code
-----------------

public void onReceive(Context c, Intent indent) {
    mContext = c;

    try {
        // HERE IT DOESN'T WORK - ClassCastException is thrown
        SomeInterface callback = (SomeInterface) c;
        callback.SomeInterfaceMethod(s);

    } catch (ClassCastException e) {
        throw new ClassCastException(c.toString()
                + " must implement SomeInterface");
    }
}

Unfortunately, it isn't working, as I can't make this cast, and apparently something goes wrong with the context either in the PendingIntent or the Alarm mechanism, but I have no clue how to investigate further. Does someone here have particular/important insights regarding this issue, before I'm going to change completely my design?

Of course I did my share of reading by going through the entries of Fragments, Intents, Broadcastreceivers in aspect of the context in developer.android API documentation, but couldn't find something of interest.

Aviv
  • 414
  • 4
  • 16

1 Answers1

0

I think ultimately the design depends on what you need your callback to do, but consider that the broadcast receiver could call onReceive when your app is not running. (e.g., your alarm is set, then your user switches to another app).

If you simply want to run some code periodically, while your app is active, I'd recommend using Handler.postDelayed. If you need to do work that doesn't involve the ui (e.g., update a database in the background), I'd recommend a Service.

chessdork
  • 1,999
  • 1
  • 19
  • 20
  • This particular code has to run even when the program is closed. Being more accurate keeping some data always fresh. I assume I should use an alarm instead of an handler because of the "work-even-when-program-is-closed" thingy. Of course you could offer me better designs, but I'm still interested in why the context suddenly changes (although the program is still on the foreground) – Aviv Jan 17 '16 at 17:20
  • I don't think the context has necessarily changed. `onAttach` provides you with an activity. Activities are ContextWrappers. `onReceive` provides you with the context, NOT the activity. And in this case, only the Activity implements the custom interface, not the context. – chessdork Jan 17 '16 at 17:41
  • You are saying it as these are different objects, but Activity is a context and im passing it as it is. As far as I understand I should be able to deduce the older runtime type, unless someone behind is building a new Context based on the given activity. – Aviv Jan 17 '16 at 17:51
  • They are actually different. You are right that an activity is a context, but only because the activity has a reference to a context that it delegates to. Check out the docs for contextwrapper. – chessdork Jan 17 '16 at 18:23