美文网首页android程序员其它
Android消息推送:手把手教你集成小米推送

Android消息推送:手把手教你集成小米推送

作者: Carson带你学安卓 | 来源:发表于2016-12-08 22:43 被阅读12217次

    前言

    • 在Android开发中,消息推送功能的使用非常常见。
    推送消息截图
    • 为了降低开发成本,使用第三方推送是现今较为流行的解决方案。
    • 今天,我将手把手教大家如何在你的应用里集成小米推送
    1. 该文档基于小米推送官方Demo进行解析,并给出简易推送Demo
    2. 看该文档前,请先阅读我写的另外两篇文章:
      史上最全解析Android消息推送解决方案
      Android推送:第三方消息推送平台详细解析

    目录

    目录

    1. 官方Demo解析

    首先,我们先对小米官方的推送Demo进行解析。

    请先到官网下载官方DemoSDK说明文档

    1.1 Demo概况

    Demo目录

    目录说明:

    • DemoApplication类
      继承自Application类,其作用主要是:设置App的ID & Key、注册推送服务

    • DemoMessageReceiver类
      继承自BroadcastReceiver,用于接收推送消息并对这些消息进行处理

    • MainActivity
      实现界面按钮处理 & 设置本地推送方案

    • TimeIntervalDialog
      设置推送的时间间段

    接下来,我将对每个类进行详细分析

    1.2 详细分析

    1.2.1 DemoApplication类

    继承自Application类,其作用主要是:

    • 设置App的ID & Key
    • 注册推送服务

    接下来我们通过代码来看下这两个功能如何实现:

    DemoApplication.java

    package com.xiaomi.mipushdemo;
    
    import android.app.ActivityManager;
    import android.app.ActivityManager.RunningAppProcessInfo;
    import android.app.Application;
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.os.Process;
    import android.text.TextUtils;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.xiaomi.channel.commonutils.logger.LoggerInterface;
    import com.xiaomi.mipush.sdk.Logger;
    import com.xiaomi.mipush.sdk.MiPushClient;
    
    import java.util.List;
    
    
    public class DemoApplication extends Application {
    
        // 使用自己APP的ID(官网注册的)
        private static final String APP_ID = "1000270";
        // 使用自己APP的KEY(官网注册的)
        private static final String APP_KEY = "670100056270";
    
        // 此TAG在adb logcat中检索自己所需要的信息, 只需在命令行终端输入 adb logcat | grep
        // com.xiaomi.mipushdemo
        public static final String TAG = "com.xiaomi.mipushdemo";
    
        private static DemoHandler sHandler = null;
        private static MainActivity sMainActivity = null;
    
        //为了提高推送服务的注册率,官方Demo建议在Application的onCreate中初始化推送服务
        //你也可以根据需要,在其他地方初始化推送服务
        
        @Override
        public void onCreate() {
    
            super.onCreate();
            
            //判断用户是否已经打开App,详细见下面方法定义
            if (shouldInit()) {
            //注册推送服务
            //注册成功后会向DemoMessageReceiver发送广播
            // 可以从DemoMessageReceiver的onCommandResult方法中MiPushCommandMessage对象参数中获取注册信息
                MiPushClient.registerPush(this, APP_ID, APP_KEY);
             //参数说明
            //context:Android平台上app的上下文,建议传入当前app的application context
            //appID:在开发者网站上注册时生成的,MiPush推送服务颁发给app的唯一认证标识
           //appKey:在开发者网站上注册时生成的,与appID相对应,用于验证appID是否合法
            }
    
    
            //下面是与测试相关的日志设置
            LoggerInterface newLogger = new LoggerInterface() {
    
                @Override
                public void setTag(String tag) {
                    // ignore
                }
    
                @Override
                public void log(String content, Throwable t) {
                    Log.d(TAG, content, t);
                }
    
                @Override
                public void log(String content) {
                    Log.d(TAG, content);
                }
            };
            Logger.setLogger(this, newLogger);
            if (sHandler == null) {
                sHandler = new DemoHandler(getApplicationContext());
            }
        }
    
    
    //通过判断手机里的所有进程是否有这个App的进程
    //从而判断该App是否有打开
        private boolean shouldInit() {
    //通过ActivityManager我们可以获得系统里正在运行的activities
    //包括进程(Process)等、应用程序/包、服务(Service)、任务(Task)信息。
            ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
            List<RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
            String mainProcessName = getPackageName();
            
           //获取本App的唯一标识
            int myPid = Process.myPid();
            //利用一个增强for循环取出手机里的所有进程
            for (RunningAppProcessInfo info : processInfos) {
                //通过比较进程的唯一标识和包名判断进程里是否存在该App
                if (info.pid == myPid && mainProcessName.equals(info.processName)) {
                    return true;
                }
            }
            return false;
        }
    
        public static DemoHandler getHandler() {
            return sHandler;
        }
    
        public static void setMainActivity(MainActivity activity) {
            sMainActivity = activity;
        }
    
    
    //通过设置Handler来设置提示文案
        public static class DemoHandler extends Handler {
    
            private Context context;
    
            public DemoHandler(Context context) {
                this.context = context;
            }
    
            @Override
            public void handleMessage(Message msg) {
                String s = (String) msg.obj;
                if (sMainActivity != null) {
                    sMainActivity.refreshLogInfo();
                }
                if (!TextUtils.isEmpty(s)) {
                    Toast.makeText(context, s, Toast.LENGTH_LONG).show();
                }
            }
        }
    }
    

    总结:

    • 步骤1:先判断应用App是否已开启 - 通过判断系统里的进程
    • 通过静态方法
    public static void registerPush(Context context, String appID, String appKey)
    

    进行推送服务注册,详细参数如下:

    • 为了提高注册率,最好在Application的onCreate中初始化推送服务

    你也可以根据需要,在其他地方初始化推送服务

    1.2.2 DemoMessageReceiver类

    继承自PushMessageReceiver(抽象类,继承自BroadcastReceiver),其作用主要是:

    • 接收推送消息
    • 对推送消息进行处理

    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.xml
    
    
    
    public class DemoMessageReceiver extends PushMessageReceiver {
    
        private String mRegId;
        private String mTopic;
        private String mAlias;
        private String mAccount;
        private String mStartTime;
        private String mEndTime;
    
    
        //透传消息到达客户端时调用
        //作用:可通过参数message从而获得透传消息,具体请看官方SDK文档
        @Override
        public void onReceivePassThroughMessage(Context context, MiPushMessage message) {
            Log.v(DemoApplication.TAG,
                    "onReceivePassThroughMessage is called. " + message.toString());
            String log = context.getString(R.string.recv_passthrough_message, message.getContent());
            MainActivity.logList.add(0, getSimpleDate() + " " + log);
    
            if (!TextUtils.isEmpty(message.getTopic())) {
                mTopic = message.getTopic();
            } else if (!TextUtils.isEmpty(message.getAlias())) {
                mAlias = message.getAlias();
            }
    
            Message msg = Message.obtain();
            msg.obj = log;
            DemoApplication.getHandler().sendMessage(msg);
        }
    
    
    //通知消息到达客户端时调用
         //注:应用在前台时不弹出通知的通知消息到达客户端时也会回调函数
        //作用:通过参数message从而获得通知消息,具体请看官方SDK文档
       
        @Override
        public void onNotificationMessageArrived(Context context, MiPushMessage message) {
            Log.v(DemoApplication.TAG,
                    "onNotificationMessageArrived is called. " + message.toString());
            String log = context.getString(R.string.arrive_notification_message, message.getContent());
            MainActivity.logList.add(0, getSimpleDate() + " " + log);
    
            if (!TextUtils.isEmpty(message.getTopic())) {
                mTopic = message.getTopic();
            } else if (!TextUtils.isEmpty(message.getAlias())) {
                mAlias = message.getAlias();
            }
    
            Message msg = Message.obtain();
            msg.obj = log;
            DemoApplication.getHandler().sendMessage(msg);
        }
        
        //用户手动点击通知栏消息时调用
         //注:应用在前台时不弹出通知的通知消息到达客户端时也会回调函数
        //作用:1. 通过参数message从而获得通知消息,具体请看官方SDK文档
        //2. 设置用户点击消息后打开应用 or 网页 or 其他页面
    
        @Override
        public void onNotificationMessageClicked(Context context, MiPushMessage message) {
            Log.v(DemoApplication.TAG,
                    "onNotificationMessageClicked is called. " + message.toString());
            String log = context.getString(R.string.click_notification_message, message.getContent());
            MainActivity.logList.add(0, getSimpleDate() + " " + log);
    
            if (!TextUtils.isEmpty(message.getTopic())) {
                mTopic = message.getTopic();
            } else if (!TextUtils.isEmpty(message.getAlias())) {
                mAlias = message.getAlias();
            }
    
            Message msg = Message.obtain();
            if (message.isNotified()) {
                msg.obj = log;
            }
            DemoApplication.getHandler().sendMessage(msg);
        }
    
    
        
        //用来接收客户端向服务器发送命令后的响应结果。
        @Override
        public void onCommandResult(Context context, MiPushCommandMessage message) {
            Log.v(DemoApplication.TAG,
                    "onCommandResult is called. " + message.toString());
            String command = message.getCommand();
            List<String> 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);
            String log;
            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 if (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());
                }
            } else if (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());
                }
            } else if (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());
                }
            } else if (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());
                }
            } else if (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());
                }
            } else if (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());
                }
            } else if (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);
        }
    
    
        //用于接收客户端向服务器发送注册命令后的响应结果。
        @Override
        public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) {
            Log.v(DemoApplication.TAG,
                    "onReceiveRegisterResult is called. " + message.toString());
            String command = message.getCommand();
            List<String> arguments = message.getCommandArguments();
            String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments.get(0) : null);
            String log;
            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 String getSimpleDate() {
            return new SimpleDateFormat("MM-dd hh:mm:ss").format(new Date());
        }
    
    }
    

    总结

    • 根据需要复写PushMessageReceiver里对消息的相关处理方法,以下是相关方法的详情:


      相关方法详情
    • 关于onCommandResult(Context context,MiPushCommandMessage message)
      a. 作用:当客户端向服务器发送注册push、设置alias、取消注册alias、订阅topic、取消订阅topic等等命令后,从服务器返回结果。
      b. 参数说明

      参数说明

    1.2.3 MainActivity

    用于给用户设置标识,如别名、标签、账号等等

    MainActivity.java

    public class MainActivity extends Activity {
    
        public static List<String> logList = new CopyOnWriteArrayList<String>();
    
        private TextView mLogView = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            DemoApplication.setMainActivity(this);
    
            mLogView = (TextView) findViewById(R.id.log);
            
            // 设置别名
            findViewById(R.id.set_alias).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    final EditText editText = new EditText(MainActivity.this);
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle(R.string.set_alias)
                            .setView(editText)
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String alias = editText.getText().toString();
    //调用静态方法进行设置                                MiPushClient.setAlias(MainActivity.this, alias, null);
                                }
    
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                }
            });
            // 撤销别名
            findViewById(R.id.unset_alias).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    final EditText editText = new EditText(MainActivity.this);
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle(R.string.unset_alias)
                            .setView(editText)
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String alias = editText.getText().toString();
    //调用静态方法进行设置                                  MiPushClient.unsetAlias(MainActivity.this, alias, null);
                                }
    
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
    
                }
            });
            // 设置帐号
            findViewById(R.id.set_account).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    final EditText editText = new EditText(MainActivity.this);
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle(R.string.set_account)
                            .setView(editText)
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String account = editText.getText().toString();
    //调用静态方法进行设置                                  MiPushClient.setUserAccount(MainActivity.this, account, null);
                                }
    
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
    
                }
            });
            // 撤销帐号
            findViewById(R.id.unset_account).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    final EditText editText = new EditText(MainActivity.this);
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle(R.string.unset_account)
                            .setView(editText)
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String account = editText.getText().toString();
    //调用静态方法进行设置                                  MiPushClient.unsetUserAccount(MainActivity.this, account, null);
                                }
    
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                }
            });
            // 设置标签
            findViewById(R.id.subscribe_topic).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    final EditText editText = new EditText(MainActivity.this);
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle(R.string.subscribe_topic)
                            .setView(editText)
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String topic = editText.getText().toString();
    //调用静态方法进行设置                                  MiPushClient.subscribe(MainActivity.this, topic, null);
                                }
    
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                }
            });
            // 撤销标签
            findViewById(R.id.unsubscribe_topic).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    final EditText editText = new EditText(MainActivity.this);
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle(R.string.unsubscribe_topic)
                            .setView(editText)
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String topic = editText.getText().toString();
    //调用静态方法进行设置                                  MiPushClient.unsubscribe(MainActivity.this, topic, null);
                                }
    
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                }
            });
            // 设置接收消息时间
            findViewById(R.id.set_accept_time).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    new TimeIntervalDialog(MainActivity.this, new TimeIntervalInterface() {
    
                        @Override
                        public void apply(int startHour, int startMin, int endHour,
                                          int endMin) {
                            //调用静态方法进行设置  
                            MiPushClient.setAcceptTime(MainActivity.this, startHour, startMin, endHour, endMin, null);
                        }
    
                        @Override
                        public void cancel() {
                            //ignore
                        }
    
                    })
                            .show();
                }
            });
            // 暂停推送
            findViewById(R.id.pause_push).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    MiPushClient.pausePush(MainActivity.this, null);
                }
            });
    
            findViewById(R.id.resume_push).setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                //调用静态方法进行设置  
                    MiPushClient.resumePush(MainActivity.this, null);
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            refreshLogInfo();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            DemoApplication.setMainActivity(null);
        }
    
        public void refreshLogInfo() {
            String AllLog = "";
            for (String log : logList) {
                AllLog = AllLog + log + "\n\n";
            }
            mLogView.setText(AllLog);
        }
    }
    

    总结

    根据需求对不同用户设置不同的推送标识,如别名、标签等等。

    a. 别名(Alias)

    • 开发者可以为指定用户设置别名,然后给这个别名推送消息,

    效果等同于给RegId推送消息,Alias是除Regid(自动生成的)和UserAccount之外的第三个用户标识

    • 开发者可以取消指定用户的某个别名,服务器就不会给这个别名推送消息了。
    //设置别名
    MiPushClient.setAlias(Context context, String alias, String category);
    
    //撤销别名
    MiPushClient.unsetAlias(Context context, String alias, String category);
    //参数说明
    //context:Android平台上app的上下文,建议传入当前app的application context
    //alias:为指定用户设置别名 / 为指定用户取消别名
    //category:扩展参数,暂时没有用途,直接填null
    
    //获取该客户端所有的别名
    public static List<String> getAllAlias(final Context context)
    

    b. 用户账号(UserAccoun)

    • 开发者可以为指定用户设置userAccount
    • 开发者可以取消指定用户的某个userAccount,服务器就不会给这个userAccount推送消息了
    //设置
    MiPushClient.setUserAccount(final Context context, final String userAccount, String
    category)
    
    //撤销
    MiPushClient.unsetUserAccount(final Context context, final String userAccount, String
    category)
    //参数说明
    //context:Android平台上app的上下文,建议传入当前app的application context
    //userAccount:为指定用户设置userAccount / 为指定用户取消userAccount
    //category:扩展参数,暂时没有用途,直接填null
    
    //获取该客户端所有设置的账号
    public static List<String> getAllUserAccount(final Context context)
    

    c. 标签(Topic)

    • 开发者可以结合自己的业务特征,给用户打上不同的标签。
    • 消息推送时,开发者可以结合每条消息的内容和目标用户,为每条消息选择对应的标签,为开发者可以根据订阅的主题实现分组群发,从而进行消息的精准推送
    //设置标签
    MiPushClient.subscribe(Context context, String topic, String category);
    //撤销标签
    MiPushClient.unsubscribe(Context context, String topic, String category);
    //参数说明
    //context:Android平台上app的上下文,建议传入当前app的application context
    //topic:为指定用户设置设置订阅的主题 / 为指定用户取消订阅的主题
    //category:扩展参数,暂时没有用途,直接填null
    
    //获取该客户端所有的标签
    public static List<String> getAllTopic(final Context context);
    
    

    TimeIntervalDialog

    作用:用于设置推送的时间-开始时间+暂停时间

    package com.xiaomi.mipushdemo;
    
    import android.app.Dialog;
    import android.content.Context;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TimePicker;
    import android.widget.TimePicker.OnTimeChangedListener;
    
    //继承OnTimeChangedListener接口
    public class TimeIntervalDialog extends Dialog implements OnTimeChangedListener {
    
        
        private TimeIntervalInterface mTimeIntervalInterface;
        private Context mContext;
        private TimePicker mStartTimePicker, mEndTimePicker;
        private int mStartHour, mStartMinute, mEndHour, mEndMinute;
    
        private Button.OnClickListener clickListener = new Button.OnClickListener() {
    
            @Override
            public void onClick(View v) {
                switch (v.getId()) {
                    case R.id.apply:
                        dismiss();
                        //设置时间参数
                        mTimeIntervalInterface.apply(mStartHour, mStartMinute, mEndHour, mEndMinute);
                        break;
                    case R.id.cancel:
                        dismiss();
                        mTimeIntervalInterface.cancel();
                        break;
                    default:
                        break;
                }
            }
        };
    
        public TimeIntervalDialog(Context context, TimeIntervalInterface timeIntervalInterface,
                                  int startHour, int startMinute, int endHour, int endMinute) {
            super(context);
            mContext = context;
            this.mTimeIntervalInterface = timeIntervalInterface;
            this.mStartHour = startHour;
            this.mStartMinute = startMinute;
            this.mEndHour = endHour;
            this.mEndMinute = endMinute;
        }
    
        public TimeIntervalDialog(Context context, TimeIntervalInterface timeIntervalInterface) {
            this(context, timeIntervalInterface, 0, 0, 23, 59);
        }
    
        @Override
        protected void onCreate(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);
        }
    
        @Override
        public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
            if (view == mStartTimePicker) {
                mStartHour = hourOfDay;
                mStartMinute = minute;
            } else if (view == mEndTimePicker) {
                mEndHour = hourOfDay;
                mEndMinute = minute;
            }
        }
    
        interface TimeIntervalInterface {
            void apply(int startHour, int startMin, int endHour, int endMin);
    
            void cancel();
        }
    }
    
    

    总结

    • 使用一个继承了Dialog类的TimeIntervalDialog类进行推送时间的配置
    • 可进行的配置:设置推送时间(开始 & 结束)、暂停推送时间、恢复推送时间
    //设置推送时间(开始 & 结束)
    MiPushClient.setAcceptTime(Context context, int startHour, int startMin, int endHour,
    int endMin, String category)
    //设置暂停推送时间、恢复推送时间
    pausePush(Context context, String category)`和`resumePush(Context context, String category)
    //参数说明
    //context:Android平台上app的上下文,建议传入当前app的application context
    //startHour:接收时段开始时间的小时
    //startMin  :接收时段开始时间的分钟
    //endHour:接收时段结束时间的小时
    //endMin:接收时段结束时间的分钟
    //category:扩展参数,暂时没有用途,直接填null
    
    

    AndroidManifest文件的配置

    //小米推送支持最低的Android版本是2.2
    <uses-sdk  android:minSdkVersion="8"/>
    
    //设置一系列权限
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.GET_TASKS" />
        <uses-permission android:name="android.permission.VIBRATE" />
    
    //这里com.xiaomi.mipushdemo改成自身app的包名
        <permission android:name="com.xiaomi.mipushdemo.permission.MIPUSH_RECEIVE" android:protectionLevel="signature" />
    
    //这里com.xiaomi.mipushdemo改成自身app的包名
        <uses-permission android:name="com.xiaomi.mipushdemo.permission.MIPUSH_RECEIVE" />
    
    
    //注册广播BroadcastReceiver & Service
    //都是静态注册,因为要长期处在后台运行
    //注:共是3个广播接收器和4个服务,其中包括继承了PushMessageReceiver的DemoMessageReceiver
                    
            //4个后台服务
            <service
              android:enabled="true"
              android:process=":pushservice"
              android:name="com.xiaomi.push.service.XMPushService"/>
    
            //此service必须在3.0.1版本以后(包括3.0.1版本)加入
            <service
              android:name="com.xiaomi.push.service.XMJobService"
              android:enabled="true"
              android:exported="false"
              android:permission="android.permission.BIND_JOB_SERVICE"
              android:process=":pushservice" />
            
            //此service必须在2.2.5版本以后(包括2.2.5版本)加入
            <service
              android:enabled="true"
              android:exported="true"
              android:name="com.xiaomi.mipush.sdk.PushMessageHandler" /> 
    
            <service android:enabled="true"
              android:name="com.xiaomi.mipush.sdk.MessageHandleService" /> 
            
    
            //3个广播
            <receiver
              android:exported="true"
              android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver" >
              <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <category android:name="android.intent.category.DEFAULT" />
              </intent-filter>
            </receiver>
    
            <receiver
              android:exported="false"
              android:process=":pushservice"
              android:name="com.xiaomi.push.service.receivers.PingReceiver" >
              <intent-filter>
                <action android:name="com.xiaomi.push.PING_TIMER" />
              </intent-filter>
            </receiver>
    
    //继承了PushMessageReceiver的DemoMessageReceiver的广播注册
            <receiver
                android:name="com.xiaomi.mipushdemo.DemoMessageReceiver"
                android:exported="true">
                <intent-filter>
                    <action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" />
                </intent-filter>
                <intent-filter>
                    <action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" />
                </intent-filter>
                <intent-filter>
                    <action android:name="com.xiaomi.mipush.ERROR" />
                </intent-filter>
            </receiver>
    

    2. 集成小米推送步骤汇总

    • 步骤1:在小米推送平台进行相关注册开发者账号,并进行应用的注册:应用包名,AppID和AppKey
    • 步骤2:将小米推送的SDK包加入库
    • 步骤3:在应用内初始化小米推送服务
    • 步骤4:继承PushMessageReceiver,并复写相关推送消息的方法
    • 步骤5:在AndroidManifest文件里面配置好权限、注册Service和BroadcastReceiver

    在Android6.0里面的权限需要动态获取

    • 步骤6:根据需要设置一系列的推送设置,如用户别名、标签等等

    接下来,我们来按照上面的步骤,一步步来实现一个简易的小米推送Demo

    3. 实例解析

    步骤1:在小米推送平台进行相关注册开发者账号,并进行应用的注册:应用包名,AppID和AppKey

    注意,填入的包名要跟你的应用App的包名是一致的

    创建应用 AppID和Key

    步骤2:将小米推送的SDK包加入到你应用的库里

    放入到app/libs文件夹下,然后右键点击add as Library,最后点击Model就导入成功了
    点击此处进行下载

    小米推送SDK 导入包

    步骤3:在应用内初始化小米推送服务

    为了提高推送服务的注册率,我选择在Application的onCreate中初始化推送服务

    BaseActivity.java

    package scut.carson_ho.demo_mipush;
    
    import android.app.ActivityManager;
    import android.app.Application;
    import android.content.Context;
    import android.os.Process;
    
    import com.xiaomi.mipush.sdk.MiPushClient;
    
    import java.util.List;
    
    /**
     * Created by Carson_Ho on 16/10/26.
     */
    
        //主要要继承Application
    public class BaseActivity extends Application {
        // 使用自己APP的ID(官网注册的)
        private static final String APP_ID = "2882303761517520369";
        // 使用自己APP的Key(官网注册的)
        private static final String APP_KEY = "5401752085369";
    
    
        //为了提高推送服务的注册率,我建议在Application的onCreate中初始化推送服务
        //你也可以根据需要,在其他地方初始化推送服务
        @Override
        public void onCreate() {
            super.onCreate();
    
    
            if (shouldInit()) {
                //注册推送服务
                //注册成功后会向DemoMessageReceiver发送广播
                // 可以从DemoMessageReceiver的onCommandResult方法中MiPushCommandMessage对象参数中获取注册信息
                MiPushClient.registerPush(this, APP_ID, APP_KEY);
            }
        }
    
        //通过判断手机里的所有进程是否有这个App的进程
        //从而判断该App是否有打开
        private boolean shouldInit() {
    
        //通过ActivityManager我们可以获得系统里正在运行的activities
        //包括进程(Process)等、应用程序/包、服务(Service)、任务(Task)信息。
            ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
            List<ActivityManager.RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
            String mainProcessName = getPackageName();
    
            //获取本App的唯一标识
            int myPid = Process.myPid();
            //利用一个增强for循环取出手机里的所有进程
            for (ActivityManager.RunningAppProcessInfo info : processInfos) {
                //通过比较进程的唯一标识和包名判断进程里是否存在该App
                if (info.pid == myPid && mainProcessName.equals(info.processName)) {
                    return true;
                }
            }
            return false;
        }
    }
    

    注意要在Android.manifest.xml里的application里加入

    android:name=".BaseActivity"
    

    这样在应用初始化时是第一个加载BaseActivity.java类文件的
    如下图:

    示意图

    步骤4:设置子类继承PushMessageReceiver,并复写相关推送消息的方法

    Mipush_Broadcast.java

    package scut.carson_ho.demo_mipush;
    
    import android.content.Context;
    
    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;
    
    /**
     * Created by Carson_Ho on 16/10/26.
     */
    
    public class Mipush_Broadcast extends PushMessageReceiver {
    
        //透传消息到达客户端时调用
        //作用:可通过参数message从而获得透传消息,具体请看官方SDK文档
        @Override
        public void onReceivePassThroughMessage(Context context, MiPushMessage message) {
    
            //打印消息方便测试
            System.out.println("透传消息到达了");
            System.out.println("透传消息是"+message.toString());
    
        }
    
    
    //通知消息到达客户端时调用
        //注:应用在前台时不弹出通知的通知消息到达客户端时也会回调函数
        //作用:通过参数message从而获得通知消息,具体请看官方SDK文档
    
        @Override
        public void onNotificationMessageArrived(Context context, MiPushMessage message) {
            //打印消息方便测试
            System.out.println("通知消息到达了");
            System.out.println("通知消息是"+message.toString());
        }
    
        //用户手动点击通知栏消息时调用
        //注:应用在前台时不弹出通知的通知消息到达客户端时也会回调函数
        //作用:1. 通过参数message从而获得通知消息,具体请看官方SDK文档
        //2. 设置用户点击消息后打开应用 or 网页 or 其他页面
    
        @Override
        public void onNotificationMessageClicked(Context context, MiPushMessage message) {
    
            //打印消息方便测试
            System.out.println("用户点击了通知消息");
            System.out.println("通知消息是" + message.toString());
            System.out.println("点击后,会进入应用" );
    
        }
    
        //用来接收客户端向服务器发送命令后的响应结果。
        @Override
        public void onCommandResult(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("注册失败");
                }
            }
        }
    
        //用于接收客户端向服务器发送注册命令后的响应结果。
        @Override
        public void onReceiveRegisterResult(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());
            }
        }
    
    }
    

    具体设置请看官方SDK文档,这里只给出最简单Demo,不作过多描述

    步骤5:在AndroidManifest文件里面配置好权限、注册Service和BroadcastReceiver

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="scut.carson_ho.demo_mipush">
    
        //相关权限
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.GET_TASKS" />
        <uses-permission android:name="android.permission.VIBRATE" />
    
    
        //注意这里.permission.MIPUSH_RECEIVE是自身app的包名
        <permission android:name="scut.carson_ho.demo_mipush.permission.MIPUSH_RECEIVE" android:protectionLevel="signature" />
    
        //注意这里.permission.MIPUSH_RECEIVE是自身app的包名
        <uses-permission android:name="scut.carson_ho.demo_mipush.permission.MIPUSH_RECEIVE" />
    
    //注意要初始化BaseActivity.java类
        <application
            android:name=".BaseActivity"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
    
    
        //注册广播BroadcastReceiver和Service
        //都是静态注册,因为要长期处在后台运行
        //注:共是3个广播接收器和4个服务,其中包括继承了PushMessageReceiver的DemoMessageReceiver
    
        //4个后台服务
        <service
            android:enabled="true"
            android:process=":pushservice"
            android:name="com.xiaomi.push.service.XMPushService"/>
    
        //此service必须在3.0.1版本以后(包括3.0.1版本)加入
        <service
            android:name="com.xiaomi.push.service.XMJobService"
            android:enabled="true"
            android:exported="false"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:process=":pushservice" />
    
        //此service必须在2.2.5版本以后(包括2.2.5版本)加入
        <service
            android:enabled="true"
            android:exported="true"
            android:name="com.xiaomi.mipush.sdk.PushMessageHandler" />
    
        <service android:enabled="true"
            android:name="com.xiaomi.mipush.sdk.MessageHandleService" />
    
    
        //3个广播
        <receiver
            android:exported="true"
            android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver" >
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
    
        <receiver
            android:exported="false"
            android:process=":pushservice"
            android:name="com.xiaomi.push.service.receivers.PingReceiver" >
            <intent-filter>
                <action android:name="com.xiaomi.push.PING_TIMER" />
            </intent-filter>
        </receiver>
    
        //继承了PushMessageReceiver的DemoMessageReceiver的广播注册
        <receiver
            android:name=".Mipush_Broadcast"
            android:exported="true">
            <intent-filter>
                <action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.xiaomi.mipush.ERROR" />
            </intent-filter>
        </receiver>
    
    
        </application>
    </manifest>
    
    

    步骤6:根据需要设置一系列的推送设置,如用户别名、标签等等

    • 此处是简单Demo,所以不作过多的设置
    • 更多设置请回看上方官方Demo解析

    运行结果

    测试成功结果

    好了,客户端的代码写好后,可以去小米官网测试一下消息推送了

    步骤1:在小米官网的消息推送里选择你创建的应用,然后点击“推送工具”

    点击推送工具

    步骤2:设置推送消息的相关信息

    可进行的配置非常全面,基本上能满足推送的需求

    设置推送消息
    设置推送消息

    推送的结果

    消息到达客户端 测试结果
    测试结果:收到的信息 点击通知栏消息后

    4. Demo下载地址

    Carson的Github:Demo_MiPush

    5. 关于对小米推送的思考(问题)

    上述说的小米推送看似简单:初始化推送服务 + 相关推送设置。但是,好的代码不仅能在正常情况下工作,还应该充分考虑失败情况。那么,有什么样的失败情况需要我们考虑呢?

    • 背景:在这个初始化推送服务的过程中,是需要联系小米推送的服务器来申请reg id(即推送token)。
    • 冲突:初始化过程可能失败:网络问题(没网or网络信号弱)、服务器问题导致初始化失败。那么,当失败以后,该什么时候再次进行初始化呢?

    小米推送的Demo里并没有相关措施解决这个问题

    • 解决方案:在初始化失败的情况下提供重试机制,直到初始化成功(可以通过检测是否已经拿到推送token来确定),问题解决的逻辑如下:
    解决逻辑
    • 具体代码在这里就不作过多描述,如果你希望获得含注册重试机制的小米推送源代码,请在评论留下你的邮箱,我将亲自发送到你的邮箱
    1. 知识点涵盖:网络数据的检测 & 广播接收器
    2. 具体请看我写的另外两篇文章:
      Android:BroadcastReceiver广播接收器最全面解析
      Android:检测网络状态&监听网络变化

    总结

    全面考虑到所有异常问题并恰当地进行处理才能真正体现程序猿的功力,希望大家做撸代码的时候不要只做代码的搬运工,纯粹写代码并不会让你成长,关键在于思考

    6. 总结


    请点赞!因为你的鼓励是我写作的最大动力!

    相关文章阅读
    Android开发:最全面、最易懂的Android屏幕适配解决方案
    Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)
    Android开发:顶部Tab导航栏实现(TabLayout+ViewPager+Fragment)
    Android开发:底部Tab菜单栏实现(FragmentTabHost+ViewPager)
    Android开发:JSON简介及最全面解析方法!
    Android开发:XML简介及DOM、SAX、PULL解析对比


    欢迎关注Carson_Ho的简书!

    不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度

    相关文章

      网友评论

      • 0error_0warning:有没有哪个大哥试过将这个推送中的广播搞成动态注册的广播啊?我试了试发现不能正常的接收推送消息啊。。华为的推送,搞成动态的广播,可以收到透传消息,但是收不到通知的消息,有没有哪个大手子知道为啥啊?
      • ef40a0722441:博主你好,我想要那个注册重试机制的小米推送源代码,邮箱是529575319@qq.com。谢谢你的分享
      • 芮瑞:麻烦发一下注册重试机制的小米推送源代码,1326703922@qq.com 多谢!
      • 0error_0warning:有没有看官方文档,发现它快速接入指南中修改gradle的图片显示不出来的?我强行试了试,它修改的是build.gradle中的applicationId
      • f5aa00b41d31:麻烦发一下注册重试机制的小米推送源代码,3256470467@qq.com 多谢!
      • coolzpw:请问下,大神,如果我想在华为手机用华为的推送,小米用小米的推送,我应该怎么去实现? 在application去判断型号,然后去初始化一个推送?还是分渠道打包呀?
      • 这个不会有人用了吧:博主你好,我想要那个注册重试机制的小米推送源代码,邮箱是504903657@qq.com。谢谢你的分享。
      • f3e6b7ae9a26:麻烦发一下注册重试机制的小米推送源代码,249640881@qq.com,谢谢
      • 033e73e19deb:谢谢分享,麻烦发我一份注册重试机制的小米推送代码846969127@qq.com, 谢谢博主分享 !
      • walker113:谢谢分享,特需要注册重试机制的小米推送代码,邮箱是
        597222089@qq.com
        麻烦了
      • 6a808a91450f:你好,我的邮箱是372221253@qq.com。想要那个注册重试机制的小米推送源代码,谢谢你的分享。
      • a47d94b2d476:发我一份注册重试机制的小米推送代码 406724259@qq.com, 谢谢博主分享 !
      • Coair_Scarlet:谢谢 博主分享 麻烦博主发一份注册重试机制的小米推送代码 924508262@qq.com,再谢!
      • 景瀚:谢谢分享,特需要注册重试机制的小米推送代码,邮箱是469077279@qq.com,麻烦了
      • a3e41f0baf69:你好,首先非常感谢你的分享。我想要那个注册重试机制的小米推送源代码,麻烦了,我的邮箱是547860818@qq.com。谢谢了
      • 放纵的卡尔:大神,有时间请抽空发下邮箱. 875721373@qq.com 感谢!
      • 花花笑脸人888:写得很详细,赞赞赞 麻烦发一下注册重试机制的源码 1007812935@qq.com 谢谢了
      • dc5a6a4d06fa:注册机制推送源码,644210665@qq.com,谢谢:pray:
      • d151ed08f4ad:你好,我的邮箱是646729425@qq.com。想要那个注册重试机制的小米推送源代码,谢谢你的分享。
      • 0bb3ab76741a:您好,辛苦您写出这么好的文章,注册重试机制的推送源代码麻烦给一份吧,15037007464@163.com,辛苦您了
      • 0ab412589f2a:你好,谢谢你的分享。那个注册重试机制的小米推送源代码发我一份,麻烦了,我的邮箱是798298436@qq.com
      • 叛逆的曾小砂:博主你好,我想要那个注册重试机制的小米推送源代码,邮箱是659809560@qq.com。谢谢你的分享。
      • 9c61578f5722:先为这个系列文章点个赞。想要注册重试机制的源码,麻烦了。953736489@qq.com。
      • 0a6d2960499b:感谢作者的分享,我想要您的注册重试机制的小米推送源代码,邮箱751330332@qq.com,谢谢
      • Linkll:谢谢您的分享,希望您能帮忙把那个注册重试机制的小米推送源代码发我一份,谢谢!bb168ll@foxmail.com
      • ab4e84018444:你好,我的邮箱是1048181453@qq.com。想要那个注册重试机制的小米推送源代码,谢谢你的分享。
      • 子龙_3ac9:mark2007081021@163.com
      • LucasAdam:453166006@qq.com
      • reader_b8f9:想问一下注册个人开发者还是企业开发者,有啥不一样?
      • reader_b8f9:qff_it@163.com 麻烦楼主发一个!
      • 都不想悔疚:🌝感谢分享,小哥哥能分享下注册重试机制的小米推送源代码嘛…邮箱747422053@qq.com
      • 都不想悔疚:超喜欢小哥哥的ヽ(´~`;)好多次找资料都是看见你的文章~~
      • d34d39687452:你好,感谢你的分享。麻烦将那个注册重试机制的小米推送源代码发我一份,谢谢,我的邮箱
        1274100542@qq.com
      • 9e29589e5c0e:谢谢谢谢!1184106223@qq.com 我想要那个注册重试机制的小米推送源代码
      • here_30e0:你好,你的文章写得很详细,支持支持,我的邮箱是1014667709@qq.com
      • 隰有荷:你好,小米推送搞了一天,终于在贵文章中获取到思路,谢谢你的分享,同时很期待重试机制的推送代码,我的邮箱是2419378537@qq.com。
      • d94a13c3b02f:你好,谢谢你的分享。我的邮箱是71048510@qq.com。想要那个注册重试机制的小米推送源代码,能麻烦发我一下吗?谢谢。
      • Lindroid:你好,感谢你的分享,注册重试机制的源码能否发给我一份呢?我的邮箱是1603683935@qq.com。谢谢了。
      • 9f9097eb1aae:谢谢您分享了这么多有用的知识,注册重试机制的源码请发我一份:a610757257@163.com.
      • RoboyCore:你好,感谢你的分享。麻烦将那个注册重试机制的小米推送源代码发送到我的邮箱22271405@qq.com。
      • 9b97ac74f30d:您好,我是一名正在学习Android开发的大学生,看到您的文章觉得非常有帮助,能请您分享一下小米重试机制的源代码吗?麻烦您了,我的邮箱是764297959@qq.com,谢谢您。
      • a_simple_coder:App在杀掉进程后接收不到消息,这块在小米官网技术问题块看到说通知栏消息是不受自启动管理影响的,大神知道是什么原因么?
      • 柴江朋:你好,我也集成了小米推送,为什么我推送多条,手机通知栏上只显示一条,把之前的都覆盖了,怎么能让它不覆盖呢,推送几条就显示几条。
      • 59cdbeb4fc8a:475972748@qq.com 感谢作者 注册重试
      • 7f90ee6a6181:博主你好,我想要那个注册重试机制的小米推送源代码,邮箱是457758064@qq.com。谢谢你的分享。
      • 324e7ae086e9:你好,谢谢你的分享。新手一枚,想要那个注册重试机制的小米推送源代码,麻烦了,我的邮箱是472378168@qq.com。
      • f8af1a4d91b9:您好,感谢分享,分享下注册重试机制的小米推送源代码,推送的问题困扰了我很久,麻烦了,我的邮箱是 18511899797@163.com。
      • 9c45fcc97b7a:楼主V5,求注册重试机制的小米推送源代码,chenxingyi90@163.com,谢谢
      • Ez浮生:谢谢您的分享,希望您能帮忙把那个注册重试机制的小米推送源代码发我一份,谢谢!250091036@qq.com
      • zouzhenglu:这个是官方的demo吧,如果 我要设置多个别名,多个标签的话应该怎样?
      • e71c13205f34:感谢作者无私的分享精神,有空请传一份注册重试机制推送源代码给我。谢谢。18616751989@163.com
      • 0445981d6022:善于思考的程序员是个好程序员,哈哈,好的东西需要分享一下,学习一下,fang47881@126.com。谢谢
      • spynokia:782055421@qq.com 求
      • 7c85ea2fe049:你好,感谢你的分享。麻烦将那个注册重试机制的小米推送源代码发送到我的邮箱liyanlong307@qq.com。
      • 8009048f3604:你好,我的邮箱是1098424420@qq.com。想要那个注册重试机制的小米推送源代码,谢谢你的分享。
      • thaixp:虽然我看懂了,可是我还是想看你解决的代码,小码农一名,楼主写的博客很详细我也会多多推荐我身边的朋友来看。邮箱 thaixp@163.com
      • 7134e654c6c9:我说的前提 是小米手机上集成这个小米推送的sdk
      • 7134e654c6c9:您好 请问下小米推送是如何保证 android端的PushService存活的呢。一旦被手动清理掉 小米SDK中的PushService和心跳Receiver是否还能存活? 请您务必回复一下我 我和纠结这个问题 谢谢您了!
        Carson带你学安卓:@小小铯铯 你好,具体请看我的写另外一个文章:Android消息推送:第三方消息推送平台详细解析,http://www.jianshu.com/p/d77eaca4e52a
        Carson带你学安卓:你好,具体请看我的写另外一个文章:Android消息推送:第三方消息推送平台详细解析,http://www.jianshu.com/p/d77eaca4e52a
        b8adf0a1bb57:我也很纠结这个问题。。。。
      • e33ed3368e62:你好,首先谢谢你的分享。再就是我,我想要那个注册重试机制的小米推送源代码,麻烦了,我的邮箱是lyh_550@163.com。

      本文标题:Android消息推送:手把手教你集成小米推送

      本文链接:https://www.haomeiwen.com/subject/llsluttx.html