Decide what touching Notification icon does

2019-06-04 01:34发布

问题:

I have a scenario where I want to display a message which i show in the notification box to a new screen when the notification box is touched. I am able to generate the notification on the cell phone but when I touch the notification box I am unable to display that notification message instead some old message is being displayed. Can someone help me with it.

Below is code for the Activity I want to start:

public class MainActivity extends Activity {
// label to display gcm messages
TextView lblMessage;

// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;

// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();

// Connection detector
ConnectionDetector cd;

public static String name;
public static String email;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    cd = new ConnectionDetector(getApplicationContext());

    // Check if Internet present
    if (!cd.isConnectingToInternet()) {
        // Internet Connection is not present
        alert.showAlertDialog(MainActivity.this,
                "Internet Connection Error",
                "Please connect to working Internet connection", false);
        // stop executing code by return
        return;
    }

    // Getting name, email from intent
    Intent i = getIntent();

    name = i.getStringExtra("name");
    email = i.getStringExtra("email");      

    // Make sure the device has the proper dependencies.
    GCMRegistrar.checkDevice(this);

    // Make sure the manifest was properly set - comment out this line
    // while developing the app, then uncomment it when it's ready.
    GCMRegistrar.checkManifest(this);

    lblMessage = (TextView) findViewById(R.id.lblMessage);
    lblMessage.setText("");
    String previous=i.getStringExtra("previous message");
    if(!previous.equals("The Very Beginning"))
    lblMessage.setText(previous);
    registerReceiver(mHandleMessageReceiver, new IntentFilter(
            DISPLAY_MESSAGE_ACTION));

    // Get GCM registration id
    final String regId = GCMRegistrar.getRegistrationId(this);

    // Check if regid already presents
    if (regId.equals("")) {
        // Registration is not present, register now with GCM           
        GCMRegistrar.register(this, SENDER_ID);
    } else {
        // Device is already registered on GCM
        if (GCMRegistrar.isRegisteredOnServer(this)) {
            // Skips registration.
            if(previous.equals("The Very Beginning"))
            Toast.makeText(getApplicationContext(), "Already registered with GCM", Toast.LENGTH_LONG).show();
            Log.v("Reg ID", regId);
        } else {
            // Try to register again, but not in the UI thread.
            // It's also necessary to cancel the thread onDestroy(),
            // hence the use of AsyncTask instead of a raw thread.
            final Context context = this;
            mRegisterTask = new AsyncTask<Void, Void, Void>() {

                @Override
                protected Void doInBackground(Void... params) {
                    // Register on our server
                    // On server creates a new user
                    ServerUtilities.register(context, name, email, regId);
                    return null;
                }

                @Override
                protected void onPostExecute(Void result) {
                    mRegisterTask = null;
                }

            };
            mRegisterTask.execute(null, null, null);
        }
    }
}       

/**
 * Receiving push messages
 * */
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
        // Waking up mobile if it is sleeping
        WakeLocker.acquire(getApplicationContext());

        /**
         * Take appropriate action on this message
         * depending upon your app requirement
         * For now i am just displaying it on the screen
         * */

        // Showing received message
        lblMessage.setText(newMessage + "\n");          
        Toast.makeText(getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show();

        // Releasing wake lock
        WakeLocker.release();
    }
};

@Override
protected void onDestroy() {
    if (mRegisterTask != null) {
        mRegisterTask.cancel(true);
    }
    try {
        unregisterReceiver(mHandleMessageReceiver);
        GCMRegistrar.onDestroy(this);
    } catch (Exception e) {
        Log.e("UnRegister Receiver Error", "> " + e.getMessage());
    }
    super.onDestroy();
}

}

Below is the code for GCM Broadcast class:

