前言
在Android開發(fā)中,消息推送功能的使用非常常見翁狐。
推送消息截圖
為了降低開發(fā)成本类溢,使用第三方推送是現(xiàn)今較為流行的解決方案。
今天,我將手把手教大家如何在你的應(yīng)用里集成小米推送
該文檔基于小米推送官方Demo進(jìn)行解析闯冷,并給出簡易推送Demo
看該文檔前砂心,請先閱讀我寫的另外兩篇文章:
目錄
目錄
1. 官方Demo解析
首先,我們先對小米官方的推送Demo進(jìn)行解析蛇耀。
1.1 Demo概況
need-to-insert-img
Demo目錄
目錄說明:
DemoApplication類
繼承自Application類辩诞,其作用主要是:設(shè)置App的ID & Key、注冊推送服務(wù)
DemoMessageReceiver類
繼承自BroadcastReceiver纺涤,用于接收推送消息并對這些消息進(jìn)行處理
MainActivity
實(shí)現(xiàn)界面按鈕處理 & 設(shè)置本地推送方案
TimeIntervalDialog
設(shè)置推送的時間間段
接下來译暂,我將對每個類進(jìn)行詳細(xì)分析
1.2 詳細(xì)分析
1.2.1 DemoApplication類
繼承自Application類,其作用主要是:
設(shè)置App的ID & Key
注冊推送服務(wù)
接下來我們通過代碼來看下這兩個功能如何實(shí)現(xiàn):
DemoApplication.java
packagecom.xiaomi.mipushdemo;importandroid.app.ActivityManager;importandroid.app.ActivityManager.RunningAppProcessInfo;importandroid.app.Application;importandroid.content.Context;importandroid.os.Handler;importandroid.os.Message;importandroid.os.Process;importandroid.text.TextUtils;importandroid.util.Log;importandroid.widget.Toast;importcom.xiaomi.channel.commonutils.logger.LoggerInterface;importcom.xiaomi.mipush.sdk.Logger;importcom.xiaomi.mipush.sdk.MiPushClient;importjava.util.List;publicclassDemoApplicationextendsApplication{// 使用自己APP的ID(官網(wǎng)注冊的)privatestaticfinalString APP_ID ="1000270";// 使用自己APP的KEY(官網(wǎng)注冊的)privatestaticfinalString APP_KEY ="670100056270";// 此TAG在adb logcat中檢索自己所需要的信息撩炊, 只需在命令行終端輸入 adb logcat | grep// com.xiaomi.mipushdemopublicstaticfinalString TAG ="com.xiaomi.mipushdemo";privatestaticDemoHandler sHandler =null;privatestaticMainActivity sMainActivity =null;//為了提高推送服務(wù)的注冊率外永,官方Demo建議在Application的onCreate中初始化推送服務(wù)//你也可以根據(jù)需要,在其他地方初始化推送服務(wù)@OverridepublicvoidonCreate(){super.onCreate();//判斷用戶是否已經(jīng)打開App拧咳,詳細(xì)見下面方法定義if(shouldInit()) {//注冊推送服務(wù)//注冊成功后會向DemoMessageReceiver發(fā)送廣播// 可以從DemoMessageReceiver的onCommandResult方法中MiPushCommandMessage對象參數(shù)中獲取注冊信息MiPushClient.registerPush(this, APP_ID, APP_KEY);//參數(shù)說明//context:Android平臺上app的上下文伯顶,建議傳入當(dāng)前app的application context//appID:在開發(fā)者網(wǎng)站上注冊時生成的,MiPush推送服務(wù)頒發(fā)給app的唯一認(rèn)證標(biāo)識//appKey:在開發(fā)者網(wǎng)站上注冊時生成的,與appID相對應(yīng),用于驗(yàn)證appID是否合法}//下面是與測試相關(guān)的日志設(shè)置LoggerInterface newLogger =newLoggerInterface() {@OverridepublicvoidsetTag(String tag){// ignore}@Overridepublicvoidlog(String content, Throwable t){? ? ? ? ? ? ? ? Log.d(TAG, content, t);? ? ? ? ? ? }@Overridepublicvoidlog(String content){? ? ? ? ? ? ? ? Log.d(TAG, content);? ? ? ? ? ? }? ? ? ? };? ? ? ? Logger.setLogger(this, newLogger);if(sHandler ==null) {? ? ? ? ? ? sHandler =newDemoHandler(getApplicationContext());? ? ? ? }? ? }//通過判斷手機(jī)里的所有進(jìn)程是否有這個App的進(jìn)程//從而判斷該App是否有打開privatebooleanshouldInit(){//通過ActivityManager我們可以獲得系統(tǒng)里正在運(yùn)行的activities//包括進(jìn)程(Process)等壹瘟、應(yīng)用程序/包、服務(wù)(Service)汪厨、任務(wù)(Task)信息。ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));? ? ? ? List processInfos = am.getRunningAppProcesses();? ? ? ? String mainProcessName = getPackageName();//獲取本App的唯一標(biāo)識intmyPid = Process.myPid();//利用一個增強(qiáng)for循環(huán)取出手機(jī)里的所有進(jìn)程for(RunningAppProcessInfo info : processInfos) {//通過比較進(jìn)程的唯一標(biāo)識和包名判斷進(jìn)程里是否存在該Appif(info.pid == myPid && mainProcessName.equals(info.processName)) {returntrue;? ? ? ? ? ? }? ? ? ? }returnfalse;? ? }publicstaticDemoHandlergetHandler(){returnsHandler;? ? }publicstaticvoidsetMainActivity(MainActivity activity){? ? ? ? sMainActivity = activity;? ? }//通過設(shè)置Handler來設(shè)置提示文案publicstaticclassDemoHandlerextendsHandler{privateContext context;publicDemoHandler(Context context){this.context = context;? ? ? ? }@OverridepublicvoidhandleMessage(Message msg){? ? ? ? ? ? String s = (String) msg.obj;if(sMainActivity !=null) {? ? ? ? ? ? ? ? sMainActivity.refreshLogInfo();? ? ? ? ? ? }if(!TextUtils.isEmpty(s)) {? ? ? ? ? ? ? ? Toast.makeText(context, s, Toast.LENGTH_LONG).show();? ? ? ? ? ? }? ? ? ? }? ? }}
總結(jié):
步驟1:先判斷應(yīng)用App是否已開啟 - 通過判斷系統(tǒng)里的進(jìn)程
通過靜態(tài)方法
publicstaticvoidregisterPush(Context context,StringappID,StringappKey)
進(jìn)行推送服務(wù)注冊愉择,詳細(xì)參數(shù)如下:
need-to-insert-img
為了提高注冊率,最好在Application的onCreate中初始化推送服務(wù)
你也可以根據(jù)需要织中,在其他地方初始化推送服務(wù)
1.2.2 DemoMessageReceiver類
繼承自PushMessageReceiver(抽象類锥涕,繼承自BroadcastReceiver),其作用主要是:
接收推送消息
對推送消息進(jìn)行處理
DemoMessageReceiver.java
package com.xiaomi.mipushdemo;import android.annotation.SuppressLint;import android.content.Context;import android.os.Message;import android.text.TextUtils;import android.util.Log;import com.xiaomi.mipush.sdk.ErrorCode;import com.xiaomi.mipush.sdk.MiPushClient;import com.xiaomi.mipush.sdk.MiPushCommandMessage;import com.xiaomi.mipush.sdk.MiPushMessage;import com.xiaomi.mipush.sdk.PushMessageReceiver;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;/** * 1狭吼、PushMessageReceiver 是個抽象類层坠,該類繼承了 BroadcastReceiver。 * 2刁笙、需要將自定義的 DemoMessageReceiver 注冊在 AndroidManifest.xmlpublic class DemoMessageReceiver extends PushMessageReceiver {? ? private String mRegId;? ? private String mTopic;? ? private String mAlias;? ? private String mAccount;? ? private String mStartTime;? ? private String mEndTime;? ? //透傳消息到達(dá)客戶端時調(diào)用? ? //作用:可通過參數(shù)message從而獲得透傳消息破花,具體請看官方SDK文檔? ? @Override? ? public void onReceivePassThroughMessage(Context context, MiPushMessage message) {? ? ? ? Log.v(DemoApplication.TAG,"onReceivePassThroughMessage is called. "+ message.toString());? ? ? ? Stringlog= context.getString(R.string.recv_passthrough_message, message.getContent());? ? ? ? MainActivity.logList.add(0, getSimpleDate() +" "+log);if(!TextUtils.isEmpty(message.getTopic())) {? ? ? ? ? ? mTopic = message.getTopic();? ? ? ? }elseif(!TextUtils.isEmpty(message.getAlias())) {? ? ? ? ? ? mAlias = message.getAlias();? ? ? ? }? ? ? ? Message msg = Message.obtain();? ? ? ? msg.obj =log;? ? ? ? DemoApplication.getHandler().sendMessage(msg);? ? }//通知消息到達(dá)客戶端時調(diào)用? ? //注:應(yīng)用在前臺時不彈出通知的通知消息到達(dá)客戶端時也會回調(diào)函數(shù)? ? //作用:通過參數(shù)message從而獲得通知消息,具體請看官方SDK文檔? ? ? @Override? ? public void onNotificationMessageArrived(Context context, MiPushMessage message) {? ? ? ? Log.v(DemoApplication.TAG,"onNotificationMessageArrived is called. "+ message.toString());? ? ? ? Stringlog= context.getString(R.string.arrive_notification_message, message.getContent());? ? ? ? MainActivity.logList.add(0, getSimpleDate() +" "+log);if(!TextUtils.isEmpty(message.getTopic())) {? ? ? ? ? ? mTopic = message.getTopic();? ? ? ? }elseif(!TextUtils.isEmpty(message.getAlias())) {? ? ? ? ? ? mAlias = message.getAlias();? ? ? ? }? ? ? ? Message msg = Message.obtain();? ? ? ? msg.obj =log;? ? ? ? DemoApplication.getHandler().sendMessage(msg);? ? }? ? ? ? //用戶手動點(diǎn)擊通知欄消息時調(diào)用? ? //注:應(yīng)用在前臺時不彈出通知的通知消息到達(dá)客戶端時也會回調(diào)函數(shù)? ? //作用:1. 通過參數(shù)message從而獲得通知消息疲吸,具體請看官方SDK文檔? ? //2. 設(shè)置用戶點(diǎn)擊消息后打開應(yīng)用 or 網(wǎng)頁 or 其他頁面? ? @Override? ? public void onNotificationMessageClicked(Context context, MiPushMessage message) {? ? ? ? Log.v(DemoApplication.TAG,"onNotificationMessageClicked is called. "+ message.toString());? ? ? ? Stringlog= context.getString(R.string.click_notification_message, message.getContent());? ? ? ? MainActivity.logList.add(0, getSimpleDate() +" "+log);if(!TextUtils.isEmpty(message.getTopic())) {? ? ? ? ? ? mTopic = message.getTopic();? ? ? ? }elseif(!TextUtils.isEmpty(message.getAlias())) {? ? ? ? ? ? mAlias = message.getAlias();? ? ? ? }? ? ? ? Message msg = Message.obtain();if(message.isNotified()) {? ? ? ? ? ? msg.obj =log;? ? ? ? }? ? ? ? DemoApplication.getHandler().sendMessage(msg);? ? }? ? ? ? //用來接收客戶端向服務(wù)器發(fā)送命令后的響應(yīng)結(jié)果座每。? ? @Override? ? public void onCommandResult(Context context, MiPushCommandMessage message) {? ? ? ? Log.v(DemoApplication.TAG,"onCommandResult is called. "+ message.toString());? ? ? ? Stringcommand= message.getCommand();? ? ? ? List arguments = message.getCommandArguments();? ? ? ? String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments.get(0) : null);? ? ? ? String cmdArg2 = ((arguments != null && arguments.size() > 1) ? arguments.get(1) : null);? ? ? ? Stringlog;if(MiPushClient.COMMAND_REGISTER.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mRegId = cmdArg1;log= context.getString(R.string.register_success);? ? ? ? ? ? }else{log= context.getString(R.string.register_fail);? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_SET_ALIAS.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mAlias = cmdArg1;log= context.getString(R.string.set_alias_success, mAlias);? ? ? ? ? ? }else{log= context.getString(R.string.set_alias_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_UNSET_ALIAS.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mAlias = cmdArg1;log= context.getString(R.string.unset_alias_success, mAlias);? ? ? ? ? ? }else{log= context.getString(R.string.unset_alias_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_SET_ACCOUNT.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mAccount = cmdArg1;log= context.getString(R.string.set_account_success, mAccount);? ? ? ? ? ? }else{log= context.getString(R.string.set_account_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_UNSET_ACCOUNT.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mAccount = cmdArg1;log= context.getString(R.string.unset_account_success, mAccount);? ? ? ? ? ? }else{log= context.getString(R.string.unset_account_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_SUBSCRIBE_TOPIC.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mTopic = cmdArg1;log= context.getString(R.string.subscribe_topic_success, mTopic);? ? ? ? ? ? }else{log= context.getString(R.string.subscribe_topic_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_UNSUBSCRIBE_TOPIC.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mTopic = cmdArg1;log= context.getString(R.string.unsubscribe_topic_success, mTopic);? ? ? ? ? ? }else{log= context.getString(R.string.unsubscribe_topic_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }elseif(MiPushClient.COMMAND_SET_ACCEPT_TIME.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mStartTime = cmdArg1;? ? ? ? ? ? ? ? mEndTime = cmdArg2;log= context.getString(R.string.set_accept_time_success, mStartTime, mEndTime);? ? ? ? ? ? }else{log= context.getString(R.string.set_accept_time_fail, message.getReason());? ? ? ? ? ? }? ? ? ? }else{log= message.getReason();? ? ? ? }? ? ? ? MainActivity.logList.add(0, getSimpleDate() +"? ? "+log);? ? ? ? Message msg = Message.obtain();? ? ? ? msg.obj =log;? ? ? ? DemoApplication.getHandler().sendMessage(msg);? ? }? ? //用于接收客戶端向服務(wù)器發(fā)送注冊命令后的響應(yīng)結(jié)果。? ? @Override? ? public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) {? ? ? ? Log.v(DemoApplication.TAG,"onReceiveRegisterResult is called. "+ message.toString());? ? ? ? Stringcommand= message.getCommand();? ? ? ? List arguments = message.getCommandArguments();? ? ? ? String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments.get(0) : null);? ? ? ? Stringlog;if(MiPushClient.COMMAND_REGISTER.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {? ? ? ? ? ? ? ? mRegId = cmdArg1;? ? ? ? ? ? ? ? //打印日志:注冊成功log= context.getString(R.string.register_success);? ? ? ? ? ? }else{? ? ? ? ? ? ? ? ? ? ? //打印日志:注冊失敗log= context.getString(R.string.register_fail);? ? ? ? ? ? }? ? ? ? }else{log= message.getReason();? ? ? ? }? ? ? ? Message msg = Message.obtain();? ? ? ? msg.obj =log;? ? ? ? DemoApplication.getHandler().sendMessage(msg);? ? }? ? @SuppressLint("SimpleDateFormat")? ? private static StringgetSimpleDate() {returnnew SimpleDateFormat("MM-dd hh:mm:ss").format(new Date());? ? }}
總結(jié)
根據(jù)需要復(fù)寫PushMessageReceiver里對消息的相關(guān)處理方法摘悴,以下是相關(guān)方法的詳情:
need-to-insert-img
相關(guān)方法詳情
關(guān)于onCommandResult(Context context峭梳,MiPushCommandMessage message)
a. 作用:當(dāng)客戶端向服務(wù)器發(fā)送注冊push、設(shè)置alias蹂喻、取消注冊alias葱椭、訂閱topic捂寿、取消訂閱topic等等命令后,從服務(wù)器返回結(jié)果孵运。
b. 參數(shù)說明:
need-to-insert-img
參數(shù)說明
1.2.3 MainActivity
用于給用戶設(shè)置標(biāo)識秦陋,如別名、標(biāo)簽治笨、賬號等等
MainActivity.java
publicclassMainActivityextendsActivity{publicstaticList logList =newCopyOnWriteArrayList();privateTextView mLogView =null;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);? ? ? ? setContentView(R.layout.activity_main);? ? ? ? DemoApplication.setMainActivity(this);? ? ? ? mLogView = (TextView) findViewById(R.id.log);// 設(shè)置別名findViewById(R.id.set_alias).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){finalEditText editText =newEditText(MainActivity.this);newAlertDialog.Builder(MainActivity.this)? ? ? ? ? ? ? ? ? ? ? ? .setTitle(R.string.set_alias)? ? ? ? ? ? ? ? ? ? ? ? .setView(editText)? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton(R.string.ok,newDialogInterface.OnClickListener() {@OverridepublicvoidonClick(DialogInterface dialog,intwhich){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String alias = editText.getText().toString();//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MiPushClient.setAlias(MainActivity.this, alias, null);}? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .setNegativeButton(R.string.cancel,null)? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 撤銷別名findViewById(R.id.unset_alias).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){finalEditText editText =newEditText(MainActivity.this);newAlertDialog.Builder(MainActivity.this)? ? ? ? ? ? ? ? ? ? ? ? .setTitle(R.string.unset_alias)? ? ? ? ? ? ? ? ? ? ? ? .setView(editText)? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton(R.string.ok,newDialogInterface.OnClickListener() {@OverridepublicvoidonClick(DialogInterface dialog,intwhich){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String alias = editText.getText().toString();//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MiPushClient.unsetAlias(MainActivity.this, alias, null);}? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .setNegativeButton(R.string.cancel,null)? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 設(shè)置帳號findViewById(R.id.set_account).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){finalEditText editText =newEditText(MainActivity.this);newAlertDialog.Builder(MainActivity.this)? ? ? ? ? ? ? ? ? ? ? ? .setTitle(R.string.set_account)? ? ? ? ? ? ? ? ? ? ? ? .setView(editText)? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton(R.string.ok,newDialogInterface.OnClickListener() {@OverridepublicvoidonClick(DialogInterface dialog,intwhich){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String account = editText.getText().toString();//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MiPushClient.setUserAccount(MainActivity.this, account, null);}? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .setNegativeButton(R.string.cancel,null)? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 撤銷帳號findViewById(R.id.unset_account).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){finalEditText editText =newEditText(MainActivity.this);newAlertDialog.Builder(MainActivity.this)? ? ? ? ? ? ? ? ? ? ? ? .setTitle(R.string.unset_account)? ? ? ? ? ? ? ? ? ? ? ? .setView(editText)? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton(R.string.ok,newDialogInterface.OnClickListener() {@OverridepublicvoidonClick(DialogInterface dialog,intwhich){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String account = editText.getText().toString();//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MiPushClient.unsetUserAccount(MainActivity.this, account, null);}? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .setNegativeButton(R.string.cancel,null)? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 設(shè)置標(biāo)簽findViewById(R.id.subscribe_topic).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){finalEditText editText =newEditText(MainActivity.this);newAlertDialog.Builder(MainActivity.this)? ? ? ? ? ? ? ? ? ? ? ? .setTitle(R.string.subscribe_topic)? ? ? ? ? ? ? ? ? ? ? ? .setView(editText)? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton(R.string.ok,newDialogInterface.OnClickListener() {@OverridepublicvoidonClick(DialogInterface dialog,intwhich){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String topic = editText.getText().toString();//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MiPushClient.subscribe(MainActivity.this, topic, null);}? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .setNegativeButton(R.string.cancel,null)? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 撤銷標(biāo)簽findViewById(R.id.unsubscribe_topic).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){finalEditText editText =newEditText(MainActivity.this);newAlertDialog.Builder(MainActivity.this)? ? ? ? ? ? ? ? ? ? ? ? .setTitle(R.string.unsubscribe_topic)? ? ? ? ? ? ? ? ? ? ? ? .setView(editText)? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton(R.string.ok,newDialogInterface.OnClickListener() {@OverridepublicvoidonClick(DialogInterface dialog,intwhich){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String topic = editText.getText().toString();//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MiPushClient.unsubscribe(MainActivity.this, topic, null);}? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .setNegativeButton(R.string.cancel,null)? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 設(shè)置接收消息時間findViewById(R.id.set_accept_time).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){newTimeIntervalDialog(MainActivity.this,newTimeIntervalInterface() {@Overridepublicvoidapply(intstartHour,intstartMin,intendHour,intendMin){//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? MiPushClient.setAcceptTime(MainActivity.this, startHour, startMin, endHour, endMin,null);? ? ? ? ? ? ? ? ? ? }@Overridepublicvoidcancel(){//ignore}? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? .show();? ? ? ? ? ? }? ? ? ? });// 暫停推送findViewById(R.id.pause_push).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){? ? ? ? ? ? ? ? MiPushClient.pausePush(MainActivity.this,null);? ? ? ? ? ? }? ? ? ? });? ? ? ? findViewById(R.id.resume_push).setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v){//調(diào)用靜態(tài)方法進(jìn)行設(shè)置? MiPushClient.resumePush(MainActivity.this,null);? ? ? ? ? ? }? ? ? ? });? ? }@OverrideprotectedvoidonResume(){super.onResume();? ? ? ? refreshLogInfo();? ? }@OverrideprotectedvoidonDestroy(){super.onDestroy();? ? ? ? DemoApplication.setMainActivity(null);? ? }publicvoidrefreshLogInfo(){? ? ? ? String AllLog ="";for(String log : logList) {? ? ? ? ? ? AllLog = AllLog + log +"\n\n";? ? ? ? }? ? ? ? mLogView.setText(AllLog);? ? }}
總結(jié)
根據(jù)需求對不同用戶設(shè)置不同的推送標(biāo)識驳概,如別名、標(biāo)簽等等大磺。
a. 別名(Alias)
開發(fā)者可以為指定用戶設(shè)置別名抡句,然后給這個別名推送消息,
效果等同于給RegId推送消息杠愧,Alias是除Regid(自動生成的)和UserAccount之外的第三個用戶標(biāo)識
開發(fā)者可以取消指定用戶的某個別名待榔,服務(wù)器就不會給這個別名推送消息了。
//設(shè)置別名MiPushClient.setAlias(Context context,Stringalias,Stringcategory)流济;//撤銷別名MiPushClient.unsetAlias(Context context,Stringalias,Stringcategory)锐锣;//參數(shù)說明//context:Android平臺上app的上下文,建議傳入當(dāng)前app的application context//alias:為指定用戶設(shè)置別名 / 為指定用戶取消別名//category:擴(kuò)展參數(shù)绳瘟,暫時沒有用途雕憔,直接填null//獲取該客戶端所有的別名publicstaticList getAllAlias(final Context context)
b. 用戶賬號(UserAccoun)
開發(fā)者可以為指定用戶設(shè)置userAccount
開發(fā)者可以取消指定用戶的某個userAccount,服務(wù)器就不會給這個userAccount推送消息了
//設(shè)置MiPushClient.setUserAccount(finalContext context,finalString userAccount, Stringcategory)//撤銷MiPushClient.unsetUserAccount(finalContext context,finalString userAccount, Stringcategory)//參數(shù)說明//context:Android平臺上app的上下文糖声,建議傳入當(dāng)前app的application context//userAccount:為指定用戶設(shè)置userAccount / 為指定用戶取消userAccount//category:擴(kuò)展參數(shù)斤彼,暫時沒有用途,直接填null//獲取該客戶端所有設(shè)置的賬號publicstaticList getAllUserAccount(finalContext context)
c. 標(biāo)簽(Topic)
開發(fā)者可以結(jié)合自己的業(yè)務(wù)特征蘸泻,給用戶打上不同的標(biāo)簽琉苇。
消息推送時,開發(fā)者可以結(jié)合每條消息的內(nèi)容和目標(biāo)用戶悦施,為每條消息選擇對應(yīng)的標(biāo)簽并扇,為開發(fā)者可以根據(jù)訂閱的主題實(shí)現(xiàn)分組群發(fā),從而進(jìn)行消息的精準(zhǔn)推送
//設(shè)置標(biāo)簽MiPushClient.subscribe(Context context,Stringtopic,Stringcategory)抡诞;//撤銷標(biāo)簽MiPushClient.unsubscribe(Context context,Stringtopic,Stringcategory)穷蛹;//參數(shù)說明//context:Android平臺上app的上下文,建議傳入當(dāng)前app的application context//topic:為指定用戶設(shè)置設(shè)置訂閱的主題 / 為指定用戶取消訂閱的主題//category:擴(kuò)展參數(shù)昼汗,暫時沒有用途肴熏,直接填null//獲取該客戶端所有的標(biāo)簽publicstaticList getAllTopic(final Context context);
TimeIntervalDialog
作用:用于設(shè)置推送的時間-開始時間+暫停時間
packagecom.xiaomi.mipushdemo;importandroid.app.Dialog;importandroid.content.Context;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;importandroid.widget.TimePicker;importandroid.widget.TimePicker.OnTimeChangedListener;//繼承OnTimeChangedListener接口publicclassTimeIntervalDialogextendsDialogimplementsOnTimeChangedListener{privateTimeIntervalInterface mTimeIntervalInterface;privateContext mContext;privateTimePicker mStartTimePicker, mEndTimePicker;privateintmStartHour, mStartMinute, mEndHour, mEndMinute;privateButton.OnClickListener clickListener =newButton.OnClickListener() {@OverridepublicvoidonClick(View v){switch(v.getId()) {caseR.id.apply:? ? ? ? ? ? ? ? ? ? dismiss();//設(shè)置時間參數(shù)mTimeIntervalInterface.apply(mStartHour, mStartMinute, mEndHour, mEndMinute);break;caseR.id.cancel:? ? ? ? ? ? ? ? ? ? dismiss();? ? ? ? ? ? ? ? ? ? mTimeIntervalInterface.cancel();break;default:break;? ? ? ? ? ? }? ? ? ? }? ? };publicTimeIntervalDialog(Context context, TimeIntervalInterface timeIntervalInterface,intstartHour,intstartMinute,intendHour,intendMinute){super(context);? ? ? ? mContext = context;this.mTimeIntervalInterface = timeIntervalInterface;this.mStartHour = startHour;this.mStartMinute = startMinute;this.mEndHour = endHour;this.mEndMinute = endMinute;? ? }publicTimeIntervalDialog(Context context, TimeIntervalInterface timeIntervalInterface){this(context, timeIntervalInterface,0,0,23,59);? ? }@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);? ? ? ? setContentView(R.layout.set_time_dialog);? ? ? ? setCancelable(true);? ? ? ? setTitle(mContext.getString(R.string.set_accept_time));? ? ? ? mStartTimePicker = (TimePicker) findViewById(R.id.startTimePicker);? ? ? ? mStartTimePicker.setIs24HourView(true);? ? ? ? mStartTimePicker.setCurrentHour(mStartHour);? ? ? ? mStartTimePicker.setCurrentMinute(mStartMinute);? ? ? ? mStartTimePicker.setOnTimeChangedListener(this);? ? ? ? mEndTimePicker = (TimePicker) findViewById(R.id.endTimePicker);? ? ? ? mEndTimePicker.setIs24HourView(true);? ? ? ? mEndTimePicker.setCurrentHour(mEndHour);? ? ? ? mEndTimePicker.setCurrentMinute(mEndMinute);? ? ? ? mEndTimePicker.setOnTimeChangedListener(this);? ? ? ? Button applyBtn = (Button) findViewById(R.id.apply);? ? ? ? applyBtn.setOnClickListener(clickListener);? ? ? ? Button cancelBtn = (Button) findViewById(R.id.cancel);? ? ? ? cancelBtn.setOnClickListener(clickListener);? ? }@OverridepublicvoidonTimeChanged(TimePicker view,inthourOfDay,intminute){if(view == mStartTimePicker) {? ? ? ? ? ? mStartHour = hourOfDay;? ? ? ? ? ? mStartMinute = minute;? ? ? ? }elseif(view == mEndTimePicker) {? ? ? ? ? ? mEndHour = hourOfDay;? ? ? ? ? ? mEndMinute = minute;? ? ? ? }? ? }interfaceTimeIntervalInterface{voidapply(intstartHour,intstartMin,intendHour,intendMin);voidcancel();? ? }}
總結(jié)
使用一個繼承了Dialog類的TimeIntervalDialog類進(jìn)行推送時間的配置
可進(jìn)行的配置:設(shè)置推送時間(開始 & 結(jié)束)乔遮、暫停推送時間扮超、恢復(fù)推送時間
//設(shè)置推送時間(開始 & 結(jié)束)MiPushClient.setAcceptTime(Context context,intstartHour,intstartMin,intendHour,intendMin, String category)//設(shè)置暫停推送時間、恢復(fù)推送時間pausePush(Context context, String category)`和`resumePush(Context context, String category)//參數(shù)說明//context:Android平臺上app的上下文,建議傳入當(dāng)前app的application context//startHour:接收時段開始時間的小時//startMin? :接收時段開始時間的分鐘//endHour:接收時段結(jié)束時間的小時//endMin:接收時段結(jié)束時間的分鐘//category:擴(kuò)展參數(shù)出刷,暫時沒有用途璧疗,直接填null
AndroidManifest文件的配置
//小米推送支持最低的Android版本是2.2//設(shè)置一系列權(quán)限//這里com.xiaomi.mipushdemo改成自身app的包名//這里com.xiaomi.mipushdemo改成自身app的包名//注冊廣播BroadcastReceiver & Service//都是靜態(tài)注冊,因?yàn)橐L期處在后臺運(yùn)行//注:共是3個廣播接收器和4個服務(wù)馁龟,其中包括繼承了PushMessageReceiver的DemoMessageReceiver? ? ? ? ? ? ? ? ? ? ? ? //4個后臺服務(wù)//此service必須在3.0.1版本以后(包括3.0.1版本)加入//此service必須在2.2.5版本以后(包括2.2.5版本)加入//3個廣播//繼承了PushMessageReceiver的DemoMessageReceiver的廣播注冊
2. 集成小米推送步驟匯總
步驟1:在小米推送平臺進(jìn)行相關(guān)注冊開發(fā)者賬號崩侠,并進(jìn)行應(yīng)用的注冊:應(yīng)用包名,AppID和AppKey
步驟2:將小米推送的SDK包加入庫
步驟3:在應(yīng)用內(nèi)初始化小米推送服務(wù)
步驟4:繼承PushMessageReceiver坷檩,并復(fù)寫相關(guān)推送消息的方法
步驟5:在AndroidManifest文件里面配置好權(quán)限却音、注冊Service和BroadcastReceiver
在Android6.0里面的權(quán)限需要動態(tài)獲取
步驟6:根據(jù)需要設(shè)置一系列的推送設(shè)置,如用戶別名矢炼、標(biāo)簽等等
接下來系瓢,我們來按照上面的步驟,一步步來實(shí)現(xiàn)一個簡易的小米推送Demo
3. 實(shí)例解析
步驟1:在小米推送平臺進(jìn)行相關(guān)注冊開發(fā)者賬號句灌,并進(jìn)行應(yīng)用的注冊:應(yīng)用包名夷陋,AppID和AppKey
注意,填入的包名要跟你的應(yīng)用App的包名是一致的
創(chuàng)建應(yīng)用
AppID和Key
步驟2:將小米推送的SDK包加入到你應(yīng)用的庫里
放入到app/libs文件夾下胰锌,然后右鍵點(diǎn)擊add as Library骗绕,最后點(diǎn)擊Model就導(dǎo)入成功了
小米推送SDK
導(dǎo)入包
步驟3:在應(yīng)用內(nèi)初始化小米推送服務(wù)
為了提高推送服務(wù)的注冊率,我選擇在Application的onCreate中初始化推送服務(wù)
BaseActivity.java
packagescut.carson_ho.demo_mipush;importandroid.app.ActivityManager;importandroid.app.Application;importandroid.content.Context;importandroid.os.Process;importcom.xiaomi.mipush.sdk.MiPushClient;importjava.util.List;/**
* Created by Carson_Ho on 16/10/26.
*///主要要繼承ApplicationpublicclassBaseActivityextendsApplication{// 使用自己APP的ID(官網(wǎng)注冊的)privatestaticfinalString APP_ID ="2882303761517520369";// 使用自己APP的Key(官網(wǎng)注冊的)privatestaticfinalString APP_KEY ="5401752085369";//為了提高推送服務(wù)的注冊率资昧,我建議在Application的onCreate中初始化推送服務(wù)//你也可以根據(jù)需要酬土,在其他地方初始化推送服務(wù)@OverridepublicvoidonCreate(){super.onCreate();if(shouldInit()) {//注冊推送服務(wù)//注冊成功后會向DemoMessageReceiver發(fā)送廣播// 可以從DemoMessageReceiver的onCommandResult方法中MiPushCommandMessage對象參數(shù)中獲取注冊信息MiPushClient.registerPush(this, APP_ID, APP_KEY);? ? ? ? }? ? }//通過判斷手機(jī)里的所有進(jìn)程是否有這個App的進(jìn)程//從而判斷該App是否有打開privatebooleanshouldInit(){//通過ActivityManager我們可以獲得系統(tǒng)里正在運(yùn)行的activities//包括進(jìn)程(Process)等、應(yīng)用程序/包格带、服務(wù)(Service)撤缴、任務(wù)(Task)信息。ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));? ? ? ? List processInfos = am.getRunningAppProcesses();? ? ? ? String mainProcessName = getPackageName();//獲取本App的唯一標(biāo)識intmyPid = Process.myPid();//利用一個增強(qiáng)for循環(huán)取出手機(jī)里的所有進(jìn)程for(ActivityManager.RunningAppProcessInfo info : processInfos) {//通過比較進(jìn)程的唯一標(biāo)識和包名判斷進(jìn)程里是否存在該Appif(info.pid == myPid && mainProcessName.equals(info.processName)) {returntrue;? ? ? ? ? ? }? ? ? ? }returnfalse;? ? }}
注意要在Android.manifest.xml里的application里加入
android:name=".BaseActivity"
這樣在應(yīng)用初始化時是第一個加載BaseActivity.java類文件的
如下圖:
示意圖
步驟4:設(shè)置子類繼承PushMessageReceiver叽唱,并復(fù)寫相關(guān)推送消息的方法
Mipush_Broadcast.java
packagescut.carson_ho.demo_mipush;importandroid.content.Context;importcom.xiaomi.mipush.sdk.ErrorCode;importcom.xiaomi.mipush.sdk.MiPushClient;importcom.xiaomi.mipush.sdk.MiPushCommandMessage;importcom.xiaomi.mipush.sdk.MiPushMessage;importcom.xiaomi.mipush.sdk.PushMessageReceiver;/**
* Created by Carson_Ho on 16/10/26.
*/publicclassMipush_BroadcastextendsPushMessageReceiver{//透傳消息到達(dá)客戶端時調(diào)用//作用:可通過參數(shù)message從而獲得透傳消息腹泌,具體請看官方SDK文檔@OverridepublicvoidonReceivePassThroughMessage(Context context, MiPushMessage message){//打印消息方便測試System.out.println("透傳消息到達(dá)了");? ? ? ? System.out.println("透傳消息是"+message.toString());? ? }//通知消息到達(dá)客戶端時調(diào)用//注:應(yīng)用在前臺時不彈出通知的通知消息到達(dá)客戶端時也會回調(diào)函數(shù)//作用:通過參數(shù)message從而獲得通知消息,具體請看官方SDK文檔@OverridepublicvoidonNotificationMessageArrived(Context context, MiPushMessage message){//打印消息方便測試System.out.println("通知消息到達(dá)了");? ? ? ? System.out.println("通知消息是"+message.toString());? ? }//用戶手動點(diǎn)擊通知欄消息時調(diào)用//注:應(yīng)用在前臺時不彈出通知的通知消息到達(dá)客戶端時也會回調(diào)函數(shù)//作用:1. 通過參數(shù)message從而獲得通知消息尔觉,具體請看官方SDK文檔//2. 設(shè)置用戶點(diǎn)擊消息后打開應(yīng)用 or 網(wǎng)頁 or 其他頁面@OverridepublicvoidonNotificationMessageClicked(Context context, MiPushMessage message){//打印消息方便測試System.out.println("用戶點(diǎn)擊了通知消息");? ? ? ? System.out.println("通知消息是"+ message.toString());? ? ? ? System.out.println("點(diǎn)擊后,會進(jìn)入應(yīng)用");? ? }//用來接收客戶端向服務(wù)器發(fā)送命令后的響應(yīng)結(jié)果。@OverridepublicvoidonCommandResult(Context context, MiPushCommandMessage message){? ? ? ? String command = message.getCommand();? ? ? ? System.out.println(command );if(MiPushClient.COMMAND_REGISTER.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {//打印信息便于測試注冊成功與否System.out.println("注冊成功");? ? ? ? ? ? }else{? ? ? ? ? ? ? ? System.out.println("注冊失敗");? ? ? ? ? ? }? ? ? ? }? ? }//用于接收客戶端向服務(wù)器發(fā)送注冊命令后的響應(yīng)結(jié)果芥吟。@OverridepublicvoidonReceiveRegisterResult(Context context, MiPushCommandMessage message){? ? ? ? String command = message.getCommand();? ? ? ? System.out.println(command );if(MiPushClient.COMMAND_REGISTER.equals(command)) {if(message.getResultCode() == ErrorCode.SUCCESS) {//打印日志:注冊成功System.out.println("注冊成功");? ? ? ? ? ? }else{//打印日志:注冊失敗System.out.println("注冊失敗");? ? ? ? ? ? }? ? ? ? }else{? ? ? ? ? ? System.out.println("其他情況"+message.getReason());? ? ? ? }? ? }}
具體設(shè)置請看官方SDK文檔侦铜,這里只給出最簡單Demo,不作過多描述
步驟5:在AndroidManifest文件里面配置好權(quán)限钟鸵、注冊Service和BroadcastReceiver
AndroidManifest.xml
//相關(guān)權(quán)限//注意這里.permission.MIPUSH_RECEIVE是自身app的包名//注意這里.permission.MIPUSH_RECEIVE是自身app的包名//注意要初始化BaseActivity.java類//注冊廣播BroadcastReceiver和Service? ? //都是靜態(tài)注冊钉稍,因?yàn)橐L期處在后臺運(yùn)行? ? //注:共是3個廣播接收器和4個服務(wù),其中包括繼承了PushMessageReceiver的DemoMessageReceiver? ? //4個后臺服務(wù)//此service必須在3.0.1版本以后(包括3.0.1版本)加入//此service必須在2.2.5版本以后(包括2.2.5版本)加入//3個廣播//繼承了PushMessageReceiver的DemoMessageReceiver的廣播注冊
步驟6:根據(jù)需要設(shè)置一系列的推送設(shè)置棺耍,如用戶別名贡未、標(biāo)簽等等
此處是簡單Demo,所以不作過多的設(shè)置
更多設(shè)置請回看上方官方Demo解析
運(yùn)行結(jié)果
測試成功結(jié)果
好了,客戶端的代碼寫好后俊卤,可以去小米官網(wǎng)測試一下消息推送了
步驟1:在小米官網(wǎng)的消息推送里選擇你創(chuàng)建的應(yīng)用嫩挤,然后點(diǎn)擊“推送工具”
點(diǎn)擊推送工具
步驟2:設(shè)置推送消息的相關(guān)信息
可進(jìn)行的配置非常全面,基本上能滿足推送的需求
設(shè)置推送消息
設(shè)置推送消息
推送的結(jié)果
消息到達(dá)客戶端
測試結(jié)果
測試結(jié)果:收到的信息
點(diǎn)擊通知欄消息后
4. Demo下載地址
Carson的Github:Demo_MiPush
5. 關(guān)于對小米推送的思考(問題)
上述說的小米推送看似簡單:初始化推送服務(wù) + 相關(guān)推送設(shè)置消恍。但是岂昭,好的代碼不僅能在正常情況下工作,還應(yīng)該充分考慮失敗情況狠怨。那么约啊,有什么樣的失敗情況需要我們考慮呢?
背景:在這個初始化推送服務(wù)的過程中佣赖,是需要聯(lián)系小米推送的服務(wù)器來申請reg id(即推送token)恰矩。
沖突:初始化過程可能失敗:網(wǎng)絡(luò)問題(沒網(wǎng)or網(wǎng)絡(luò)信號弱)憎蛤、服務(wù)器問題導(dǎo)致初始化失敗外傅。那么,當(dāng)失敗以后蹂午,該什么時候再次進(jìn)行初始化呢栏豺?
小米推送的Demo里并沒有相關(guān)措施解決這個問題
解決方案:在初始化失敗的情況下提供重試機(jī)制,直到初始化成功(可以通過檢測是否已經(jīng)拿到推送token來確定)豆胸,問題解決的邏輯如下:
解決邏輯
具體代碼在這里就不作過多描述奥洼,如果你希望獲得含注冊重試機(jī)制的小米推送源代碼,請?jiān)谠u論留下你的郵箱晚胡,我將親自發(fā)送到你的郵箱
知識點(diǎn)涵蓋:網(wǎng)絡(luò)數(shù)據(jù)的檢測 & 廣播接收器
具體請看我寫的另外兩篇文章:
Android:BroadcastReceiver廣播接收器最全面解析
Android:檢測網(wǎng)絡(luò)狀態(tài)&監(jiān)聽網(wǎng)絡(luò)變化
總結(jié)
全面考慮到所有異常問題并恰當(dāng)?shù)剡M(jìn)行處理才能真正體現(xiàn)程序猿的功力灵奖,希望大家做擼代碼的時候不要只做代碼的搬運(yùn)工,純粹寫代碼并不會讓你成長估盘,關(guān)鍵在于思考瓷患。
6. 總結(jié)
相信大家已經(jīng)非常了解如何在你的Android應(yīng)用中集成小米推送
接下來,我會繼續(xù)介紹具體如何在Android中關(guān)于推送的消息遣妥,請看
接下來擅编,我會繼續(xù)介紹具體如何在Android應(yīng)用中集成相應(yīng)的第三方推送功能(華為推送、極光推送箫踩、個推等等)爱态,有興趣可以繼續(xù)關(guān)注Carson_Ho的安卓開發(fā)筆記
請點(diǎn)贊!因?yàn)槟愕墓膭钍俏覍懽鞯淖畲髣恿Γ?/p>
相關(guān)文章閱讀
Android開發(fā):最全面境钟、最易懂的Android屏幕適配解決方案
Android開發(fā):Handler異步通信機(jī)制全面解析(包含Looper锦担、Message Queue)
Android開發(fā):頂部Tab導(dǎo)航欄實(shí)現(xiàn)(TabLayout+ViewPager+Fragment)
Android開發(fā):底部Tab菜單欄實(shí)現(xiàn)(FragmentTabHost+ViewPager)
Android開發(fā):XML簡介及DOM、SAX慨削、PULL解析對比
作者:Carson_Ho
鏈接:http://www.reibang.com/p/b1134bebc2d4
來源:簡書
著作權(quán)歸作者所有洞渔。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)套媚,非商業(yè)轉(zhuǎn)載請注明出處。