Notification PendingIntent extras always empty

2019-07-26 09:35发布

问题:

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));
        }
    }
    ...
}

回答1:

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).