搜索
分发文档
应用分发
游戏分发
电视应用分发
快应用分发
小游戏分发
服务分发
内容分发
分发文档/应用分发/应用服务/推送服务/服务端Java SDK文档
服务端Java SDK文档更新时间: 2024-10-22 15:42:00

一、Introduction

1、Push Server SDK文档

更新日志

2、用途

推送消息发送;
消息统计数据获取;
订阅标签;
消息状态;
开发者工具;

二、快速接入

接入Java SDK前,您需要已启用小米推送服务,并且获得应用对应的AppId、 AppKey和AppSecret。

您可以选择接入服务端Java Http2 SDK(参见2.1节)。

1、接入Java Http2 SDK

1.1、获取SDK

Java Http2 SDK下载地址:http://admin.xmpush.xiaomi.com/zh_CN/mipush/downpage/java-http2

请下载最新的SDK版本。

1.2、运行环境

要求JDK版本大于或等于1.8。

1.3、导入SDK

  • 解压“MiPush_SDK_Server_Http2.zip”压缩包。
  • 将“MiPush_SDK_Server_Http2”目录下的jar包放入项目工程libs目录。
说明:如果运行环境为JDK 1.9以上版本可以不引入conscrypt-openjdk-uber-2.1.0.jar包。如果不想使用okhttp3组件,可以不引入conscrypt-openjdk-uber-2.1.0.jar、okhttp-3.14.2.jar和okio-1.17.2.jar这三个jar包,同时调用Constants.disableOkHttp3()方法,此时将不会启动HTTP2.0协议。

2、SDK类定义说明

参见各个类使用说明:

类名使用说明
Message消息对象
Builder构建发送给Android设备的Message对象
TargetedMessage构建要发送的消息内容和发送目标
SenderMiPush消息发送类
Result服务器返回结果
Stats获取消息统计数据
Tracer追踪消息状态
Subscription订阅/取消订阅标签
Feedback{Deprecated}获取失效的RegID或Alias列表。
该接口已下线,请使用消息回执callback接口(callback.type: 16)进行失效数据过滤。
DevTools设备工具集
Constants常量定义
ErrorCode错误类型

三、发送消息

发送消息依赖Sender类com.xiaomi.xmpush.server.Sender
实例化SenderSender(String appSecret) - appSecret是在开发者网站上注册时生成的, 可在应用详情下查看返回结果Resultcom.xiaomi.xmpush.server.Result
方法说明
String getMessageId()消息发送成功, 服务器返回消息ID, 否则返回Null
ErrorCode getErrorCode()发送消息返回的错误码, 若返回ErrorCode.Success表示发送成功, 否则发送失败
String getReason()若消息发送失败, 服务器返回错误原因的文字描述, 否则返回Null

Result对于所有发送消息接口使用方式完全一样

Demo

private void sendMessage() throws Exception {
Constants.useOfficial();
Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
Result result = sender.send(message, regId, 3);
Log.v("Server response: ", "MessageId: " + result.getMessageId()
+ " ErrorCode: " + result.getErrorCode().toString()
+ " Reason: " + result.getReason());
}

1、构建消息

  • 构建Message消息对象
  • 构建TargetedMessage对象:TargetedMessage类中封装了Message对象和该Message所要发送的target;
TargetedMessage类:com.xiaomi.xmpush.server.TargetedMessage

区别:Message消息体只是包含消息参数, 不包括消息推送目标(regid, alias, useraccount, topic)

注意: TargetedMessage集合接口发送消息时, 所有的TargetedMessage对象的targetType必须相同, 不支持在一个调用中同时给regid和alias发送消息

方法说明
TargetedMessage()构造函数
setMessage(Message message)设置消息
setTarget(int targetType, String target)设置发送目标
targetType表示目标类型(目前仅支持三种类型)TargetedMessage.TARGET_TYPE_REGID(regid消息类型, target对应regid)TargetedMessage.TARGET_TYPE_ALIAS(alias消息类型, target对应alias)TargetedMessage.TARGET_TYPE_USER_ACCOUNT(useraccount消息类型, target对应useraccount)

1.1、Android平台

com.xiaomi.xmpush.server.Message.Builder

消息类型:

  • 通知栏消息 - 在系统通知栏进行展示;

Builder方法列表:

方法说明
Builder()构造方法
payload(String payload)设置要发送的消息内容payload, 不允许全是空白字符, 长度小于4KB, 一个中英文字符均计算为1
title(String title)设置在通知栏展示的通知的标题, 不允许全是空白字符, 长度小于50, 一个中英文字符均计算为1(通知栏消息必填)
description(String description)设置在通知栏展示的通知描述, 不允许全是空白字符, 长度小于128, 一个中英文字符均计算为1(通知栏消息必填)
notifyType(Integer type)设置通知类型, type类型支持以下值:
• 1:使用默认提示音提示
• 2:使用默认振动提示
• 4:使用默认呼吸灯提示
• -1(系统默认值):以上三种效果都有
• 0:以上三种效果都无,即静默推送。
并且支持1,2,4的任意OR运算来实现声音、振动和呼吸灯的任意组合。
restrictedPackageName(String packageName)设置app的包名packageName, packageName必须和开发者网站上申请的结果一致
restrictedPackageNames(String[] packageNames)设置app的多包名packageNames(多包名发送广播消息), packageNames必须和开发者网站上申请的结果一致, 可以为空, 为空则默认给所有渠道包名推送(不能同时调用restrictedPackageName方法和restrictedPackageNames方法)
timeToLive(int milliseconds)可选项,消息有效期,单位:毫秒(ms)。当用户设备未联网时,消息默认缓存时间为:公信消息最长1天,私信消息最长10天,超过缓存时间消息会丢弃
timeToSend(long milliseconds)可选项, 定时发送消息, timeToSend是以毫秒为单位的时间戳(仅支持七天内的定时消息)
notifyId(Integer id)可选项, 默认情况下, 通知栏只显示一条推送消息, 如果通知栏要显示多条推送消息, 需要针对不同的消息设置不同的notify_id(相同notify_id的通知栏消息会覆盖之前的),且要求notify_id为取值在0~2147483647的整数。
enableFlowControl(boolean needFlowControl)可选项, 控制消息是否需要进行平滑推送(qps less 3000/second), 默认不支持
extra(String key, String value)可选项, 对app提供一些扩展功能(除了这些扩展功能, 开发者还可以定义一些key和value来控制客户端的行为, 注:key和value的字符数不能超过1024, 至多可以设置10个key-value键值对)
build()根据设置的属性, 生成Message对象

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
Message message = new Message.Builder()
.payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
return message;
}

2、RegID消息

使用场景:

regId是app在客户端向小米推送服务注册时, 小米推送服务端根据设备标识和appId以及当前时间戳生成, 因此能够保证每个设备上每个app对应的regId都是不同的, 可以作为每台设备上app的唯一标识;注: 需要开发者自己的服务器接收客户端返回的regid并存储在自身服务器;

接口说明:

com.xiaomi.xmpush.server.Sender
方法说明
send(Message message, String regid, int retries)根据regid, 发送消息到指定设备上, retries代表发送失败后重试的次数。
send(Message message, List<String> regids, int retries)根据regids, 发送消息到指定的一组设备上, regids的个数不得超过1000个。
sendHybridMessageByRegId(message, regids, retries)给快应用发送regid消息。如果应用类型是快应用,须调用此方法。

Demo:

  • 单个regid消息:
private void sendMessage() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload= “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.send(message, regId, 3); //根据regID,发送消息到指定设备上
}
  • 多个regid消息(推荐使用)
private void sendMessage() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload= “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.send(message, Lists.newArrayList(regId1, regId2 ...), 3); //发送消息到一组设备上, regids个数不得超过1000个
}

3、Alias消息

使用场景:

别名alias是小米推送这边提供的一个个性化设定, 可以为每个设备上的app设置一个别名, 方便开发者管理, 并能做到精细化推送 alias与regid(设备)一一对应, 主要是为了方便开发者管理而推出, 如果多个设备设置同一个alias, 则只能后设置的设备才会收到消息(如果需要多个设备使用同一名称进行管理, 推荐使用UserAccount消息);注: alias由客户端发送Command请求进行设置,且每个app单台设备可订阅的alias上限为15个。

接口说明:

