热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android消息推送:手把手教你集成小米推送(附demo)

本篇文章主要介绍了Android消息推送:手把手教你集成小米推送,非常具有实用价值,需要的朋友可以参考下。

前言

在Android开发中,消息推送功能的使用非常常见。

推送消息截图

为了降低开发成本,使用第三方推送是现今较为流行的解决方案。

今天,我将手把手教大家如何在你的应用里集成小米推送

目录

目录

1. 官方Demo解析

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

请先到官网下载官方Demo和SDK说明文档

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 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 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 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 logList = new CopyOnWriteArrayList();

  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)

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

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

2、开发者可以取消指定用户的某个别名,服务器就不会给这个别名推送消息了。

//设置别名
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 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 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 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


//设置一系列权限
  
  
  
  
  
  
  

//这里com.xiaomi.mipushdemo改成自身app的包名
  

//这里com.xiaomi.mipushdemo改成自身app的包名
  


//注册广播BroadcastReceiver & Service
//都是静态注册,因为要长期处在后台运行
//注:共是3个广播接收器和4个服务,其中包括继承了PushMessageReceiver的DemoMessageReceiver

    //4个后台服务
    

    //此service必须在3.0.1版本以后(包括3.0.1版本)加入
    

    //此service必须在2.2.5版本以后(包括2.2.5版本)加入
     

     


    //3个广播
    
     
      
      
     
    

    
     
      
     
    

//继承了PushMessageReceiver的DemoMessageReceiver的广播注册
    
      
        
      
      
        
      
      
        
      
    

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包加入到你应用的库里

点击此处进行下载

小米推送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 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());
    }
  }

}

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

AndroidManifest.xml

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  //相关权限
  
  
  
  
  
  
  


  //注意这里.permission.MIPUSH_RECEIVE是自身app的包名
  

  //注意这里.permission.MIPUSH_RECEIVE是自身app的包名
  

//注意要初始化BaseActivity.java类
  
    
      
        

        
      
    



  //注册广播BroadcastReceiver和Service
  //都是静态注册,因为要长期处在后台运行
  //注:共是3个广播接收器和4个服务,其中包括继承了PushMessageReceiver的DemoMessageReceiver

  //4个后台服务
  

  //此service必须在3.0.1版本以后(包括3.0.1版本)加入
  

  //此service必须在2.2.5版本以后(包括2.2.5版本)加入
  

  


  //3个广播
  
    
      
      
    
  

  
    
      
    
  

  //继承了PushMessageReceiver的DemoMessageReceiver的广播注册
  
    
      
    
    
      
    
    
      
    
  


  


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

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

运行结果

测试成功结果

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

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

点击推送工具

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

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

设置推送消息 

设置推送消息

推送的结果

消息到达客户端

测试结果
测试结果:收到的信息

点击通知栏消息后

4. Demo下载地址  demo

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

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

  • 背景:在这个初始化推送服务的过程中,是需要联系小米推送的服务器来申请reg id(即推送token)。
  • 冲突:初始化过程可能失败:网络问题(没网or网络信号弱)、服务器问题导致初始化失败。那么,当失败以后,该什么时候再次进行初始化呢?
  • 解决方案:在初始化失败的情况下提供重试机制,直到初始化成功(可以通过检测是否已经拿到推送token来确定),问题解决的逻辑如下:

解决逻辑

总结

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
author-avatar
袁韦伦世彦琬育
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有