版權聲明:本文為博主原創(chuàng)文章逻淌,轉載請附上原文出處鏈接和本聲明么伯。
本文鏈接:http://www.reibang.com/p/a3744cae1b52
友情提示:在看本文前,最好對友盟推送的集成文檔看個差不多卡儒,不然可能有些概念不是太清楚田柔。
友盟集成文檔:https://developer.umeng.com/docs/66632/detail/98581
本文demo下載地址:https://github.com/274800562/umengtest.git
----------------分割線--------------------
應用分為在線狀態(tài)和離線狀態(tài),以應用進程是否存在為判斷依據(jù)骨望。
通知分為在線通知和離線通知硬爆,同樣以應用進程是否存在時為判斷依據(jù)。進程存在時接收到的通知即在線通知擎鸠,離線時接收到的通知為離線通知缀磕。
一 、需求描述:
1.應用離線時,收到通知袜蚕,點擊通知糟把,啟動應用,啟動SplashActivity->MainActivity,然后根據(jù)需要跳轉相應界面牲剃。
2.應用在線:
1)應用在前臺時遣疯,收到通知,應用內彈框颠黎,點擊跳轉響應界面另锋;
2)應用在后臺時,收到通知狭归,存儲通知數(shù)據(jù)夭坪,待應用切回到前臺時再彈框,點擊跳轉響應界面过椎。
二室梅、需求實現(xiàn)
首先,我們設定有SplashActivity疚宇、MainActivity亡鼠、DetailActivity、ListActvity四個類敷待,我們通過UMessage對象的extra字段配置數(shù)據(jù):type,id,title等间涵,type=1時,跳轉DetailActivity榜揖;type=2時勾哩,跳轉ListActvity。
1.友盟推送可以集成廠商通道举哟,以接收離線通知思劳。通過繼承UmengNotifyClickActivity類,重寫onMessage(),點擊時回調此方法妨猩。
public class UmengClickActivityextends UmengNotifyClickActivity {
private static StringTAG = UmengClickActivity.class.getName();
@Override
public void onMessage(Intent intent0) {
super.onMessage(intent0); //此方法必須調用潜叛,否則無法統(tǒng)計打開數(shù)
String body = intent0.getStringExtra(AgooConstants.MESSAGE_BODY);
Log.e(TAG, "body:" + body);
Gson gson = new Gson();
UmengClickBean bean = gson.fromJson(body, UmengClickBean.class);
//ExtraBean包含三個字段:type,id,title,根據(jù)type跳轉相應界面
ExtraBean extraBean = bean.getExtra();
if (null != bean) {
Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//必須
intent.putExtra("bean", extraBean);
intent.putExtra("tag", 1);//標志位,點擊跳過去的壶硅,區(qū)別于正常邏輯跳轉
startActivity(intent);
finish();
}
}
}
接著威兜,啟動SplashActivity->MainActivity。
public class SplashActivity extends AppCompatActivity {
public static final String TAG = "SplashActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int tag = getIntent().getIntExtra("tag", 0);
//1.其他操作 省略
//2.跳主界面
Intent intent = new Intent(this,MainActivity.class);
//tag==1時說明是點擊離線通知過來的庐椒,需要攜帶數(shù)據(jù)跳轉
if (tag == 1) {
ExtraBean extraBean= (ExtraBean) getIntent().getSerializableExtra("bean");
intent.putExtra("bean", extraBean);
intent.putExtra("tag", tag);
}
startActivity(intent);
}
}
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int tag = getIntent().getIntExtra("tag", 0);
if (tag == 1) {//點擊通知跳轉過來的牡属,有攜帶數(shù)據(jù),需要執(zhí)行跳轉邏輯扼睬,根據(jù)type跳對應界面
ExtraBean extraBean = (ExtraBean) getIntent().getSerializableExtra("bean");
int type = extraBean.getType();
Log.e(TAG, "umeng type:" + type);
Intent intent = null;
if (type == 1) {
intent = new Intent(this, DetailActivity.class);
} else {
intent = new Intent(this, ListActivity.class);
}
intent.putExtra("bean", extraBean);
startActivity(intent);
}
}
}
DetailActivity逮栅、ListActivity代碼相同:
public class DetailActivity extends AppCompatActivity {
public static final String TAG = "DetailActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExtraBean extraBean= (ExtraBean) getIntent().getSerializableExtra("bean");
String id = String.valueOf(extraBean.getId());
String title = extraBean.getTitle();
TextView textView = findViewById(R.id.textview);
textView.setText("id:"+id+"\n"+"title:"+title);
}
}
按上面的代碼執(zhí)行是沒有什么問題的悴势,但是有一種情況時,收到離線通知措伐,不去點擊特纤,啟動app,再去點擊侥加。這時候依然會去執(zhí)行UmengClickActivity里的onMessage()方法捧存。按照上邊的邏輯會啟動SplashActivity,而不是根據(jù)type值啟動對應的Activity担败。
我的實現(xiàn)思路是昔穴,在onMessage()方法內部添加判斷,根據(jù)結果執(zhí)行不同邏輯提前。
public class UmengClickActivity extends UmengNotifyClickActivity {
private static String TAG = UmengClickActivity.class.getName();
@Override
public void onMessage(Intent intent0) {
super.onMessage(intent0); //此方法必須調用吗货,否則無法統(tǒng)計打開數(shù)
String body = intent0.getStringExtra(AgooConstants.MESSAGE_BODY);
Log.e(TAG, "body:" + body);
Gson gson = new Gson();
//將接收到的body信息裝換成UmengClickBean
UmengClickBean bean = gson.fromJson(body, UmengClickBean.class);
//ExtraBean包含三個字段:type,id,title,根據(jù)type跳轉相應界面
ExtraBean extraBean = bean.getExtra();
if (null != bean) {
int type = extraBean.getType();
Intent intent = null;
/**
* 判斷棧中是否有MainActivity,有則意味著程序已啟動狈网,否則沒有
*/
if (isExistMainActivity(MainActivity.class)) {
if (type == 1) {
intent = new Intent(this, DetailActivity.class);
} else {
intent = new Intent(this, ListActivity.class);
}
} else {
intent = new Intent(this, SplashActivity.class);
intent.putExtra("tag", 1);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
intent.putExtra("bean", extraBean);
startActivity(intent);
finish();
}
}
@TargetApi(Build.VERSION_CODES.Q)
private boolean isExistMainActivity(Class<?> activity) {
Intent intent = new Intent(this, activity);
ComponentName cmpName = intent.resolveActivity(getPackageManager());
boolean flag = false;
if (cmpName != null) { // 說明系統(tǒng)中存在這個activity
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfoList =
am.getRunningTasks(10);
//這里獲取的是APP棧的數(shù)量宙搬,一般也就兩個
ActivityManager.RunningTaskInfo runningTaskInfo = taskInfoList.get(0);
// 只是拿當前運行的棧
int numActivities = taskInfoList.get(0).numActivities;
for (ActivityManager.RunningTaskInfo taskInfo : taskInfoList) {
if (taskInfo.baseActivity.equals(cmpName)) {// 說明它已經(jīng)啟動了
flag = true;
break;//跳出循環(huán),優(yōu)化效率
}
}
}
return flag;
}
}
2.應用在前臺時拓哺,接收推送勇垛,彈框;在后臺時存數(shù)據(jù)士鸥,待應用切到前臺時再彈框闲孤。
在前臺時,在umeng 封裝類里的setMessageHandler()方法內部烤礁,重寫某個方法讼积,我們是重寫dealWithNotificationMessage()。
UmengHelper.java
public class UmPushHelper {
public static final String TAG = "UmPushHelper";
static UmPushHelper umPushHelper;
Context context = MyApplacation.getMyApplication();
private PushAgent mPushAgent;
public static UmPushHelper getInstance() {
if (null == umPushHelper) {
umPushHelper = new UmPushHelper();
}
return umPushHelper;
}
/**
* 友盟初始化
* <p>
* 友盟初始化及相關配置
* 注冊
* 通道配置
*/
public void init() {
//
UMConfigure.init(context, "Appkey", "Umeng",
UMConfigure.DEVICE_TYPE_PHONE, "Umeng Message Secret");
UMConfigure.setLogEnabled(true);//日志輸出鸽凶,上線關閉
mPushAgent = PushAgent.getInstance(context);
mPushAgent.register(new IUmengRegisterCallback() {
@Override
public void onSuccess(String deviceToken) {
//注冊成功會返回deviceToken deviceToken是推送消息的唯一標志
Log.i(TAG, "注冊成功:deviceToken:--------> " + deviceToken);
}
@Override
public void onFailure(String s, String s1) {
Log.e(TAG, "注冊失敱疑啊:--------> " + "s:" + s + ",s1:" + s1);
}
});
//小米通道
MiPushRegistar.register(context, "xiaomiId", "xiaomiKey");
//華為通道
HuaWeiRegister.register(MyApplacation.getMyApplication());
//魅族通道
MeizuRegister.register(context, "appId", "appKey");
mPushAgent.onAppStart();
//最多展示條數(shù)
mPushAgent.setDisplayNotificationNumber(10);
//通知或消息接收
setMessageHandler();
//通知點擊
setNotificationClickHandler();
}
/**
* MessageHandler有很多回調方法建峭,根據(jù)自己需要選擇
*/
private void setMessageHandler() {
UmengMessageHandler messageHandler = new UmengMessageHandler() {
@Override
public void dealWithNotificationMessage(Context context, UMessage uMessage) {
super.dealWithNotificationMessage(context, uMessage);
Log.e(TAG, "um notification msg.extra" + uMessage.extra);
try {
JSONObject object = new JSONObject(uMessage.extra);
int type = object.getInt("type");
Long id = object.getLong("id");
String title = object.getString("title");
ExtraBean bean = new ExtraBean();
bean.setId(id);
bean.setType(type);
bean.setTitle(title);
/**
* 應用不在前臺時玻侥,不彈框,并把推送的數(shù)據(jù)存起來
*
* 在前臺時直接彈框
*/
if (MyApplacation.getMyApplication().getActivityCount() == 0) {
ExtraBeanDao dao = MyApplacation.getMyApplication().getDaoSession().getExtraBeanDao();
dao.insertOrReplace(bean);
return;
}
Intent intent = new Intent(context, NotificationDialogActivity.class);
intent.putExtra("bean", bean);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (JSONException e) {
e.printStackTrace();
}
}
};
PushAgent.getInstance(context).setMessageHandler(messageHandler);
}
private void setNotificationClickHandler() {
/**
* 自定義行為的回調處理亿蒸,參考文檔:高級功能-通知的展示及提醒-自定義通知打開動作
* UmengNotificationClickHandler是在BroadcastReceiver中被調用凑兰,故
* 如果需啟動Activity,需添加Intent.FLAG_ACTIVITY_NEW_TASK
* */
UmengNotificationClickHandler notificationClickHandler = new UmengNotificationClickHandler() {
@Override
public void launchApp(Context context, UMessage msg) {
Log.e("umenguuu", "helper launchApp extra:" + msg.extra.toString());
super.launchApp(context, msg);
}
@Override
public void openUrl(Context context, UMessage msg) {
Log.e("umenguuu", "helper openUrl extra:" + msg.extra.toString());
super.openUrl(context, msg);
}
@Override
public void openActivity(Context context, UMessage msg) {
//獲取extra字段值
Log.e("umenguuu", "helper openActivity extra:" + msg.extra.toString());
try {
JSONObject object = new JSONObject(msg.extra);
int type = object.getInt("type");
long id = object.getLong("id");
String title = object.getString("title");
ExtraBean extraBean = new ExtraBean();
extraBean.setId(id);
extraBean.setType(type);
extraBean.setTitle(title);
Intent intent;
Log.e("umenguuu", "helper type:" + type);
/**
* type=1 跳詳情界面
* type=2 跳列表界面
*/
if (type == 1) {
intent = new Intent(context, DetailActivity.class);
} else {
intent = new Intent(context, ListActivity.class);
}
intent.putExtra("bean", extraBean);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void dealWithCustomAction(Context context, UMessage msg) {
Log.e("umenguuu", "helper dealWithCustomAction extra:" + msg.extra.toString());
}
};
//使用自定義的NotificationHandler PushAgent.getInstance(context).setNotificationClickHandler(notificationClickHandler);
}
}
應用在前臺還是在后臺的判斷是在MyApplication.java內部, mActivityCount==0時边锁,意味著應用在后臺姑食。
public class MyApplacation extends Application {
public static final String TAG = "MyApplication";
private static MyApplacation app;
private DaoSession daoSession;
private int mActivityCount = 0;
public static MyApplacation getMyApplication() {
return app;
}
@Override
public void onCreate() {
super.onCreate();
app = this;//
UmPushHelper.getInstance().init();//初始化友盟推送
initDb();//初始化數(shù)據(jù)庫
/**
* 通過mActivityCount判斷當前應用在前臺還是在后臺
*/
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated");
}
@Override
public void onActivityStarted(Activity activity) {
Log.d(TAG, "onActivityStarted");
mActivityCount++;
}
@Override
public void onActivityResumed(Activity activity) {
Log.d(TAG, "onActivityResumed");
/**
* 后臺切前臺的時候,判斷是否有未彈框的通知消息茅坛,如果有遍歷彈框
*
* 說明:此處設計的是彈框疊加音半,如果只彈一個框则拷,luanchMode="SingleTop"
* 并在NotificationDialogActivity內的onNewIntent()方法內處理邏輯
*
*/
List<ExtraBean> list = getDaoSession().getExtraBeanDao().queryBuilder().list();
if (null != list && list.size() > 0) {
for (ExtraBean bean : list) {
Intent intent = new Intent(activity, NotificationDialogActivity.class);
intent.putExtra("bean", bean);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//必須
activity.startActivity(intent);
}
getDaoSession().getExtraBeanDao().deleteAll();
}
}
@Override
public void onActivityPaused(Activity activity) {
Log.d(TAG, "onActivityPaused");
}
@Override
public void onActivityStopped(Activity activity) {
Log.d(TAG, "onActivityStopped");
mActivityCount--;
if (mActivityCount == 0) {//此時切后臺
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.d(TAG, "onActivitySaveInstanceState");
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.d(TAG, "onActivityDestroyed");
}
});
}
public int getActivityCount(){
return mActivityCount;
}
public void initDb() {
MyOpenHelper helper = new MyOpenHelper(this, "test.db", null);
//對數(shù)據(jù)庫庫加密
// Database db = helper.getEncryptedWritableDb(UUID);
//不加密,uyi
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
}
彈框:用一個透明activity實現(xiàn)假彈框,疊加彈框默認lanuchMode即可曹鸠,只彈一個lanuchMode="singleTop",并重寫onNewIntent()方法煌茬。
public class NotificationDialogActivity extends AppCompatActivity {
private ExtraBean extraBean;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_show_notification);
textView = findViewById(R.id.textview);
TextView tvCancel = findViewById(R.id.tv_cancel);
TextView tvConfirm = findViewById(R.id.tv_confirm);
extraBean = (ExtraBean) getIntent().getSerializableExtra("bean");
textView.setText(extraBean.getTitle());
final int type = extraBean.getType();
tvConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=null;
if (type == 1) {
intent = new Intent(NotificationDialogActivity.this, DetailActivity.class);
} else {
intent = new Intent(NotificationDialogActivity.this, ListActivity.class);
}
intent.putExtra("bean", extraBean);
startActivity(intent);
finish();
}
});
tvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
extraBean = (ExtraBean) intent.getSerializableExtra("bean");
textView.setText(extraBean.getTitle());
}
}
其他類在demo里,demo下載地址:https://github.com/274800562/umengtest.git
如果您覺得此文章對您有幫助彻桃,請多多支持坛善。