com.xiaomi.xmpush.server.Sender
方法说明
sendToAlias(Message message, String alias, int retries)根据alias, 发送消息到指定设备上, alias不允许全是空白字符, 不能包含逗号, 长度小于128, 中英文均以一个计算
sendToAlias(Message message, List<String> aliasList, int retries)根据aliasList, 发送消息到指定的一组设备上, 元素的个数不得超过1000个

Demo:

  • 单个alias消息:
private void sendMessageToAlias() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
String alias = “testAlias”; //alias非空白, 不能包含逗号, 长度小于128
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.sendToAlias(message, alias, 3); //根据alias, 发送消息到指定设备上
}
  • 多个alias消息(推荐使用)
private void sendMessageToAliases() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
List<String> aliasList = new ArrayList<String>();
aliasList.add(“testAlias1”); //alias非空白,不能包含逗号, 长度小于128
aliasList.add(“testAlias2”); //alias非空白,不能包含逗号, 长度小于128
aliasList.add(“testAlias3”); //alias非空白,不能包含逗号, 长度小于128
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.sendToAlias(message, aliasList, 3); //根据aliasList, 发送消息到指定设备上
}

4、UserAccount消息

使用场景:

userAccount主要适用于用户多点登陆的情况;一个账号account可以绑定多个设备(上限20个), 可以认为是小型的topic。注: useraccount由客户端调用setUserAccount(final Context context, final String userAccount, String category)接口进行设置。

接口说明:

com.xiaomi.xmpush.server.Sender
方法说明
sendToUserAccount(Message message, String userAccount, int retries)根据account, 发送消息到指定account上, account不允许全是空白字符, 不能包含逗号, 长度小于128, 中英文均以一个计算
sendToUserAccount(Message message, List<String> accountList, int retries)根据accountList, 发送消息到指定的一组设备上, 元素的个数不得超过1000个

Demo:

  • 单个useraccount消息:
private void sendMessageToUserAccount() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
String useraccount = “testUserAccount”; //useraccount非空白, 不能包含逗号, 长度小于128
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.sendToUserAccount(message, useraccount, 3); //根据useraccount, 发送消息到指定设备上
}
  • 多个useraccount消息(推荐使用):
private void sendMessageToUserAccounts() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
List<String> accoutList = new ArrayList<String>();
accoutList.add(“testUserAccount1”); //useraccount非空白,不能包含逗号, 长度小于128
accoutList.add(“testUserAccount2”); //useraccount非空白,不能包含逗号, 长度小于128
accoutList.add(“testUserAccount3”); //useraccount非空白,不能包含逗号, 长度小于128
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.sendToUserAccount(message, accoutList, 3); //根据accountList, 发送消息到指定设备上
}

5、Topic消息

使用场景:

Topic消息, 开发者如果想要给不同的用户群体(量级一般比较大)发送不同的推送消息, 比如不同的客户端版本、 不同地域、男女等的用户群体,那么使用Topic消息就非常适合;通过给不同的用户群体打不同的标签(topic)来实现, 我们内部还为全量用户打了统一标签, 开发者可以直接使用全量标签发送, 方便快捷;开发者还可以使用topic做交并差集运算,以达到更精细推送的目的;注: 参考第七部分订阅标签。

特别提示:请谨慎使用API发送全量Topic消息,如果因测试等原因误发全量消息,对用户造成干扰,小米推送有权禁止topic消息功能使用;

接口说明:

com.xiaomi.xmpush.server.Sender
方法说明
broadcast(Message message, String topic, int retries)根据topic, 发送消息到指定一组设备上, topic不允许全是空白字符, 长度小于128, 中英文均以一个计算
broadcastAll(Message message, int retries)向所有设备发送消息
multiTopicBroadcast(Message message, List<String> topics, topic_op, int retries)向多个topic广播消息, 支持topic间的交集、并集或差集(如果只有一个topic请用单topic版本)
broadcastHybridAll(message, retries)给快应用发送全量消息。如果应用类型是快应用,须调用此方法。
  • 在multiTopicBroadcast中topic_op - BROADCAST_TOPIC_OP是一个枚举类型, 指定了发送广播消息时多个topic之间的运算关系;
public enum BROADCAST_TOPIC_OP {
UNION, // 并集
INTERSECTION, // 交集
EXCEPT, // 差集
}
  • 例如: topics的列表元素是[A, B, C, D], 则并集结果是A ∪ B ∪ C ∪ D, 交集的结果是A ∩ B ∩ C ∩ D,差集的结果是A - B - C - D

注: 发送topic消息时topic的数量不能超过5;

Demo:

  • 单个topic:
private void sendBroadcast() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
String topic = “testTopic”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
sender.broadcast(message, topic, 3); //根据topic, 发送消息到指定一组设备上
}
  • 多个topic:
private void sendBroadcast() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
List<String> topicList = new ArrayList<>();
String topic1 = “testTopic1”;
String topic2 = “testTopic2”;
topicList.add(topic1);
topicList.add(topic2);
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
//根据topicList做并集运算, 发送消息到指定一组设备上
sender.multiTopicBroadcast(message, topicList, BROADCAST_TOPIC_OP.UNION, 3);
}

6、定时消息

使用场景:

一些日常的定点推送任务或者一些固定时间点的活动, 实时推送难免会费时费力还可能不及时, 这时候就可以提前准备好推送文案, 提交定时消息到我们后台, 到了推送时间指定时间小米推送会准时将消息下发;

接口说明:

com.xiaomi.xmpush.server.Sender

1.构建Message对象时设置timeToSend(long milliseconds)

  • 定时发送消息, timeToSend是以毫秒为单位的时间戳(仅支持七天内的定时消息)

2.构建TargetedMessage对象调用Sender.send(List messages, int retries, long timeToSend)

  • 定时发送一组消息, timeToSend是用自1970年1月1日以来00:00:00.0 UTC时间表示(以毫秒为单位的时间)注: 仅支持七天内的定时消息;
方法说明
checkScheduleJobExist(String msgId)检测定时消息的任务是否存在
deleteScheduleJob(String msgId)根据消息ID删除指定的定时消息
deleteScheduleJobByJobKey(String jobKey)根据jobKey删除指定的定时消息

Demo:

设置Message对象timeToSend属性:

private void sendMessageToAlias() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
String alias = “testAlias”; //alias非空白, 不能包含逗号, 长度小于128
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.timeToSend(System.currentTimeMillis() + 60 * 60 * 1000) // 1个小时后发送
.notifyType(1) // 使用默认提示音提示
.build();
sender.sendToAlias(message, alias, 3); //根据alias, 发送消息到指定设备上
}

构建TargetedMessage:

private void sendMessageToAlias() throws Exception {
Constants.useOfficial();
private Sender sender = new Sender(APP_SECRET_KEY);
String messagePayload = “This is a message”;
String messagePayload1 = “Other This is a message”;
String title = “notification title”;
String title1 = "other notification title"
String description = “notification description”;
String description1 = “other notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
String alias = “testAlias”; //alias非空白, 不能包含逗号, 长度小于128
String alias1 = “testAlias1”; //alias非空白, 不能包含逗号, 长度小于128
TargetedMessage targetedMessage = new TargetedMessage();
targetedMessage.setTarget(TargetedMessage.TARGET_TYPE_ALIAS, alias);
targetedMessage.setMessage(message);

TargetedMessage targetedMessage1 = new TargetedMessage();
targetedMessage1.setTarget(TargetedMessage.TARGET_TYPE_ALIAS, alias1);
Message message1 = new Message.Builder()
.title(title1)
.description(description1).payload(messagePayload1)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1) // 使用默认提示音提示
.build();
targetedMessage1.setMessage(message1);
List<TargetedMessage> messages = new ArrayList<TargetdMessage>();
messages.add(targetMessage);
messages.add(targetMessage1);

//根据TargetedMessage列表, 发送消息到指定设备上, 设置一个小时后发送
sender.send(messages, 3, System.currentTimeMillis() + 60 * 60 * 1000);
}

7、提高发送性能

优先使用batch接口, 如优先使用, 在发消息时, 想要发送一条消息给10000个用户, 开发者A只用10次请求每次发送1000个目标量(如alias, regId等), 而开发者B用了10000次请求每次只发送1个目标量. 很明显, 开发者A的效率远高于开发者B, 其次使用TargetMessage消息对象;发送之前如果能够过滤掉一部分无效设备数(通过消息回执callback接口,设置callback.type=16,获取无效设备), 提高发送性能。