import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {

private static final String TAG = "GCMIntentService";

public GCMIntentService() {
    super(SENDER_ID);
}

/**
 * Method called on device registered
 **/
@Override
protected void onRegistered(Context context, String registrationId) {
    Log.i(TAG, "Device registered: regId = " + registrationId);
    displayMessage(context, "Your device registred with GCM");
    Log.d("NAME", MainActivity.name);
    ServerUtilities.register(context, MainActivity.name, MainActivity.email, registrationId);
}

/**
 * Method called on device un registred
 * */
@Override
protected void onUnregistered(Context context, String registrationId) {
    Log.i(TAG, "Device unregistered");
    displayMessage(context, getString(R.string.gcm_unregistered));
    ServerUtilities.unregister(context, registrationId);
}

/**
 * Method called on Receiving a new message
 * */
@Override
protected void onMessage(Context context, Intent intent) {
    Log.i(TAG, "Received message");
    String message = intent.getExtras().getString("message");

    displayMessage(context, message);
    // notifies user
    generateNotification(context, message);
}

/**
 * Method called on receiving a deleted message
 * */
@Override
protected void onDeletedMessages(Context context, int total) {
    Log.i(TAG, "Received deleted messages notification");
    String message = getString(R.string.gcm_deleted, total);
    displayMessage(context, message);
    // notifies user
    generateNotification(context, message);
}

/**
 * Method called on Error
 * */
@Override
public void onError(Context context, String errorId) {
    Log.i(TAG, "Received error: " + errorId);
    displayMessage(context, getString(R.string.gcm_error, errorId));
}

@Override
protected boolean onRecoverableError(Context context, String errorId) {
    // log message
    Log.i(TAG, "Received recoverable error: " + errorId);
    displayMessage(context, getString(R.string.gcm_recoverable_error,
            errorId));
    return super.onRecoverableError(context, errorId);
}

/**
 * Issues a notification to inform the user that server has sent a message.
 */
private static void generateNotification(Context context, String message) {
    int icon = R.drawable.ic_launcher;
    long when = System.currentTimeMillis();
    NotificationManager notificationManager = (NotificationManager)
            context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification = new Notification(icon, message, when);

    String title = context.getString(R.string.app_name);

    Intent notificationIntent = new Intent(context, MainActivity.class);
    // set intent so it does not start a new activity
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
            Intent.FLAG_ACTIVITY_SINGLE_TOP);
    //Here to
    notificationIntent.putExtra("previous message", message);
    //Here
    PendingIntent intent =
            PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notification.setLatestEventInfo(context, title, message, intent);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;

    // Play default notification sound
    notification.defaults |= Notification.DEFAULT_SOUND;

    //notification.sound = Uri.parse("android.resource://" + context.getPackageName() + "your_sound_file_name.mp3");

    // Vibrate if vibrate is enabled
    notification.defaults |= Notification.DEFAULT_VIBRATE;
    notificationManager.notify(0, notification);      

}

}

回答1:

also override onNewIntent. Activity is not destroyed immediately. For example (code which works for me):

notifying:

 private int m_notifyId = 0;
private void noti() {
    m_notifyId++;
    if (m_notifyId == Integer.MAX_VALUE) // ha ha
            m_notifyId = 1;

    NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    Notification noti = new Notification(android.R.drawable.ic_menu_agenda, "Notification Alert", System.currentTimeMillis());

    Intent notifyIntent = new Intent(this, NotificationReceiver.class);
    notifyIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    notifyIntent.putExtra("test", "notification");
    double d = m_random.nextDouble();
    notifyIntent.putExtra("double", d);
    // despite that docs says that requestCode is not used in getActivity
    // it is actually used. Try with same requestCode.

    PendingIntent pendingIntent = PendingIntent.getActivity(this, m_notifyId, notifyIntent, PendingIntent.FLAG_ONE_SHOT);
    noti.setLatestEventInfo(getApplicationContext(), (CharSequence)"Notification", (CharSequence)("Notification: " + d), pendingIntent);
     noti.flags |= Notification.FLAG_AUTO_CANCEL;

    nm.notify(m_notifyId, noti);

}

handling

private TextView m_tvInfo;

    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.notification_receiver_main);

            m_tvInfo = (TextView) findViewById(R.id.tvInfo);

            Intent intent = getIntent();

            Log.d("log", "onCreate getIntent");

                        // check if extras contains the key.

            String test = intent.getExtras().getString("test");
            test += "\n" + Double.toString(intent.getExtras().getDouble("double"));

            m_tvInfo.setText(test);
    }



    @Override
    protected void onNewIntent(Intent intent) {
                  setIntent(intent); // maybe not needed. depends on the activity logic.

            Log.d("log", "onNewIntent");

            String test = intent.getExtras().getString("test");
            test += "\n" + Double.toString(intent.getExtras().getDouble("double"));
            m_tvInfo.setText(test); 

    }

NB. imho and old code.



回答2:

You are using the following flags :

FLAG_ACTIVITY_CLEAR_TOP

If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.

FLAG_ACTIVITY_SINGLE_TOP

If set, the activity will not be launched if it is already running at the top of the history stack.

This means that if the activity you are trying to open is already running, a new one won't be created, and the existing one will be on top. That's why onCreate is not executed and the new message is not displayed. You can either use different flags (to force the creation of a new activity), or you can update the message from a different method (such as onResume).