Notification中Intent攜帶資料重複問題

傲慢的上校發表於2013-01-10

Notification中多個Intent使用putExtra方法攜帶資料,在目的activity中通過getIntent方法取出傳遞資料時,有時候會發現取出來的資料都是第一次putExtra中放入的資料。

下面看下程式碼,比較簡單:

package com.example.notificationdemo;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;


public class FirstActivity extends Activity {
	
	private Button mButton;
	
	private NotificationManager mNotificationManager;
	private Intent mIntent;
	private PendingIntent mPendingIntent;
	Notification mNotification;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.first);	
		
		mNotification = new Notification();
		mIntent = new Intent(FirstActivity.this, MainActivity.class);
		mIntent.putExtra("hello", "first");
		Log.v("@@@@@@", "this is put in intent first....");
		mNotificationManager = 
				(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
		//主要在於PendingIntent的getActivity方法中的引數
		mPendingIntent = PendingIntent.getActivity(FirstActivity.this, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		//如果使用下面註釋掉的程式碼,將會出現上面說講到的問題,當然在SecondActivity中也必須做修改
		//mPendingIntent = PendingIntent.getActivity(FirstActivity.this, 0, mIntent, 0);
		mButton = (Button)findViewById(R.id.first_button);
		mButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View view) {
				showNotification();
			}
		});
	}
	
	private void showNotification() {  
		
		mNotification.icon = R.drawable.message;
		mNotification.defaults = Notification.DEFAULT_SOUND; 
		mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
		mNotification.tickerText = "第一個";
		mNotification.setLatestEventInfo(FirstActivity.this, "第一個",
				"第一個", mPendingIntent);
		mNotificationManager.notify(0, mNotification);
	}
}

第二個Activity:

package com.example.notificationdemo;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SecondActivity extends Activity {
	
	private Button mButton;	
	private NotificationManager mNotificationManager2;
	private Intent mIntent;
	private PendingIntent mPendingIntent2;
	Notification mNotification2;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		
		mNotification2 = new Notification();
		mIntent = new Intent(SecondActivity.this, MainActivity.class);
		mIntent.putExtra("hello", "second");
		Log.v("@@@@@@", "this is doing in second activity");
		mNotificationManager2 = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
		mPendingIntent2 = PendingIntent.getActivity(SecondActivity.this, 1, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		//如果使用下面註釋掉的程式碼,將會出現上面說講到的問題,當然在FirstActivity中也必須做修改(把上面程式碼註釋掉,使用下面行程式碼,就會重現)
		//mPendingIntent2 = PendingIntent.getActivity(SecondActivity.this, 0, mIntent, 0);
		
		mButton = (Button) findViewById(R.id.second_button);		
		mButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View view) {
				showNotification();
			}
		});	
	}
	
	private void showNotification() {    			
		
		mNotification2.icon = R.drawable.message2;
		mNotification2.defaults = Notification.DEFAULT_SOUND; 
		mNotification2.flags |= Notification.FLAG_AUTO_CANCEL;
		mNotification2.tickerText = "第二個";
		
		Log.v("@@@@@@", "intent put second ...");
		mNotification2.setLatestEventInfo(SecondActivity.this, "第二個", "第二個", mPendingIntent2);
		Log.v("@@@@@@", "do shownotification in second activity");
		mNotificationManager2.notify(0, mNotification2);
		
	}	
}

在MainActivity中接受兩個Activity中的Notification傳過來的資料:

package com.example.notificationdemo;

import android.os.Bundle;
import android.app.TabActivity;
import android.content.Intent;
import android.graphics.Color;
import android.util.Log;
import android.view.Menu;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TabHost;

public class MainActivity extends TabActivity implements OnCheckedChangeListener{