8 、提高送达率

使用消息回执callback接口,设置callback.type=16,过滤用户集中的无效设备;设置合适的ttl(timeToLive消息过期时间)也能一定程度上提高送达率;建议使用通知栏消息;

四、高级功能

构造Message对象时, 调用extra(String key, String value)方法设置key和value, 自定义app的扩展功能;

1、自定义铃声

Android 8.0以下版本

Android 8.0以下版本在发送消息时按此方式设置自定义铃声:

调用Message.Builder类的extra(String key, String value)方法设置铃声uri。
key - 'sound_uri', value - 铃声的uri;
注:铃声只能使用当前app内的资源, uri格式满足 android.resource://your packagename/XXX/XXX
铃声文件放在Android app的raw目录下
只适用于通知栏消息
存储的声音文件需要有扩展名, 但是不要把扩展名写在uri中
private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra(Constants.EXTRA_PARAM_SOUND_URI, "android.resource://" + PACKAGENAME + "/raw/shaking")
.build();
return message;
}

Android 8.0及以上版本

Android 8.0及以上版本的通知效果以channel中的效果为准,发送消息时设置自定义铃声将不会生效,需要在新建channel时设置自定义铃声。

  • 如果您未设置channel,当您发送第一条消息时小米推送会为您创建一个默认channel,该channel的效果会以您发送的这条消息为准。如果您在这条消息中按照上面的方式设置了自定义铃声,该默认channel的铃声效果就会为此自定义铃声效果,以后再更改不会生效。
  • 如果您希望更改自定义铃声,只能新建一个channel,在新建时设置自定义铃声,再使用该channel推送消息。该channel推送的消息都会带有此自定义铃声。

    channel的使用方法请参见“4.4 通知类别(Channel)”。

2、控制APP前台通知弹出

当app在前台时, 默认情况下服务端向客户端发送通知栏消息, app会弹出通知;如果开发者不想让客户端弹出通知, 调用Message.Builder类的extra(String key, String value)方法设置是否弹出通知;key - 'notify_foreground', value - 开启/关闭(1/0);注:只适用于通知栏消息

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra(Constants.EXTRA_PARAM_NOTIFY_FOREGROUND, "0")
.build();
return message;
}

3、预定义通知栏通知的点击行为

3.1、打开当前app对应的Launcher Activity:

调用Message.Builder类的extra(String key, String value)方法将key设置为Constants.EXTRA_PARAM_NOTIFY_EFFECT,value设置为Constants.NOTIFY_LAUNCHER_ACTIVITY;

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_LAUNCHER_ACTIVITY)
.build();
return message;
}

3.2、打开当前app内任意一个Activity

调用Message.Builder类的extra(String key, String value)方法:

key - Constants.EXTRA_PARAM_NOTIFY_EFFECT, value - Constants.NOTIFY_ACTIVITYkey - Constants.EXTRA_PARAM_INTENT_URI, value - 启动Activity的intent uri

获取Intent uri的具体步骤:

在安卓客户端的工程的AndroidManifest.xml里定义一个Activity, 例如下面是一个展示新闻的Activity:
<activity android:name=".NewsActivity"/>
定义一个Intent来启动该Activity, 例如要打开上面定义的NewsActivity可定义Intent为:
intent:#Intent;component=com.yourpackage/.YourActivity;end
例如转换intent为uri:
String uriString = intent.toUri(Intent.URI_INTENT_SCHEME);//该uriString就是Constants.EXTRA_PARAM_INTENT_URI对应的值
返回值:
intent:#Intent;component=com.xiaomi.mipushdemo/.NewsActivity;end

注:

  • 如果你希望在Intent uri中携带数据,注意一个限制:Intent.toUri(Intent.URI_INTENT_SCHEME), 返回的结果不会携带除基本类型(boolean, byte, short, int, long, float, double, String)以外的数据类型, 例如数组和HashMap
  • 获取了Intent uri之后, 在服务端的工程里(需要引用推送服务器SDK), 把uriString 设置进的Message.Builder.extra(),对应的key是Constants.EXTRA_PARAM_INTENT_URI
  • 在生成intent uri时,如果出现点击无法跳转或者Activity的生命周期没有执行时,建议追加flag参数:intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
return new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_ACTIVITY)
.extra(Constants.EXTRA_PARAM_INTENT_URI, "intent:#Intent;component=com.xiaomi.mipushdemo/.NewsActivity;end")
.build();
}

3.3、打开网页

调用Message.Builder类的extra(String key, String value)方法:

key -Constants.EXTRA_PARAM_NOTIFY_EFFECT, value - Constants.NOTIFY_WEBkey - Constants.EXTRA_PARAM_WEB_URI, value - 网页uri

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_WEB)
.extra(Constants.EXTRA_PARAM_WEB_URI, "http://www.xiaomi.com")
.build();
return message;
}

4、通知类别(Channel)

通知类别(Channel)介绍

通知类别(Channel)是 Android O 引入的新功能,旨在解决以下问题:

  • 应用的通知越来越多,给用户造成明显打扰。
  • 但用户只能全局屏蔽这个应用的全部通知,不能屏蔽部分,然后留下对自己有用的。

为了解决这个问题,Android 支持开发者给自己的通知分成若干类,然后允许用户单独屏蔽这个类别的通知。关于通知类别(Channel)的详细介绍请参见《MIUI 10 通知类别 (Channel) 适配》

说明:1. 当前版本暂不支持设置Channel Group。2. 对于MIUI系统,可以不设置Channel,通知也能发出。对于非MIUI系统,是否必须设置Channel取决于你的应用的target API:target API ≥ 26(Android 8.0):必须设置Channel,而且必须给每条通知指定一个 Channel,否则无法发出通知。target API ≤ 25(Android 7.1):可以不设置Channel。在8.0及以上的设备,通知也能正常发出。为确保通知在不同类型的设备上都能正常显示,建议您设置Channel。
使用方法
注意:用户最多可创建8组Channel。各Channel的Channel_id不可重复,Channel_name也不允许同名。Channel一旦创建并发送了带有Channel的消息,设备上即会生成这个Channel,不能删除也不能修改,所以请谨慎创建Channel。
  • 添加新Channel:

参考《小米推送消息分类新规》2.channel申请与接入方法。

  • 发送带有Channel的消息:

构建message时,通过自定义键值对,向extra里传递参数。

key value
 channel_id 发送的消息归属于哪类Channel,这里须设置channel id,必须配。

代码示例:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = "This is a message";
String title = "notification title";
String description = "notification description";
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName("com.xiaomi.mipushdemo")
.notifyType(1) // 使用默认提示音提示
.extra("channel_id", "my_channel_1") // 设置channel id, 必须配
.build();
return message;
}

5、过滤消息

开发者通过调用Message.Builder类的extra(String key, String value)来指定消息的过滤规则(过滤规则能够支持所有的消息)

key - 'locale', value - 可以接收消息设备的语言范围, 用逗号分隔;key - 'locale_not_in', value - 无法收到消息设备的语言范围, 用逗号分隔;

当前设备locale获取方法为Locale.getDefault().toString()

比如, 中国大陆用"zh_CN"表示(详见附录1:语言代码对照表)

key - 'app_version', value - 可以接收消息app版本号, 用逗号分隔;key - 'app_version_not_in', value - 无法收到消息app版本号, 用逗号分隔;

安卓app版本号来源于manifest文件中的"android:versionName"的值 (目前支持MiPush_SDK_Client_2_2_12_sdk.jar及以后的版本)

key - 'connpt', value - 指定在特定的网络环境下才能接到消息, 目前仅支持指定"wifi";

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra("locale","zh_CN")
.build();
return message;
}

6、消息回执

开发者希望消息发送后,推送系统能发送回执给开发者,告知开发者这些消息的送达、点击或发送失败状态。可通过调用Message.Builder类的extra(String key, String value)来指定消息回执规则。

规则列表:

