1

I read about this all day long with different kind of solutions but non worked so far.

I have an upload service (IntentService) that sends updates to a ResultReceiver. The receiver creates and manages the Notification.

After clicking on the notification (error or success) the MainActivity is loaded. But the bundle is always null. How can I change my code to access/get the bundle?

This happens if I'am in another Activity, if the App is in background and if the app is stopped.

CustomResultReceiver:

private Context mContext;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder mBuilder;

public static final String RETURN_MESSAGE = "RETURN_MESSAGE";
public static final String RETURN_STATUS = "RETURN_STATUS";

private final int id = 1;

public CustomResultReceiver(Handler handler, Context context) {
        super(handler);
        mContext = context;
        mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(context);
        mBuilder.setContentTitle("Upload data")
                .setContentText("uploading...")
                .setSmallIcon(R.mipmap.ic_launcher);
    }

Creates the Notification. In onReceiveResult I notify the notification and if an error occured or the upload is successful I add a ContentIntent.

protected void onReceiveResult(int resultCode, Bundle resultData) {

    super.onReceiveResult(resultCode, resultData);
    String message;
    boolean success;    

switch (resultCode) {
case RESULT_ERROR:

                message = resultData.getString(BROADCAST_MESSAGE, null);
                boolean failed = resultData.getBoolean(EXTENDED_ACTION_FAILED, false);
                if (failed) {
                    mBuilder.setProgress(0, 0, false);
                    mBuilder.setContentText("Aborted! Error while uploading.");
                    mBuilder.setContentIntent(createContentIntent(message, false));
                    mNotificationManager.notify(id, mBuilder.build());
                }
                break;
 case RESULT_FINISHED:
                message = resultData.getString(UPLOAD_MESSAGE, null);
                success = resultData.getBoolean(UPLOAD_STATUS, false);
                if (success) {
                    mBuilder.setProgress(0, 0, false);
                    mBuilder.setContentText("Upload successful");
                    mBuilder.setContentIntent(createContentIntent(message, true));
                    mNotificationManager.notify(id, mBuilder.build());
                }
                break;
}
}

createContentIntent() provides a PendingIntent with a result message and a success boolean:

private PendingIntent createContentIntent(String message, boolean success) {
        Intent intent = new Intent(mContext, MainActivity.class);
        intent.putExtra(RETURN_MESSAGE, message);
        intent.putExtra(RETURN_STATUS, success);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.setAction("NOTIFIY RESPONSE");
        return PendingIntent.getActivity(mContext, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

In the receiver I'am using:

android.app.NotificationManager;
android.app.PendingIntent;
android.content.Context;
android.content.Intent;
android.os.Bundle;
android.os.Handler;
android.os.ResultReceiver;
android.support.v4.app.NotificationCompat;

The MainActivity is an android.support.v7.app.AppCompatActivity.

For the creation of the PendingIntent I already tried several different Flag combinations.

Here are some snippets from the manifest:

My permissions:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera"/>

The Activity that I open via the Notification:

<activity
            android:name=".views.activities.MainActivity"
            android:label="@string/title_activity_main"
            android:screenOrientation="landscape"
            android:theme="@style/AppTheme.NoActionBar"
            android:windowSoftInputMode="stateHidden">
            <intent-filter>
                <action android:name="android.intent.action.RUN"/>
            </intent-filter>
</activity>

Here the Service:

<service android:name=".services.UploadService"/>

For when I launch the activity from the ResultReceiver following happens:

The activity starts and onCreate is called where i check for the bundle like this:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.act_main);

    ...
    Intent old = getIntent();
    if (old != null) {
        Bundle extras = old.getExtras();
        if (extras != null) {
            Log.d(MainActivity.class.getSimpleName(), "Message: " + extras.getString(CustomResultReceiver.RETURN_MESSAGE, "empty"));
            Log.d(MainActivity.class.getSimpleName(), "Status: " + extras.getBoolean(CustomResultReceiver.RETURN_STATUS, false));
        }
    }
    ...
}
Ben
  • 117
  • 15
  • post your manifest please – David Wasser Feb 13 '18 at 19:27
  • and post the code where you expect to find stuff in the extras Bundle. – David Wasser Feb 13 '18 at 19:28
  • @DavidWasser I added both, the (maybe) relevant manifest snippets and the onCreate of the MainActivity. I also tried to get the bundle in the onNewIntent Method which wasn't called (some other threads suggested this). I also tried changing the requestcode which didn't help. – Ben Feb 14 '18 at 06:55
  • Yeah I tried another code but nothing changed. But now I tried around with other flags. What's working now is: For the intent -> `intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);` and for the PendingIntent.getActivity() -> `PendingIntent.FLAG_CANCEL_CURRENT` – Ben Feb 14 '18 at 07:10
  • I added an answer if you are interested in why I didn't work. – Ben Feb 14 '18 at 07:40

1 Answers1

0

So I finally found the problem. After debugging several flag options and changing request codes. The request code here is irrelevant to the problem.

Responsible for the empty (not null) bundle is the flag ACTIVITY_NEW_TASK.

If I went with all other tested flags for the Intent or the PendingIntent everything works fine.

The android doc says following for ACTIVITY_NEW_TASK:

When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in. See FLAG_ACTIVITY_MULTIPLE_TASK for a flag to disable this behavior.

This seems to indicate that the old Intent is still present and not the new one which I build in the receiver. Funny fact: even if I closed the app and then started the PendingIntent the bundle was empty. The doc as for my understanding would state it otherwise (activity not in a task? -> new task with new activity).

Ben
  • 117
  • 15
  • so try [this](https://pastebin.com/raw/pWYYuuJ0) - no need for playing with flags, does it work? – pskink Feb 14 '18 at 07:41
  • of course if you want activity to be called you have to use `getActivity` - i used service as it is easier to test it – pskink Feb 14 '18 at 08:00
  • Well, it's working now like I said above. But i tried your suggestion anyway. It works fine without the flags BUT using your `onStartCommand` override my service stopped working. If I just use the flagless part of the activity part you suggested it also works but instead of in `onCreate` I get the Intent in the `onNewIntent` method. So its also working with that approach. – Ben Feb 14 '18 at 08:13
  • service works ok, where would it crash? on `Log.d`? for activity, yes: if it is not started then `onCreate` is called, otherwise you have to catch your `Intent` inside `onNewIntent` method – pskink Feb 14 '18 at 08:17
  • It's not crashing just not starting probably due to my service call. I use a button which starts the service via `activity.startService(intent)` in your approach you use the notification to start the service via the `PendingIntent`. But again its working fine now. – Ben Feb 14 '18 at 08:24