	private TabHost mTabHost;
	private RadioGroup mRadioGroup;
	private RadioButton mFirstRadio, mSecondRadio;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        mTabHost = getTabHost();
		mTabHost.addTab(mTabHost.newTabSpec("first").setIndicator("First").setContent(new Intent(this, FirstActivity.class)));
		mTabHost.addTab(mTabHost.newTabSpec("second").setIndicator("Second").setContent(new Intent(this, SecondActivity.class)));
        
        mRadioGroup = (RadioGroup) findViewById(R.id.radiogroup);
		mRadioGroup.setOnCheckedChangeListener(this);
		mFirstRadio = (RadioButton)findViewById(R.id.first_radio);
		mSecondRadio = (RadioButton) findViewById(R.id.second_radio);
		
		Log.v("@@@@@@", "this is doing  in onCreate");
        ChangeChecked(true);
        String str = getIntent().getStringExtra("hello");
    	Log.v("@@@@@@", "the str is " + str);
    	if (str != null && str.equals("first")) {
    		ChangeChecked(true);
    		mTabHost.setCurrentTabByTag("first");
    	} else if (str != null && str.equals("second")) {
    		ChangeChecked(false);
    		mTabHost.setCurrentTabByTag("second");
    	}
        
    }
    
    @Override
    protected void onNewIntent(Intent intent) {    	
    	String str = intent.getStringExtra("hello");
    	if (str != null && str.equals("first")) {
    		ChangeChecked(true);
    		mTabHost.setCurrentTabByTag("first");
    	} else if (str != null && str.equals("second")) {
    		ChangeChecked(false);
    		mTabHost.setCurrentTabByTag("second");
    	}
    	super.onNewIntent(intent);
    	
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {
		switch (checkedId) {
		case R.id.first_radio:
			mTabHost.setCurrentTabByTag("first");
			ChangeChecked(true);
			break;
		case R.id.second_radio:
			mTabHost.setCurrentTabByTag("second");
			ChangeChecked(false);
			break;
		default :
			break;
		}
		
	}
	
	private void ChangeChecked(boolean bool) {
		if (bool) {
			mFirstRadio.setTextColor(Color.RED);
			mFirstRadio.setBackgroundResource(R.drawable.tab_front_bg);
			mSecondRadio.setTextColor(Color.BLACK);
			mSecondRadio.setBackgroundColor(Color.TRANSPARENT);
		} else {
			mSecondRadio.setTextColor(Color.RED);
			mSecondRadio.setBackgroundResource(R.drawable.tab_front_bg);
			mFirstRadio.setTextColor(Color.BLACK);
			mFirstRadio.setBackgroundColor(Color.TRANSPARENT);
		}
	}
}

問題主要出自:

mPendingIntent2 = PendingIntent.getActivity(SecondActivity.this, 1, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		//如果使用下面註釋掉的程式碼,將會出現上面說講到的問題,當然在FirstActivity中也必須做修改(把上面程式碼註釋掉,使用下面行程式碼,就會重現)
		//mPendingIntent2 = PendingIntent.getActivity(SecondActivity.this, 0, mIntent, 0);

看一下getActivity方法:

 PendingIntent android.app.PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)


Retrieve a PendingIntent that will start a new activity, like calling Context.startActivity(Intent). Note that the activity will be started outside of the context of an existing activity, so you must use the Intent.FLAG_ACTIVITY_NEW_TASK launch flag in the Intent.

Parameters:
context The Context in which this PendingIntent should start the activity.
requestCode Private request code for the sender (currently not used).
intent Intent of the activity to be launched.
flags May be FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of the flags as supported by Intent.fillIn() to control which unspecified parts of the intent that can be supplied when the actual send happens.
Returns:
Returns an existing or new PendingIntent matching the given parameters. May return null only if FLAG_NO_CREATE has been supplied.


引數requestCode用於區分Intent,如果flag為FLAG_UPDATE_CURRENT會即使更新intent中資料。

關於該方法的詳細概述,敬請檢視後面關於notification的原始碼解析,打算在週末的時候看一下notification原始碼,那個時候再詳細分析下。


相關文章