KeyValue含义
callbackString(必填字段), 接收回执的Http接口, 最大长度128字节
callback.paramString(可选字段), 自定义回执参数, 最大长度256字节
callback.typeString(可选字段), 支持以下状态的回执类型:
• 1:消息送达。
• 2:消息点击。
• 16:目标设备无效(设备超过30天未联网;alias/user account/regID不正确;App未注册或已卸载;发送目标的区域有误等原因)。
• 32:客户端调用了disablePush接口禁用Push。
• 64:目标设备不符合过滤条件(包括网络条件不符合、地理位置不符合、App版本不符合、机型不符合、地区语言不符合等)。
• 128:当日推送总量超限或单设备接收超限,限制规则请参见“消息限制说明”。
• 1024:消息有效期TTL过期。
如果不设置,默认类型是送达和点击。

说明:
• 对于当前设备不在线、非小米手机App未启动等原因导致的本次消息无法下发,不返回回执。
• 如果需要返回多种状态的回执,将type数值相加即可。例如:既需要收到送达回执,也需要收到目标设备无效的回执,请将callback.type设置为17(即1+16);如果需要收到消息送达、消息点击和目标设备无效三种状态的回执,请将callback.type设置为19(1+2+16)。

最佳实践:建议针对上述状态中的16类型做过滤处理,减少对这些用户的无效推送。

小米推送服务器每隔1s将已送达、已点击或目标设备无效的消息ID和对应设备的regid或alias通过调用第三方http接口传给开发者(每次调用后, 小米推送服务器会清空这些数据, 下次传给开发者将是新一拨数据)。

注意: 消息的送达回执只支持向regId或alias发送的消息。目标设备无效的回执支持regId、alias和useraccount消息。

服务器callback回调采用post方式,在进行api调用时http请求头会携带以下信息:

Accept:text/html,application/xhtml xml,application/xml

Accept-Charset:UTF-8

Accept-Language:zh-cn

Content-Type:application/x-www-form-urlencoded

请参考,并建议在接入前使用postman或其他工具测试api可用性时也携带以上请求头信息。

request body为data={json格式的字符串},JSON数据格式如下:

{
//type为1表示该消息已送达,targets为送达的设备alias列表
"msgId1":{"param":"param","type": 1, "targets":"alias1,alias2,alias3", "jobkey": "123" ,"barStatus":"Enable","timestamp":1324167800000},

//type为2表示该消息被点击,targets为点击的设备alias列表
"msgId2":{"param":"param","type": 2, "targets":"alias1,alias2,alias3", "jobkey": "456", "barStatus": "Enable", "timestamp": 1524187800000},

//type为16表示目标设备无效,targets为无效的alias列表
"msgId3":{"param":"param","type":16,"targets":"alias1,alias2,alias3","barStatus":"Unknown","timestamp":xxx},

//type为16表示目标设备无效,targets为无效的regId列表,errorCode为1表示无效regId
"msgId4":{"param":"param","type":16,"targets":"regId1,regId2,regId3","barStatus":"Unknown","errorCode":1,"timestamp":xxx,"replaceTarget":{"regId1":"otherRegId"}},

//type为64表示目标设备不符合过滤条件
"msgId5":{"param":"param","type":64,"targets":"regId1,regId2,regId3", "barStatus":"Unknown","timestamp":1572228055643}

//type为128表示当日推送总量超限,或单设备接收超限
"msgId6": {"extra":{"ack":"当日已送达数","quota":"当日可以下发总数"},"type":128,"targets":"alias","timestamp":1585203103625}
"msgId7": {"extra":{"device_acked":"当日单设备已接收数","device_quota":"当日单设备可以下发总数"},"type":128,"targets":"alias","timestamp":1585203104390}

//type为1024表示消息有效期TTL过期
"msgId8": {"param":"param","type":1024,"targets":"regId1,regId2,regId3", "timestamp":1572228055643}
}

格式说明:

外层key代表相应的消息msgId, value是一个JSONObject, 包含了下面的参数值:
param:开发者上传的自定义参数值。
type:消息状态类型(1-送达;2-点击;16-无法找到目标设备;32-客户端调用了disablePush接口禁用Push;64-目标设备不符合过滤条件;128-当日推送总量超限或单设备接收超限;1024-消息有效期TTL过期)。
device_acked:当日单设备已接收数;device_quota:当日单设备可以下发总数;targets:一批alias、regId或useraccount列表,逗号分隔;jobkey:发送消息时设置的jobkey值;barStatus:消息送达时通知栏的状态;Enable:用户允许此app展示通知栏消息; Disable:通知栏消息已关闭; Unknown:通知栏状态未知;timestamp:消息送到设备的时间;replaceTarget:该发送目标无法正常送达,但建议可替换成另外一个新的目标标识以满足该设备的正常推送,其值为键值对;key:该设备原始发送目标标识;value:建议替换成的新的目标标识;errorCode:type为16时返回的无效目标的子类;errorCode:1表示无效regid;errorCode:2表示无效alias;errorCode:3表示无效useraccount。

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = "This is a message";
String title = "notification title";
String description = "notification description";
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra("callback", "http://www.xiaomi.com/msgcallback")
.build();
return message;
}

7、 消息聚合

开发者在发送消息时可以设置消息的组ID(JobKey), 带有相同的组ID的消息会被聚合为一个消息组;

系统支持按照消息组展示消息详情以及计划推送/送达数量/送达曲线等统计信息。另外, 相同JobKey的消息在客户端会进行去重, 只展示其中的第一条。这样如果发送时同JobKey中不慎有重复的设备也不用担心用户会收到重复的通知。

设置消息的组ID的方法是调用Message.Builder类的extra(String key, String value)方法将key设置为“jobkey”;value设置为消息组的ID, 合法的消息组ID由数字([0-9]), 大小写字母([a-zA-Z]), 下划线(_)和中划线(-)组成, 长度不大于20个字符,且不能以下划线(_)开头。

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message with job key.”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra("jobkey", "0115a001")
.build();
return message;
}

8、平滑推送

考虑有开发者服务器资源的问题, 如果推送消息速度过快会导致开发者服务器产生很大的压力, 所以我们提供平滑推送特性,开发者可以设定消息发送速度。

开发者通过调用Message.Builder类的extra(String key, String value)来设置消息发送速度:

key - "flow_control"value - 发送速度(qps)注: 若设置速度低于1000, 则默认3000qps

说明:如果设置了平滑推送,同一个应用同时发送两条消息时会排队发送,需要等第一条消息发送完毕才会发送第二条。

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message with job key.”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra("flow_control", "20000") // 设置平滑推送, 推送速度20000每秒(qps=20000)
.build();
return message;
}

9、only send once消息

一些开发者希望消息只在设备网络在线时下发,不缓存离线消息进行多次下发,以满足及时性需求。为此我们提供了only send once消息功能,开启该功能后消息只会当设备在线时下发一次。

开发者通过调用Message.Builder类的extra(String key, String value)来设置only send once消息:

key - "only_send_once"value - "1"

Demo:

private Message buildMessage() throws Exception {
String PACKAGENAME = "com.xiaomi.mipushdemo";
String messagePayload = “This is a message that will only be send once.”;
String title = “notification title”;
String description = “notification description”;
Message message = new Message.Builder()
.title(title)
.description(description).payload(messagePayload)
.restrictedPackageName(MY_PACKAGE_NAME)
.notifyType(1)
.extra("only_send_once", "1") // 设置消息只发送1次
.build();
return message;
}

五、获取统计数据{Deprecated}

获取统计数据的com.xiaomi.xmpush.server.Stats类已下线,请使用com.xiaomi.xmpush.server.Tracer类获取消息统计数据。

六、追踪消息状态

获取统计数据依赖Tracer类:

com.xiaomi.xmpush.server.Tracer

实例化Tracer:

Tracer(String appSecret) - appSecret是在开发者网站上注册时生成的, 可在应用详情下查看;

方法介绍:

  • 该方法用于获取某条消息或某个时间段的消息的统计数据,如发送量、送达量、点击量等;

1、获取指定消息ID的统计信息

String getMessageStatus(String msgId, int retries)
  • msgId : 发送消息时返回的msgId(参考Sender相关接口)
  • retries : 重试次数
返回值 - json字符串
  • id表示消息ID。
  • resolved表示消息的计划推送数(包含送达数, 以及其他某些原因导致无法下发的目标数)。
  • raw_counter表示https原始请求目标数。
  • invalid_target表示无效目标数(alias无效, user_account无效等)。
  • app_not_register表示app未注册push服务数量。
  • device_condition_unmatch表示设备所处的环境不符合消息设置的条件(例如: 网络环境不匹配, 地域不匹配, app版本不匹配, 机型不匹配等)。 
  • msg_send表示消息的实际下发数。
  • delivered表示消息的送达数(实际下发到客户端的消息数量)。
  • delivery_rate表示送达率(送达数/有效目标数) 。
  • bar_closed表示屏蔽通知栏数。
  • msg_display表示消息的展示数(送达数-屏蔽通知栏数)。
  • click表示消息点击数。
  • click_rate表示消息点击率(点击数/送达数)。
  • create_time表示消息发送时间。
  • time_to_live表示消息有效期。
  • msg_type表示消息发送方式(Common、BatchRegId、Alias、BatchAlias、Topic)。

成功:

{
"result" : "ok",
"description" : "成功",
"data" : {
"data" : "{"id" : XXXX, "delivery_rate" : XXXX, "delivered" : XXXX, "resolved" : XXXX, "raw_counter": XXXX, "invalid_target": XXXX, "app_not_register": XXXX, "device_condition_unmatch": XXXX, "msg_type" : XXXX, "create_time" : XXXX, "time_to_live" : XXXX, "click" : XXXX, "click_rate":XXXX}"
},
”code”:0
}

失败:

{
"result" : "error",
"reason" : "XXXXXXXXX",
"description" : "XXXX",
"code" : XXXX
}

2、获取某个时间段内所有消息的统计数据

String getMessageStatus(long beginTime, long endTime, int retries)
  • beginTime : 开始时间戳(单位: ms)
  • endTime : 结束时间戳(单位: ms)
  • retries : 重试次数
返回值 - json字符串;

注:

  • 如果该时间区间内的消息数大于100条, 则返回最近100条
  • 开始时间和结束时间之间的跨度不能大于7天

成功:

{
"result" : "ok",
"description" : "成功",
"data" : {
"data" : "{"id" : XXXX, "delivery_rate" : XXXX, "delivered" : XXXX, "resolved" : XXXX, "msg_type" : XXXX, "raw_counter": XXXX, "invalid_target": XXXX, "app_not_register": XXXX, "device_condition_unmatch": XXXX, "create_time" : XXXX, "time_to_live" : XXXX, "click" : XXXX, "click_rate":XXXX}"
},
”code”:0
}

失败:

{
"result" : "error",
"reason" : "XXXXXXXXX",
"description" : "XXXX",
"code" : XXXX
}

3、获取指定jobkey消息统计数据

String getMessageGroupStatus(String jobKey, int retries)
  • jobKey : 发送消息时设置(参考4.高级功能), 相同jobkey的消息在客户端只显示一条, 并可以通过jobkey来批量获取消息的统计信息
  • retries : 重试次数
返回值 - json字符串

成功:

{
"result" : "ok",
"description" : "成功",
"data" : {
"data" : "{"id" : XXXX, "delivery_rate" : XXXX, "delivered" : XXXX, "resolved" : XXXX, "msg_type" : XXXX, "create_time" : XXXX, "time_to_live" : XXXX, "click" : XXXX, "click_rate":XXXX}"
},
”code”:0
}

失败:

{
"result" : "error",
"reason" : "XXXXXXXXX",
"description" : "XXXX",
"code" : XXXX
}

Demo:

public void getTrace() throws Exception {
Tracer tracer = new Tracer(APP_SECRET_KEY); // 使用AppSecretKey创建一个Tracer对象
// 获取单条消息的送达状态, 参数:msgId, retry次数
String messageStatus = tracer.getMessageStatus("s1005246409317636237jB", 0);
System.out.println(messageStatus);

// 获取一个时间区间内的消息的送达状态, 参数:开始时间, 结束时间, retry次数
String messageStatus2 = tracer.getMessageStatus(System.currentTimeMillis() - 1000, System.currentTimeMillis(), 3);
System.out.println(messageStatus2);
}

七、订阅标签

使用场景:

标签可以认为是具有某些相同属性的用户集合, 我们可以针对一个标签发送消息。这时,所有订阅了该标签的用户(设备)都会收到该消息(广播消息)。该接口用于将某个设备设置标签(加入集合)或取消标签(从集合中删除)。我们可以通过给不同的用户全体设置不同的标签,已达到精细化推送的目的。

注:每个App单台设备可订阅标签的个数为30个,如果超过了对应上限数,则新订阅的Topic会覆盖最早设置的Topic。

接口说明:

com.xiaomi.xmpush.server.Subscription

实例化Subscription

Subscription(String appSecret) - appSecret是在开发者网站上注册时生成的, 可在应用详情下查看;

API介绍:

subscribeTopic(List regIds, String topic, String category, int retries)• 给一组regid列表订阅标签(regid为应用注册时,服务器返回给客户端的唯一标识): retries表示重试的次数, catergory可以使用null(限制:最多1000个regId);
subscribeTopic(List regIds, String topic, String packageName, String category, int retries)• 给一组regid列表订阅标签(regid为应用注册时,服务器返回给客户端的唯一标识): retries表示重试的次数, catergory可以使用null(限制:最多1000个regId);
• 如果APP有多个包名, 则在订阅标签时, 需要提供一个确切的包名(非多包名情况则不需要), 这时需要使用多包名接口;
subscribeTopic(String regId, String topic, String category, int retries)• 给某个regId订阅标签;
subscribeTopic(String regId, String topic, String packageName, String category, int retries) • 给某个regid订阅标签;
• 如果APP有多个包名, 则在订阅标签时, 需要提供一个确切的包名(非多包名情况则不需要), 这时需要使用多包名接口;
unsubscribeTopic(List regIds, String topic, String category, int retries)• 取消一组regid列表的标签, 限制: 最多1000个regId;
unsubscribeTopic(List regIds, String topic, String packageName, String category, int retries)• 取消一组regid列表的标签, 限制: 最多1000个regId;
• 如果APP有多个包名, 则在订阅标签时, 需要提供一个确切的包名(非多包名情况则不需要), 这时需要使用多包名接口;
unsubscribeTopic(String regId, String topic, String category, int retries)• 取消某个regId标签;
unsubscribeTopic(String regId, String topic, String packageName, String category, int retries)• 取消某个regId标签;
• 如果APP有多个包名, 则在订阅标签时, 需要提供一个确切的包名(非多包名情况则不需要), 这时需要使用多包名接口;
subscribeTopicByAlias(String topic, List aliases, String category, int retries)• 给一组alias列表订阅标签(限制: 最多1000个alias)
subscribeTopicByAlias(String topic, List aliases, String packageName, String category, int retries)• 给一组alias列表订阅标签(限制: 最多1000个alias)
• 如果APP有多个包名, 则在订阅标签时, 需要提供一个确切的包名(非多包名情况则不需要), 这时需要使用多包名接口;
unsubscribeTopicByAlias(String topic, List aliases, String category, int retries)• 取消一组alias列表的标签(限制: 最多1000个alias);
unsubscribeTopicByAlias(String topic, List aliases, String packageName, String category, int retries)• 取消一组alias列表的标签(限制: 最多1000个alias)
• 如果APP有多个包名, 则在订阅标签时, 需要提供一个确切的包名(非多包名情况则不需要), 这时需要使用多包名接口。

八、拉取失效数据{Deprecated}

建议您使用消息回执callback接口(callback.type: 16)进行失效数据过滤。

Feedback接口用于拉取已经失效的regid或alias等数据,该接口已下线。

九、开发者工具

该接口主要用于调查问题时使用, 可以获取某个设备相关的一些信息。

开发者工具依赖DevTools类

com.xiaomi.xmpush.server.DevTools

实例化DevTools

DevTools(String appSecret) - appSecret是在开发者网站上注册时生成的, 可在应用详情下查看

方法介绍:

1、获取某个设备设置的所有alias

String getAliasesOf(String packageName, String regId, int retries)packageName : 应用包名regId : 设备regIdretries : 重试次数返回值如下:

成功:

{
"result" : "ok",
"description" : "成功",
"data" : {
"list" : ["XXXXXX", "XXXXXX", "XXXXXX"]
},
"code" : 0
}

失败:

{
"result" : "error",
"reason" : "XXXXXXXXX",
"description" : "XXXX",
"code" : XXXX
}

2、获取某个设备订阅的所有topic

String getTopicsOf(String packageName, String regId, int retries)packageName : 应用包名regId : 设备regIdretries : 重试次数返回值如下:

成功:

{
"result" : "ok",
"description" : "成功",
"data" : {
"list" : ["XXXXXX", "XXXXXX", "XXXXXX"]
},
"code" : 0
}

失败:

{
"result" : "error",
"reason" : "XXXXXXXXX",
"description" : "XXXX",
"code" : XXXX
}

十、FAQ

名词解释:

traceID是什么?

在调用我们sdk发送消息返回的结果中, 总会有一个traceId字段, 它代表这个操作请求在我们服务端的唯一标识, 所以通过这个traceId就可以定位请求的访问调查相关问题;

messageID是什么?

messageId用来标识一条消息, 通过messageId我们可以调查消息的活动周期;

异常处理

主要是三类情况:

网络问题证书问题代码漏洞;

网络问题

确认网络到api.xmpush.xiaomi.com是否畅通;

证书问题

服务端接口使用https方式, 请确认本地是否导入证书;

代码漏洞

参考Server SDK文档, 确认是否由于代码缺失参数或者调用方法错误;

十一、附录:

附录1:国家地区语言代码(基于 ISO-3166 标准)

语言代码语言_区域描述(中文)语言_区域描述(英文)
af_ZA南非荷兰语_南非Afrikaans_South Africa
am_ET阿姆哈拉语_埃塞俄比亚Amharic_Ethiopia
ar阿拉伯语_allArabic_all
ar_AE阿拉伯语_阿拉伯联合酋长国Arabic_United Arab Emirates
ar_BH阿拉伯语_巴林Arabic_Bahrain
ar_DZ阿拉伯语_阿尔及利亚Arabic_Algeria
ar_EG阿拉伯语_埃及Arabic_Egypt
ar_EG_#u_nu_latn阿拉伯文_埃及#u_nu_latnArabic_Egypt#u_nu_latn
ar_GB阿拉伯语_英国Arabic_United Kingdom
ar_IL阿拉伯语_以色列Arabic_Israel
ar_IQ阿拉伯语_伊拉克Arabic_Iraq
ar_JO阿拉伯语_约旦Arabic_Jordan
ar_KW阿拉伯语_科威特Arabic_Kuwait
ar_LB阿拉伯语_黎巴嫩Arabic_Lebanon
ar_LY阿拉伯语_利比亚Arabic_Libya
ar_MA阿拉伯语_摩洛哥Arabic_Morocco
ar_OM阿拉伯语_阿曼Arabic_Oman
ar_PS阿拉伯语_巴勒斯坦Arabic_Palestine
ar_QA阿拉伯语_卡塔尔Arabic_Qatar
ar_SA阿拉伯语_沙特阿拉伯Arabic_Saudi Arabia
ar_SD阿拉伯语_苏丹Arabic_Sudan
ar_SY阿拉伯语_叙利亚Arabic_Syrian
ar_TN阿拉伯语_突尼斯Arabic_Tunisia
ar_US阿拉伯语_美国Arabic_United States
ar_YE阿拉伯语_也门Arabic_Yemen
arn_CL马普切语_智利Mapuche_Chile
as_IN阿萨姆语_印度Assamese_India
az_AZ阿塞拜疆语_阿塞拜疆Azerbaijani_Azerbaijani
az_AZ_#Latn阿塞拜疆语_阿塞拜疆#LatnAzerbaijani_Azerbaijan#Latn
az_Cyrl阿塞拜疆语_西里尔文Azerbaijani_Cyrillic
az_Latn阿塞拜疆语_拉丁文Azerbaijani_Latin
ba_RU巴什基尔语_俄罗斯Bashkir_Russia
be_BY白俄罗斯语_白俄罗斯Belarusian_Belarus
bg_BD孟加拉语_孟加拉Bengali_Bangladesh
bg_BG保加利亚语_保加利亚Bulgarian_Bulgarian
bg_IN孟加拉语_印度Bengali_India
bn孟加拉语_allBengali_all
bn_BD孟加拉语 (孟加拉)_孟加拉国Bengali (Bangladesh)_Bangladesh
bn_IN孟加拉语 (印度)_印度Bengali (India)_India
bo_CN藏语_中国Tibetan_China
br_FR布列塔尼语_法国Breton_France
bs_BA波斯尼亚语_波黑Bosnian_Bosnian
bs_Cyrl波斯尼亚语_西里尔文Bosnian_Cyrillic
bs_Latn波斯尼亚语_拉丁文Bosnian_Latin
ca_ES加泰罗尼亚语_西班牙Catalan_Spain
co_FR科西嘉语_法国Corsican_France
cs_CZ捷克语_捷克共和国Czech_Czech Republic
cy_GB威尔士语_英国Welsh_United Kingdom
da_DK丹麦语_丹麦Danish_Denmark
de德语_allGerman_all
de_AT德语_奥地利German_Austria
de_CH德语_瑞士German_Switzerland
de_DE德语_德国_Dictionary排序German_Germany_Dictionary sort
de_LI德语_列支敦士登German_Liechtenstein
de_LU德语_卢森堡German_Luxembourg
dsb_DE下索布语_德语Lower Sorbian_German
dv_MF迪维西语_马尔代夫Divisian_Maldives
el_GR希腊语_希腊Greek_Greek
en英语_allEnglish_all
en_029英语_加勒比(en_029)English_Caribbean (en_029)
en_AE英语_阿拉伯联合酋长国English_United Arab Emirates
en_AI英语_安圭拉English_Anguilla
en_AS英语_美属萨摩亚English_American Samoa
en_AT英语_奥地利English_Austria
en_AU英语_澳大利亚English_Australia
en_BD英语_孟加拉国English_Bangladesh
en_BE英语_比利时English_Belgium
en_BG英语_保加利亚English_Bulgarian
en_BR英语_巴西English_Brazil
en_BZ英语_伯利兹English_Belize
en_CA英语_加拿大English_Canada
en_CB英语_加勒比(en_CB)English_Caribbean (en_CB)
en_CH英语_瑞士English_Switzerland
en_CN英语_中国English_China
en_EE英语_爱沙尼亚English_Estonia
en_EG英语_埃及English_Egypt
en_ES英语_西班牙English_Spain
en_FI英语_芬兰English_Finland
en_FR英语_法国English_France
en_GB英语_英国English_UK
en_GR英语_希腊English_Greek
en_HK英语_中国香港English_Hong Kong, China
en_HU英语_匈牙利English_California
en_ID英语_印尼English_Indonesia
en_IE英语_爱尔兰English_Ireland
en_IL英语_以色列English_Israel
en_IN英语_印度English_India
en_IO英语_英属印度洋领地English_British Indian Ocean Territory
en_IQ英语_伊拉克English_Iraq
en_IR英语_伊朗English_Iran
en_JM英语_牙买加English_Jamaica
en_JP英语_日本English_Japan
en_KE英语_肯尼亚English_Kenya
en_KH英语_柬埔寨English_Cambodia
en_KR英语_韩国English_Korea
en_KW英语_科威特English_Kuwait
en_LT英语_立陶宛English_Lithuania
en_LV英语_拉脱维亚English_Latvia
en_MM英语_缅甸English_Myanmar
en_MO英语_中国澳门English_Macau, China
en_MX英语_墨西哥English_Mexico
en_MY英语_马来西亚English_Malaysia
en_NG英语_尼日利亚English_Nigeria
en_NL英语_荷兰English_Netherlands
en_NO英语_挪威English_Norway
en_NZ英语_新西兰English_New Zealand
en_OC英语_OCEnglish_OC
en_PH英语_菲律宾English_Philippines
en_PK英语_巴基斯坦English_Pakistan
en_PL英语_波兰English_Poland
en_QA英语_卡塔尔English_Qatar
en_RO英语_罗马尼亚English_Montreal
en_RU英语_俄罗斯English_Russian
en_SA英语_沙特阿拉伯English_Saudi Arabia
en_SE英语_瑞典English_Sweden
en_SG英语_新加坡English_Singapore
en_SI英语_斯洛文尼亚English_Slovenia
en_TH英语_泰国English_Thailand
en_TR英语_土耳其English_Turkish
en_TT英语_特立尼达岛English_Trinidad
en_UA英语_乌克兰English_Ukraine
en_US英语_美国English_United States
en_VN英语_越南English_Vietnam
en_ZA英语_南非English_South Africa
en_ZG英语_ZGEnglish_ZG
en_ZW英语_津巴布韦English_Zimbabwe
es西班牙语_allSpanish_all
es_419西班牙语_419Spanish_419
es_AR西班牙语_阿根廷Spanish_Argentina
es_BO西班牙语_玻利维亚Spanish_Bolivia
es_CL西班牙语_智利Spanish_Chile
es_CO西班牙语_哥伦比亚Spanish_Colombia
es_CR西班牙语_哥斯达黎加Spanish_Costa Rica
es_CU西班牙语_古巴Spanish_Cuba
es_DO西班牙语_多米尼加共和国Spanish_Dominican Republic
es_EA西班牙语_休达及美利拉Spanish _ Ceuta and Melilla
es_EC西班牙语_厄瓜多尔Spanish_Ecuador
es_ES西班牙语_西班牙 (现代)Spanish_Spain (modern)
es_GT西班牙语_危地马拉Spanish_Guatemala
es_HN西班牙语_洪都拉斯Spanish_Honduras
es_IC西班牙语_ 加那利群岛Spanish_Canary Islands
es_MX西班牙语_墨西哥Spanish_Mexico
es_NI西班牙语_尼加拉瓜Spanish_Nicaragua
es_PA西班牙语_巴拿马Spanish_Panama
es_PE西班牙语_秘鲁Spanish_Peru
es_PR西班牙语_波多黎各Spanish_Puerto Rico
es_PY西班牙语_巴拉圭Spanish_Paraguay
es_SV西班牙语_萨尔瓦多Spanish_El Salvador
es_US西班牙语_美国Spanish_United States
es_UY西班牙语_乌拉圭Spanish_Uruguay
es_VE西班牙语_委内瑞拉Spanish_Venezuela
et_EE爱沙尼亚语_爱沙尼亚Estonian_Estonian
eu_ES巴斯克语_西班牙Basque_Spain
fa_AF波斯语_阿富汗Persian_Afghanistan
fa_FA波斯语_波斯Persian_Persian
fa_IR波斯语_伊朗Persian_Iran
fa_IR_#u_nu_latn波斯语_伊朗#u_nu_latnPersian_Iran#u_nu_latn
fa_IR_LNum波斯语_伊朗_拉丁文Persian_Iranian_Latin
fi_FI芬兰语_芬兰Finnish_Finland
fil_PH菲律宾语_菲律宾Filipino_Philippines
fr法语_allFrench_all
fr_BE法语_比利时French_Belgium
fr_BF法语_布基纳法索French_Burkina Faso
fr_CA法语_加拿大French_Canada
fr_CD法语_刚果民主共和国French_Democratic Republic of the Congo
fr_CH法语_瑞士French_Switzerland
fr_CI法语_科特迪瓦French_Côte d'Ivoire
fr_CM法语_喀麦隆French_Cameroon
fr_DZ法语_阿尔及利亚French_Algeria
fr_FR法语_法国French_France
fr_LU法语_卢森堡French_Luxembourg
fr_MA法语_摩洛哥French_Morocco
fr_SN法语_塞内加尔French_Senegal
fr_TN法语_突尼斯French_Tunisia
gd_IE盖尔语_爱尔兰Gaelic_Ireland
gl_ES加利西亚_西班牙Galicia_Spain
gu卡纳达语_allKannada_all
gu_IN古吉拉特语_印度Gujarati_India
ha_NG豪萨语_尼日利亚Hausa_Nigeria
he_IL希伯来_以色列Hebrew_Israel(he_IL)
hi印地文_allHindi_all
hi_IN印地文_印度Hindi_India
hr_BA克罗地亚语_波黑Croatian_Bosnia and Herzegovina
hr_HR克罗地亚语_克罗地亚Croatian_Croatia
hu_HU匈牙利Hungary
hy_AM亚美尼亚语_亚美尼亚Armenian_Armenian
id_ID印尼语_印尼Indonesian_Indonesia(id_ID)
in印度尼西亚语_allIndonesian_all
in_ID印尼语_印度尼西亚Indonesian_Indonesia(in_ID)
it_CH意大利语_瑞士Italian_Switzerland
it_IT意大利语_意大利Italian_Italy
iw_IL希伯来语_以色列Hebrew_Israel
ja日语_allJapanese_all
ja_CN日语_中国Japanese_China
ja_JP日语_日本Japanese_Japan
ka_GE格鲁吉亚语_格鲁吉亚Georgian_Georgian
kk_KZ哈萨克语_哈萨克斯坦Kazakh_Kazakhstan
km_KH高棉 (柬埔寨语)_柬埔寨Khmer (Cambodian)_Cambodia
kn古吉拉特语_allGujarati_all
kn_IN卡纳达语_印度Kannada_India
ko朝鲜语_allKorean_all
ko_CN韩语_中国Korean_China
ko_KR韩语_韩国Korean_Korea
ko_US韩语_美国Korean_United States
lo_LA老挝语_老挝Lao_Lao
lt立陶宛语_allLithuanian_all
lt_LT立陶宛_立陶宛Lithuania_Lithuania
lv拉脱维亚语_allLatvian_all
lv_LV拉脱维亚语_拉脱维亚Latvian_Latvia
mk马其顿_allMacedonia_all
mk_MK马其顿_马其顿Macedonia_Macedonia
ml马拉雅拉姆语_allMalayalam_all
ml_IN马拉雅拉姆语_印度Malayalam_India
mn_MN蒙古语 _蒙古Mongolian _ Mongolia
mr马拉地语_allMarathi_all
mr_IN马拉地语_印度Marathi_India
ms_BN马来语_文莱Malay_Brunei
ms_MY马来语_马来西亚Malay_Malaysia
mt马耳他语_allMaltese_all
mt_MT马耳他语_马耳他Maltese_Malta
mx_MX缅甸语_墨西哥Burmese_Mexico
my_MM缅甸语_缅甸Burmese_Myanmar
my_ZG缅甸语_ZGBurmese_ZG
nb_NO伯克梅尔语_挪威Birkmel _ Norway
ne_IN尼泊尔语(印度)_印度Nepali (India)_India
ne_NP尼泊尔语(尼泊尔)_尼泊尔Nepali (Nepal)_Nepal
nl_BE荷兰语_比利时Dutch_Belgium
nl_NL荷兰语_荷兰Dutch_Netherlands
nn_NO尼诺斯克语_挪威Nynorsk_Norway
or奥里雅语_allOriya_all
or_IN奥利亚语_印度Oriya_India
pa旁遮普_allPunjab_all
pa_IN旁遮普_印度Punjab_India
pa_IN_#Guru旁遮普_印度#GuruPunjab_India#Guru
pl波兰语_allPolish_all
pl_PL菲律宾Philippines
pt_AO葡萄牙语_安哥拉Portuguese_Angola
pt_br葡萄牙语_巴西Portuguese_Brazil
pt_CV葡萄牙语_佛得角Portuguese_Cape Verde
pt_GW葡萄牙语_几内亚比绍Portuguese_Guinea Bissau
pt_MZ葡萄牙语_莫桑比克Portuguese_Mozambique
pt_PT葡萄牙语_葡萄牙Portuguese_Portugal
rm罗曼什语_allRomansh_all
ro罗马尼亚语_罗马尼亚Romanian_Romania
ro_MD罗马尼亚_摩尔多瓦Romania_Moldova
ro_mo罗马尼亚语_摩尔多瓦共和国Romanian_Republic of Moldova
ro_RO罗马尼亚Romania
ru俄语_allRussian_all
ru_IL俄语_以色列Russian_Israel
ru_KG俄语_吉尔吉斯坦Russian_Kyrgyzstan
ru_KZ俄语_哈萨克斯坦Russian_Kazakhstan
ru_MD俄语_摩尔多瓦Russian_Moldova
ru_mo俄语_摩尔多瓦共和国Russian_Republic of Moldova
ru_RU俄罗斯Russia
sa梵文_allSanskrit_all
sb索布语_allSorbian_all
sk斯洛伐克语_allSlovak_all
sk_SK斯洛伐克语Slovak
sl斯洛文尼亚语_allSlovenian_all
sl_SI斯洛文尼亚语_斯洛文尼亚Slovenian_Slovenian
sq_AL阿尔巴尼亚语_阿尔巴尼亚Albanian_Albanian
sr_ME_#Cyrl塞尔维亚语_黑山_西里尔文Serbian_Montenegro_Cyrillic
sr_RS塞尔维亚语_塞尔维亚Serbian_Serbia
sr_RS_#Cyrl塞尔维亚语_塞尔维亚#CyrlSerbian_Serbian#Cyrl
sr_RS_#Latn塞尔维亚语_塞尔维亚#LatnSerbian_Serbian#Latn
sr_sp_Cyrl塞尔维亚语_西里尔字母Serbian _ Cyrillic
sr_sp_Latn塞尔维亚语_拉丁文Serbian_Latin
st南部索托语_allSouthern Soto_all
sv_FI瑞典语_芬兰Swedish_Finland
sv_SE瑞典语_瑞典Swedish_Sweden
sw斯瓦希里语_allSwahili_all
ta泰米尔语_allTamil_all
ta_IN泰米尔语_印度Tamil_India
te泰卢固语_allTelugu_all
te_IN泰卢固语_印度Telugu_India
th泰语_allThai_all
th_GB泰语_英国Thai_UK
th_TH泰语_泰国Thai_Thailand
th_US泰语_美国Thai_United States
tn茨瓦纳语_allTswana_all
tr土耳其语_allTurkish_all
tr_CY土耳其_塞浦路斯Turkey_Cyprus
tr_TR土耳其Turkey
ts特松加语_allTsonga_all
tt鞑靼语_allTatar_all
uk乌克兰语_allUkrainian_all
uk_UA乌克兰Ukraine
undundund
ur乌都语_allUdo_all
ur_IN乌尔都语_印度Urdu_India
ur_PK乌尔都语(巴基斯坦)_巴基斯坦Urdu (Pakistan)_Pakistan
uz_UZ乌兹别克语_乌兹别克斯坦Uzbek_Uzbekistan
uz_UZ_#Latn乌兹别克语_乌兹别克斯坦#LatnUzbek_Uzbekistan#Latn
uz_UZ_Cyrl乌兹别克语_西里尔文Uzbek_Cyrillic
uz_UZ_Latn乌兹别克语_拉丁文Uzbek_Latin
vi越南语_allVietnamese_all
vi_US越南语_美国Vietnamese_United States
vi_VN越南语_越南Vietnamese_Vietnamese
xh班图语_allBantu_all
yi意第绪语_allYiddish_all
zh中文_allChinese_all
zh_AE_#Hans中文_阿拉伯联合酋长国_#HansChinese_United Arab Emirates_#Hans
zh_AU_#Hans中文_澳大利亚_#HansChinese_Australia_#Hans
zh_CA_#Hans中文_加拿大_#HansChinese_Canada_#Hans
zh_CN中文_中国大陆_拼音排序Chinese_Mainland China_Pinyin Ranking
zh_CN_#Hans中文_中国#HansChinese_China #Hans
zh_CN_#Hant中文_中国_#HantChinese_中国_#Hant
zh_DE_#Hans中文_德国_#HansChinese_Germany_#Hans
zh_ES_#Hans中文_西班牙_#HansChinese_Spain_#Hans
zh_FR_#Hans中文_法国_#HansChinese_France_#Hans
zh_GB_#Hans中文_英国_#HansChinese_UK_#Hans
zh_Han_AU中文_Han_澳大利亚Chinese_Han_Australia
zh_Hans中文_简体Chinese_Simplified
zh_Hans_AU中文_简体_澳大利亚Chinese_Simplified_Australia
zh_Hans_CA中文_简体_加拿大Chinese_Simplified_Canada
zh_Hans_CN中文_简体_中国Chinese_Simplified_China
zh_Hans_DE中文_简体_德国Chinese_Simplified_Germany
zh_Hans_ES中文_简体_西班牙Chinese_Simplified_Spain
zh_Hans_FR中文_简体_法国Chinese_Simplified_France
zh_Hans_GB中文_简体_英国Chinese_Simplified_UK
zh_Hans_HK中文_简体_中国香港Chinese_Simplified_Hong Kong, China
zh_Hans_IT中文_简体_意大利Chinese_Simplified_Italy
zh_Hans_JP中文_简体_日本Chinese_Simplified_Japan
zh_Hans_KR中文_简体_韩国Chinese_Simplified_South Korea
zh_Hans_MO中文_简体_中国澳门Chinese_Simplified_Macao, China
zh_Hans_MY中文_简体_马来西亚Chinese_Simplified_Malaysia
zh_Hans_NZ中文_简体_新西兰Chinese_Simplified_New Zealand
zh_Hans_PH中文_简体_菲律宾Chinese_Simplified_Filipino
zh_Hans_SG中文_简体_新加坡Chinese_Simplified_Singapore
zh_Hans_TH中文_简体_泰国Chinese_Simplified_Thailand
zh_Hans_TW中文_简体_台湾Chinese_Simplified_Taiwan
zh_Hans_US中文_简体_美国Chinese_Simplified_United States
zh_Hant中文_繁体Chinese_Traditional
zh_Hant_AU中文_繁体_澳大利亚Chinese_Traditional_Australia
zh_Hant_CN中文_繁体_中国Chinese_Traditional_China
zh_Hant_HK中文_繁体_中国香港Chinese_Traditional_Hong Kong, China
zh_Hant_JP中文_繁体_日本Chinese_Traditional_Japan
zh_Hant_MO中文_繁体_中国澳门Chinese_Traditional_Macao, China
zh_Hant_TW中文_繁体_台湾Chinese_Traditional_Taiwan
zh_Hant_US中文_繁体_美国Chinese_Traditional_United States
zh_HK中文_香港特别行政区Chinese_Hong Kong Special Administrative Region
zh_HK_#Hans中文_中国香港_#HansChinese_Hong Kong, China_#Hans
zh_HK_#Hant中文_中国香港_#HantChinese_Hong Kong, China_#Hant
zh_IT_#Hans中文_意大利_#HansChinese_Italian_#Hans
zh_JP_#Hans中文_日本_#HansChinese_日本_#Hans
zh_MM_#Hans中文_缅甸_#HansChinese_Myanmar_#Hans
zh_MO中文_澳门特别行政区Chinese_Macao Special Administrative Region
zh_MO_#Hans中文_中国澳门_#HansChinese_Macau_China_#Hans
zh_MO_#Hant中文_中国澳门_#HantChinese_Macau_China_#Hant
zh_MY_#Hans中文_马来西亚_#HansChinese_Malaysia_#Hans
zh_MY_#Hant中文_马来西亚_#HantChinese_Malaysia_#Hant
zh_NZ_#Hans中文_新西兰_#HansChinese_New Zealand_#Hans
zh_PA_#Hans中文_巴拿马_#简体(zh_PA_#Hans)Chinese_Panama_#Simplified
zh_PH_#Hans中文_菲律宾_#HansChinese_Philippines_#Hans
zh_RU_#Hans中文_俄罗斯_#HansChinese_Russian_#Hans
zh_SG中文_新加坡Chinese_Singapore
zh_SG_#Hans中文_新加坡_#HansChinese_Singapore_#Hans
zh_TH_#Hans中文_泰国_#HansChinese_Thailand_#Hans
zh_TW中文_台湾地区Chinese_Taiwan
zh_TW_#Hans中文_台湾_#HansChinese_Taiwan_#Hans
zh_TW_#Hant中文_台湾#HantChinese_Taiwan#Hant
zh_US_#Hans中文_美国_#HansChinese_US_#Hans
zh_VN_#Hans中文_越南_#HansChinese_Vietnam_#Hans
zh_ZG_#Hans中文_ZG_#HansChinese_ZG_#Hans
zu祖鲁语_allZulu_all

附录2:品牌表

品牌model
小米xiaomi
三星samsung
华为huawei
中兴zte
中兴努比亚nubia
酷派coolpad
联想lenovo
魅族meizu
HTChtc
OPPOoppo
VIVOvivo
摩托罗拉motorola
索尼sony
LGlg
金立jinli
天语tianyu
诺基亚nokia
美图秀秀meitu
谷歌google
TCLtcl
锤子手机chuizi
一加手机1+
中国移动china mobile
昂达angda
邦华banghua
波导bird
长虹changhong
大可乐dakele
朵唯doov
海尔haier
海信hisense
康佳konka
酷比魔方kubimofang
米歌mige
欧博信ouboxin
欧新ouxin
飞利浦philip
维图voto
小辣椒xiaolajiao
夏新xiaxin
亿通yitong
语信yuxin

小米推送技术常见问题解答

上一篇:
下一篇: