MIUI 10 通知栏快捷开关 (Quick Settings Tile) 适配说明

1. 什么是通知栏快捷开关 (Quick Settings Tile)

快捷开关 (Quick Settings Tile) 是 Android 7.0 引入的新功能,支持开发者自定义通知栏快捷开关。任何开发者都可以注册快捷开关,然后会出现在开关编辑面板中,如下图:

 为了放下更多的快捷开关,MIUI 10 开关面板支持左右横滑,也不限制快捷开关的数量。用户也可以自由排序这些开关,比如放在最后或放在最前面,如下图:

点击开关的行为,由开方者自行定义,可以直接开启某功能,或者直接跳转到某一页面,如下图:

2. 如何适配通知栏快捷开关 (Quick Settings Tile)

可以参考官方文档中以下两章的内容:

  1. Tile: https://developer.android.com/reference/android/service/quicksettings/Tile
  2. TileService: https://developer.android.com/reference/android/service/quicksettings/TileService

如果需要完整的讲解,可以参考这篇谷歌 Framework 工程师的博客:Quick Settings Tiles on Android 7.0(可能需要翻墙),现摘录重点如下:

2.1. 在 manifest 中声明 TileService ,示例如下

<service
  android:name=".AwesomeTileService"
 
  //快捷开关的图标
  android:icon="@drawable/ic_tile_default"
 
  //快捷开关的名称
  android:label="@string/tile_name"
  android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
  <intent-filter>
    <action
      android:name="android.service.quicksettings.action.QS_TILE"/>
  </intent-filter>
</service>

2.2. 准备规范的快捷开关图标

如上所述,android:icon 是显示在通知栏的图标,有以下要求:

  • 要求是 vector drawable 矢量格式(注意是矢量格式)。
  • 图形必须是纯白色,透明背景,图形和功能有明显联系。
  • 大小为 24 x 24 dp (注意单位不是 px)。

快捷开关示例(矢量 + 纯白 + 透明背景):

2.3. 注意以下交互细节

  • 点击:开发者需要确认点击行为是什么,同时确认开关是否有二态变化,如果有,需要准备新的 vector drawable
  • 长按:长按快捷开关,默认会跳转到应用信息页。但开发者可以指定跳转的落地页,通过给 ACTION_QS_TILE_PREFERENCES 增加一个 <intent-filter> 来实现。
  • 自动更新:系统支持开发者更新开关的 UI,一个应用场景是“天气刷新”。开发者视业务需求酌情使用吧。

3. FAQ

3.1. 第三方快捷开关,默认会出现在第一屏吗

不会。第三方快捷开关,默认都会是未添加的状态,只有用户主动添加,才会出现在快捷开关面板中。

3.2. 这个功能对 Android 版本有依赖吗

有,必须是 Android 7.0 及以上的设备。

3.3. 这个功能 MIUI 9 支持吗

不支持,是 MIUI 10 新增的功能。

3.4. 这个功能区分国内版和海外版吗

不区分,只要是 MIUI 10 就支持。

3.5. 如何判断 MIUI 版本

有以下方法:

android.os.SystemProperties.get("ro.miui.ui.version.code", "7");// 如果返回值是「8」,就是 MIUI 10

android.os.SystemProperties.get("ro.miui.ui.version.name", "");// 如果返回值是「V10」,就是 MIUI 10

3.6. 如何测试

升级到  MIUI 10 最新开发版即可,支持的机型和下载链接如下(找到对应机型的最新开发版):

小米MIUI 10 通知类别 (Channel) 适配说明

小米MIUI 10 通知类别 (Channel) 适配说明

1. 什么是通知类别 / Channel

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

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

为了解决这个问题,Android 要求开发者给自己的通知分成若干类,然后允许用户单独屏蔽这个类别的通知。以爱奇艺(v9.5.0) 为例,将通知分成了 4 种 Channel,3 个 Channel Group,如下图:

简单解释一下:

  • Channel:实际的通知类别,爱奇艺分成了4类通知。
  • Channel Group:一组 channel,仅用于做分组区分,没有更多的逻辑。
  • 每个通知类别的权限互相独立,互不影响。例如,通知屏蔽了爱奇艺的「新群聊消息」类通知,「常规推送」类通知依然可以发出来。

Android 已将 Channel 的逻辑纳入 Android Compatibility Definition Document (CDD) 中,意味着所有 Android 厂商都必须支持。因此 MIUI 10 也将兼容和支持相关逻辑。

2.如何适配通知类别(Channel)

官方文档已有非常详细的描述,适配步骤不再赘述,详见 https://developer.android.com/training/notify-user/channels 。

有几点值得注意:

2.1. 不要滥设类别,建议控制在 7 类以内

2.2. Channel 的名字要有可读性、有具体含义,同时避免名字重复

2.3. 如果 Channel 名字不好理解,可以使用 setDescription 来补充说明 Channel 的含义

2.4. 最好不要只设一个 Channel,那样就没有设置 Channel 的意义了。以猫眼为例,可以考虑将通知拆成多个 Channel,如下图

3. FAQ

3.1. 一定要适配通知 Channel 吗

取决于你的应用的 target API:

  • target API ≥ 26(Android 8.0):必须适配,而且必须给每条通知指定一个 Channel,否则无法发出通知。
  • target API ≤ 25(Android 7.1):可以不适配。在8.0及以上的设备,通知也能正常发出。

3.2. 一定要有通知 Channel Group 吗

不是必须的。没必要强行设置 Channel Group,应该视自己的业务需求而定。

3.3. 适配 Channel 后,在 Android 8.0 以前的设备会怎么表现

Android 8.0 以前的设备,会完全无视这个功能,因此不会带来任何兼容性问题。

3.4. 创建好 Channel 后,在代码里修改其配置,为什么会不生效

这个是 Android 对此功能增加的限制:当 Channel 已经存在时,后面的 createNotificationChannel 方法仅能更新其 name/description,以及对 importance 进行降级,其余配置均无法更新。先删除旧的 Channel,再创建新的 Channel 也无法实现对其 importance 的升级。

相关逻辑在 com/android/server/notificaton/RankingHelper.java:

@Override
public void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
        boolean fromTargetApp) {
//......
    NotificationChannel existing = r.channels.get(channel.getId());
    // Keep most of the existing settings
    if (existing != null && fromTargetApp) { // 如果已经存在同channel-id的Channel
//......
        existing.setName(channel.getName().toString()); // 则更新name和description
        existing.setDescription(channel.getDescription());
        existing.setBlockableSystem(channel.isBlockableSystem());
 
        // Apps are allowed to downgrade channel importance if the user has not changed any
        // fields on this channel yet.
        if (existing.getUserLockedFields() == 0 &&  // 并且仅当更新的importance小于原来设置的值时才更新importance
                channel.getImportance() < existing.getImportance()) {
            existing.setImportance(channel.getImportance());
        }
 
        updateConfig();
        return;
    }
//......
}


3.5. 如何判断 MIUI 版本

有以下方法:

android.os.SystemProperties.get("ro.miui.ui.version.code", "7");// 如果返回值是「8」,就是 MIUI 10

android.os.SystemProperties.get("ro.miui.ui.version.name", "");// 如果返回值是「V10」,就是 MIUI 10

3.6. 如何测试

升级到  MIUI 10 最新开发版即可,支持的机型和下载链接如下(找到对应机型的最新开发版):

小米手机MIUI 10 媒体通知适配说明

小米手机MIUI 10 媒体通知适配说明

1.媒体通知是什么

媒体通知(或称 Media template / Media style)是 Android 标准通知样式的一种,自 API 21(Android 5.0) 引入,方便用户直接控制媒体内容,常见于音乐类、广播类应用。

MIUI 10 完全兼容该通知样式,并调整了视觉风格,以符合系统风格,如下图(第一条通知)。

2. 为什么要用系统的媒体通知?

音乐类应用已经都有自己的「自定义通知」可以控制音乐,那为什么还要用系统的媒体通知?

调用系统的媒体通知,系统就能做针对性的优化,如:

  • 正在播放的媒体通知默认置顶 + 默认展开为大视图。
  • 正在播放的媒体通知默认会出现在锁屏上(置顶+大视图)。

这些都能让内容更充分地曝光,也有利于提升用户体验。

注:不同于原生 Android O 允许所有通知出现在锁屏上,MIUI 限制了出现在锁屏的通知类型,以减少用户打扰。如果需要出现在锁屏上,需要前往设置 – 通知和状态栏 – 通知管理,找到对应应用,开启‘’锁屏通知‘’。

3. 如何适配系统媒体通知

3.1 媒体通知的两种视图

媒体通知有两种视图,分别称为:

  • 标准视图 / compact view:标准的通知高度,最多显示3个按钮(actions)。
  • 大视图 / expanded view:面积更大,最多显示5个按钮。

3.2 适配媒体通知

MIUI 10的媒体通知,基于 Android O,以下是几个重要的接口:

媒体通知代码示例如下:

Notification = new Notification.Builder()
    .setContentTitle("Havana(feat.Young Thug")
    .setContentText("Camila Cabello - Havana")
    .setSmallIcon(mySmallIcon)
    .setLargeIcon(album)
    .addAction(previousAction)
    .addAction(playAction)
    .addAction(nextAction)
    .addAction(playlistAction)
    .addAction(favoriteAction)
    .setOngoing(true)
    .setStyle(newNotification.MediaStyle()
        .setShowActionsInCompactView(1,2,3)
        .setMediaSession(mySession)))
    .build();

详细接口说明见官方文档:https://developer.android.com/reference/android/app/Notification.MediaStyle

不过,以下接口在 MIUI 10 无法生效:

以上接口都可能会产生不协调的颜色,故暂时屏蔽。

4. FAQ

4.1. 如何判断 MIUI 版本

有以下方法:

android.os.SystemProperties.get("ro.miui.ui.version.code", "7");// 如果返回值是「8」,就是 MIUI 10

android.os.SystemProperties.get("ro.miui.ui.version.name", "");// 如果返回值是「V10」,就是 MIUI 10

4.2. 只有 MIUI 10 支持媒体通知吗

其实 MIUI 9 也支持媒体通知,但因为没有做好优化。所以,可以大体认为「只有 MIUI 10 支持媒体通知」,含国内版和国际版,且样式和逻辑统一。

4.3. 只要是 MIUI 10 就支持媒体通知吗?

是的。因为 Android 原生从 API 21 (android 5.0)就支持媒体通知了,详见 https://developer.android.com/reference/android/app/Notification.MediaStyle。而 MIUI 10 最低是兼容到 Android 6.0,所以只要是 MIUI 10就支持媒体通知。

4.4. MIUI 10 会禁用自定义通知吗

不会。但系统无法识别自定义通知的具体内容,只会当成普通通知处理。

4.5. MIUI 10 媒体通知的样式以后会变化吗

有可能。主要取决于:

  • Android 增加新的接口:我们后续会尽力兼容新的接口,并以此调整样式。
  • 业务需求和用户反馈。

4.6. MIUI 以前自己做的锁屏音乐界面还有用吗

在 MIUI 10 上没有用了。由于那个页面的实现方式有较多问题,因此我们在 MIUI 10 上弃用了,改由在锁屏上显示媒体通知,来实现锁屏音乐控制的需求。

4.7. 第三方应用自己做的锁屏页面(如音乐类或运动类的覆盖式)还能用吗?

可以继续使用,MIUI 10 没有限制这个能力(不过前提是开启了「锁屏显示」的权限)。但我们不建议开发者做这么一个覆盖式的页面,因为用户体验很差,还是希望能够用媒体通知替代。

4.8. 如何测试

升级到  MIUI 10 最新开发版即可,支持的机型和下载链接如下(找到对应机型的最新开发版):

小米手机MIUI 9 通知过滤适配说明

小米手机MIUI 9 通知过滤适配说明

自 MIUI 9 开始,我们新增了通知过滤的功能,接下来为大家说明该功能,以解答大家的疑问。

1. 这是什么功能

通知过滤是指通过分析用户对通知的操作,来个性化地确定通知的重要与不重要,然后将不重要的通知收纳进一个统一的页面。具体交互样式如下(MIUI 10),点击不重要通知可直接查看所有被折叠的通知。

2. 如何判断重要与否

评分模型会通过多个维度判断通知重要与否,包括但不限于:

  • 通知的文本:即标题(title) 和描述(description)
  • 该应用的通知在该设备上的历史点击率
  • 用户的属性(如年龄、性别、地域等)

评分模型会综合各个维度对特定用户的影响,个性化地给出该通知的针对该用户的“评分”, 如果“评分” > “过滤阈值”,则认为是重要通知,反之则是不重要通知。

在这些维度中,目前影响最大的维度是历史点击率,这意味着:

  • 对开发者来说,优化通知的点击率(针对设备,而不是大盘),是提高重要性的最好方法,如减少推送频率,提高内容质量等。注意,是点击率,而不是点击量。
  • 历史点击率针对的是设备,而不是大盘用户。这就要求业务使用个性化的推送策略,避免全量推送,以减小被列为不重要通知的概率。

3. 为什么在同一台手机上,同一个应用的通知,有些是重要的,有些是不重要的

如前所述,除了历史点击率,通知的评分也受通知的标题和描述影响,也就使同一应用的不同通知评分产生差别。

4. 一条通知被收进二级页,是不是就不会被点击了

不是的。从目前的数据情况来看,即便是在二级页,也有很多曝光、点击行为。

5. 这个“过滤阈值”对应的历史点击率具体是多少

如前所述,历史点击率只是评分的一个影响因子,过滤阈值可以理解为是一个特殊的评分。由于评分还受到通知文本和用户属性影响,因此无法与历史点击率直接挂勾,我们也就没法给到一个准确的值。

6. 新激活的手机和新装应用如何处理

  • 新激活的手机

新激活的手机上,初始状态各应用的历史点击率都为 0,为了避免这些通知都被直接过滤,过滤阈值在新激活后的前 14 天,会从 0 开始慢慢增长(逐小时更新)。因此新激活用户的大部分通知都不会被过滤。

  • 新装应用或新发通知

如果这是一个新安装的应用,或者之前从来没有发过通知,那么这个应用的历史点击率也为 0。为了避免这个应用的通知直接被过滤,我们加入“首 x 条保护”的规则 :即如果某个应用在当前设备的过去30天都没有产生过通知,那么,该应用在该设备的前 x 条通知,默认都是重要通知,不会被过滤。只要这些通知有1条被点击,后续通知就有很大概率成为重要通知,因此请开发者提高前几条通知的质量。 x 是一个服务端配置的值,目前默认为3。

7. 一旦成为不重要通知,是不是就没法成为重要通知了

不是的。

第一,历史点击率是一个动态变化的值,意味着:

  • 如果用户经常点击你的通知,不管它当时被判断为重要还是不重要,其历史点击率都会不断上涨,超过阈值之后,不重要通知也会变成重要。
  • 如果用户经常不点击你的通知,不管它当时被判断为重要还是不重要,其历史点击率都会不断下降,低于阈值之后,重要通知也会变成不重要。

因此开发者应持续提供优质的通知内容,以保持较高的历史点击率。

第二,历史点击率的计算范围是过去30天。举个极端例子,如果一个应用超过30天停止发送通知,那么这个应用对于系统来说,就等价于一个新安装的应用,将重新开始计算历史点击率,同时,“首 x 条保护”的规则也会生效。

8. 这个功能的影响范围

8.1. 用户范围

  • 目前仅影响国内版用户,国际版暂无此功能(仍为按时间排序)
  • 目前已随 MIUI 9 稳定版发布(仅覆盖国内用户)

8.2. 应用范围

  • 所有在通知栏发通知的应用,包括MIUI 应用和第三方应用。

9. 你们只看历史点击率吗?

不是。如前所述,模型会综合考虑非常多的维度,但目前的训练结果表明,历史点击率是影响权重较大的因子。

10. 是不是历史点击率高,这个应用的所有通知都会是重要的

  • 短期:这个说法近似正确。如前所述,目前历史点击率对“重要”与否的影响比较大, 所以短期来看,这个说法近似正确。但因为也有其他维度的影响,个别通知仍然可能出现差异。
  • 长期:这个说法不正确。未来半年会挖掘更多的维度,可以预见,历史点击率的影响权重会不断降低,那么这个说法就不成立了。

11. 用户可以手动纠正吗

  • 不感兴趣

如果用户觉得某条通知不重要,可以手动从右往左滑通知,点击“不感兴趣”,那之后这个应用的所有通知都会变成不重要了。大家应该注意到,以前的右滑屏蔽不见了(长按通知进入设置页的操作仍保留)。我们不鼓励用户直接屏蔽应用,因此弱化了这个操作,用“不感兴趣”来代替。

  • 设为重要

同样,如果用户觉得某条通知重要,可以从右往左滑通知,点击“设为重要”,那之后这个应用的所有通知都会变成重要。

12. 用户可以关闭这个功能吗

可以。前往设置 > 通知和状态栏 ,关闭“通知过滤”这个开关,就会取消该功能,同时恢复为原有的按时间排序的规则。

13.如何联系我们

可以邮件给我们的项目组 miuishell@xiaomi.com,会有同事解答相关疑问。

MIUI 9 & 10“状态栏黑色字符”实现方法变更通知

MIUI 9 & 10“状态栏黑色字符”实现方法变更通知

我们在开发版 7.7.13(2017年的开发版) 及以后的版本,MIUI 状态栏更新了一处实现逻辑。直接影响就是,部分应用无法显示“状态栏黑色字符”,如下图中的即刻、UC、好奇心日报等应用。

1. 问题出现的原因

  • 在 Android 6.0 以前,Android 没有方法可以实现“状态栏黑色字符”效果,因此 MIUI 自己做了一个接口。
  • 在 Android 6.0 及以上版本,Android 提供了标准的方法实现“状态栏黑色字符”效果,但这个方法和 MIUI 的方法产生了冲突,以致于当开发者使用 Android 标准方法时,没有出现预期的效果,这给很多开发者都造成了困扰,尤其是海外开发者。

2. 如何解决

基于以上背景,我们决定兼容 Android 的方法,舍弃 MIUI 的自己的实现方法。从今天的 7.7.13 开发版生效,之后随 MIUI 9 外发。非常抱歉给各位开发者带来麻烦,但长远来看,兼容 Android 的标准,对 MIUI 和开发者都更为有利。

3. 开发者需要做的

如果开发者需要设置“状态栏黑色字符”的效果, 需要做以下几件事:

3.1. 在新的 MIUI 版本(即基于 Android 6.0 ,开发版 7.7.13 及以后版本)

  • 使用 View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR ,来设置“状态栏黑色字符”效果
  • 同时要设置 WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
  • 并且不设置 WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS

  参考实例:

Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

3.2. 在旧的MIUI版本

还有大量的用户使用旧的 MIUI 版本,因此仍然需要使用 MIUI 原有的方法,即

public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
        Class<? extends Window> clazz = activity.getWindow().getClass();
        try {
        int darkModeFlag = 0;
        Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
        Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
        darkModeFlag = field.getInt(layoutParams);
        Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
        extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
        } catch (Exception e) {
            e.printStackTrace();
        }
}

对于广大开发者而言,为了保证在新旧版本的 MIUI 都能实现「状态栏黑色字符」的效果,需要开发者同时写上以上两种实现方法。给各位开发者带来麻烦,再次表达歉意,望谅解。文末附上了常见问题,如果在适配过程中遇到问题,可以邮件给我们的项目组 miuix-systemui@xiaomi.com,会有同事解答相关疑问。。

4. FAQ

4.1. 如何调试

如前所述,相关改动将从 7.7.13 开发版(2017年的版本)及以后版本生效,因此开发者升级到  MIUI 10 最新开发版即可,支持的机型和下载链接如下(找到对应机型的最新开发版):

4.2. 如何实现状态栏白色字符效果

int flag = window.getDecorView().getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
window.getDecorView().setSystemUiVisibility(flag);​

小米商店小米上架“我的收藏”接入说明

小米商店小米上架“我的收藏”接入说明

1.“我的收藏” 简介

“我的收藏”是信息助手(负一屏)上一张默认开启的卡片。

能同步将各应用中的收藏内容添加到“我的收藏”,并通过“我的收藏” 卡片和全局搜索来查找使用。

2.为什么要做“我的收藏”

日常使用的大多数应用都有收藏功能,而手机上的收藏功能目前存在如下3个问题:

  • 查找难:收藏的内容忘记在哪个应用,且应用的收藏入口不同,查找费力;
  • 忘记查看:收藏的内容本来准备先码后看,因入口过深而遗忘;
  • 收藏方式不统一:市面上现有的全局收藏方式较为复杂,且不统一,有一定学习成本; 

3.如何使用“我的收藏”

3.1如何添加收藏

当用户在应用中有收藏行为时,应用主动发送广播,将当前收藏内容发送到“我的收藏”,“我的收藏”收藏成功后,会弹出通知提醒。 (与原应用的收藏方式相同,无需用户学习新的收藏方式) 

3.2如何查看收藏内容

目前有2种方式查找使用收藏内容:我的收藏卡片和全局搜索。

3.2.1信息助手(负一屏)我的收藏卡片

作为负一屏默认开启的常驻卡片,展现最新收藏的3篇文章。

3.2.2 全局搜索

通过全局搜索对标题、来源进行搜索查找收藏的内容。

3.3收藏的打开方式

通过合作接口添加到“我的收藏”中的所有内容,打开方式均通过原应用打开。

4. 合作方接入的好处是

· 提升产品DAU和带来一定量的新增

通过接口收藏的内容,都会通过原应用打开。若应用被卸载,会提示用户安装后使用。

· 提升品牌曝光和内容展现

收藏的内容会展现在负一屏收藏卡片,同时通过全局搜索可以查找到收藏内容。

5. 接入技术文档

接入方式,因收藏动作无需回调结果,所以可以使用原生最简单的广播接口来实现。 

    private interface IntentConfig {
        public static final String String ACTION = "com.miui.personalassistant.action.FAVORITE";
        public static final String String PACKAGE = "com.miui.personalassistant";   //发送广播指定的包名
        public static final String String PERMISSION = "com.miui.personalassistant.permission.FAVORITE";    //发送广播指定的权限
        public static final String String BUNDLES = "bundles";
        public static final String String ACTION_FAV = "action_fav";
    }
 
    private interface BundleConfig {
        public static final String MATCH_COMPONENT = "matchComponent";
        public static final String MATCH_ACTION = "matchAction";
        public static final String TARGET_URL = "targetUrl";
        public static final String TARGET_DATA = "targetData";
        public static final String TARGET_TITLE = "targetTitle";
        public static final String TARGET_IMAGE = "targetImage";
        public static final String TARGET_EXTRA = "targetExtra";
    }
 
 
 
/**
 *  批量创建bundle方式
 *
 */
    /* 添加收藏动作如下 */
    // 指定跳转应用,方案有1、2两种,选其一
    // 1、设置当前收藏的 ComponentName(以便收藏后显示来源和原App跳转), 形式如(packageName/className全称):com.android.browser/com.android.browser.BrowserActivity
    // 2、设置intent action,另需要ComponentName设置为packageName,intent.setAction(action)  intent.setPackage(packageName)跳转使用
    Bundle bundle = new Bundle();
    bundle.putString(BundleConfig.MATCH_COMPONENT, componentName);  //收藏跳转对应APP使用:setComponent(component);若设置通过intent action跳转应用,则component设置为packageName
    bundle.putString(BundleConfig.MATCH_ACTION, actionName);  //收藏跳转对应APP使用:Intent.setAction(action)
  
    bundle.putString(BundleConfig.TARGET_URL, targetUrl);  // 参数类型http/https,指详情页的具体链接地址,用于对应应用卸载后,网页显示详情,webview.loadUrl(targetUrl)
    bundle.putString(BundleConfig.TARGET_DATA, targetData);  //对应详情页面的intent data,从收藏跳转到对应APP的详情页使用:Intent.setData(Uri targetData)
    bundle.putString(BundleConfig.TARGET_TITLE, targetTitle); // 必选,收藏条目显示标题
    bundle.putString(BundleConfig.TARGET_IMAGE, targetImage);   //可选,收藏图片url,推荐大小180x180px(宽高比为1:1)
    bundle.putString(BundleConfig.TARGET_EXTRA, targetExtra);  // 可选,用于有额外需求的参数传递
 
 
    /* 取消收藏动作如下 */
    // 只需要取消对应的链接
    Bundle bundle = new Bundle();
    bundle.putString(BundleConfig.TARGET_URL, targetUrl);
     
    // 向集合中添加所有要收藏数据的bundle
    ArrayList<Bundle> bundleList = new ArrayList<Bundle>();
    for (int i = 0; i < length ; i++) {
        bundleList.add(bundle);
    }
 
    // 发送收藏广播
    Intent intent = new Intent(IntentConfig.ACTION); // 指定广播Action
    intent.putParcelableArrayListExtra(IntentConfig.BUNDLES, bundleList);
    intent.putExtra(IntentConfig.ACTION_FAV, true);  //true添加收藏动作,false取消收藏动作
    intent.setPackage(IntentConfig.PACKAGE); // 限定当前收藏广播接收者的包名和权限
    context.sendBroadcast(intent,  IntentConfig.PERMISSION);
 
    //考虑到数据安全,外发应用需要判断下是否是小米手机,如果是,则发送广播,否则取消发送
    使用android.os.Build.MANUFACTURER,其值为Xiaomi即为小米设备

6.其他说明

6.1“我的收藏”已经支持哪些版本

MIUI 9及以上的版本都已经支持“我的收藏”功能。

6.2“我的收藏”是否还有进一步的合作方式

我们愿意与合作方一起探索更深入的合作,比如收藏商品降价提醒、追剧等可能的方向。

小米商店 MIUI 10 桌面图标上传规范

小米商店 MIUI 10 桌面图标上传规范

1. 背景

自 MIUI 10 开始,小米手机桌面默认图标将升级为全新的样式,图标更精致,圆角更小。

2. 规范

小米手机桌面是直接读取应用包内图标的,但为了保证桌面图标的视觉统一,系统会对图标作一定的截剪缩放,针对「方形」和「非方形」图标,我们有不同的处理规则,详情请见附录一和附录二。希望开发者按以下要求自查或优化现有的包内图标:

  1. 方形图标请保证是直角,且周围无透明像素。由于 MIUI 10 默认桌面图标的圆角很小,请开发者避免上传大圆角的图标。
  2. 提供更大尺寸的图标,防止图标模糊,具体建议尺寸如下:
  • xhdpi:≥ 94px
  • x​xhdpi:≥ 130px

桌面图标是用户对应用的第一印象,希望各位能够保证应用在小米手机上呈现最好的视觉效果。感谢各位开发者的支持与配合,谢谢!

3. 附录

附录一:方形图标的缩放/裁剪规则

附录二:非方形图标的缩放规则

小米手机APP桌面应用角标适配说明

小米手机桌面应用角标适配说明

1. 默认逻辑

当应用向通知栏发送了一条通知 (除了进度条样式和常驻通知外),应用图标的右上角就会显示「1」。角标的数字代表应用的通知数,即应用发送了「x」条通知,角标就会显示为「x」。

2. 开发者如何设置桌面角标

2.1 MIUI6-MIUI11桌面应用角标适配方法

可通过反射调用设置桌面角标,参考代码如下:

try {
    Field field = notification.getClass().getDeclaredField(“extraNotification”);
    Object extraNotification = field.get(notification);
    Method method = extraNotification.getClass().getDeclaredMethod(“setMessageCount”, int.class);
    method.invoke(extraNotification, mCount);
} catch (Exception e) {
    e.printStackTrace();
}

2.2 MIUI12及以后桌面应用角标适配方法

由于Google屏蔽了hideAPI的反射调用,因此MIUI12及以后可以使用notification.number,可参照Android开发者文档https://developer.android.google.cn/reference/android/app/Notification#number,参考代码如下:

Notification notification = new Notification.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle(textTitle)
            .setContentText(textContent)
            .setNumber(int number)
            .build();

3. 如何判断MIUI版本

可参考文档https://dev.mi.com/console/doc/detail?pId=1312,其中6.1节有具体方法说明。

小米手机全面屏手势提示线(虚拟键)适配说明

小米手机全面屏手势提示线(虚拟键)适配说明

1.背景

MIUI12将加入”手势提示线”,在设置-更多设置-全面屏中,可以通过开关打开/关闭该功能。手势提示线的实现原理参考了原生的方式,和虚拟按键在同一个window当中,可以理解成是虚拟按键的一种新的形态。

  • 适配的原则是:”手势提示线”(也就是虚拟键)的背景颜色和页面整体的背景颜色保持一致;
  • 主要有两种适配方式:”使用沉浸式虚拟键”和“给虚拟键设置合适的颜色”。

  图例为开启“手势提示线”效果                              图例为关闭“手势提示线”效果

2.使用沉浸式虚拟键

2.1如何设置

沉浸式虚拟键,即app的content view延伸到虚拟键区域,虚拟键的颜色透明。类似的,还有沉浸式状态栏,即app的content view延伸到状态栏区域,状态栏的颜色透明。

有两种设置的方式,参考代码如下。

方式1:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_layout);
 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);       //设置沉浸式状态栏,在MIUI系统中,状态栏背景透明。原生系统中,状态栏背景半透明。
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);   //设置沉浸式虚拟键,在MIUI系统中,虚拟键背景透明。原生系统中,虚拟键背景半透明。
}

方式2:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_layout);
 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    getWindow().setStatusBarColor(Color.TRANSPARENT);
    getWindow().setNavigationBarColor(Color.TRANSPARENT);
    getWindow().getDecorView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE|
        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|
        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    );
}

2.2可能存在的问题

设置了沉浸式虚拟键和沉浸式状态栏之后,状态栏和虚拟键会遮挡住app的内容,效果如下:

2.3解决方案

如果不希望app的内容被遮挡,可以给view设置  android:fitsSystemWindows=”true”,设置之后,系统会给该view自动加上paddingTop和paddingBottom。参考代码和效果如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/apps_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000FF"
    android:fitsSystemWindows="true">

2.4适用的场景举例

当页面具有复杂的背景或纹理时:

3.给虚拟键设置合适的颜色

3.1如何设置

使用setNavigationBarColor来设置虚拟键的颜色。注意不要单独把颜色设置成透明,如果要设置成透明的话,参考上面的沉浸式虚拟键,配合其他flag使用。

参考下面的代码,按照这种方式设置之后,app的content view将不会延伸到虚拟键区域。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_layout);
 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    getWindow().setStatusBarColor(Color.BLUE);     //设置状态栏的背景颜色
    getWindow().setNavigationBarColor(Color.BLUE);  //设置虚拟键的背景颜色
}

3.2可能存在的问题

同一个应用往往有多个子页面,如果页面中背景颜色发生了变化,为了让虚拟键的颜色和页面的颜色保持一致,需要重新设置虚拟键的颜色,而不是统一给应用设置一个色值。

目前大部分业务已经适配了深色模式,因此在深色模式下还需要单独对虚拟键背景做深色适配。

3.3适用的场景举例

使用底部tab的颜色或者页面背景的颜色

小米商店上架APP权限用途用户告知适配说明

1.系统权限描述

MIUI11中,应政府对手机软件权限获取的合规要求,MIUI将支持三方应用通过向系统接口传输参数的方式,显示获取运行时权限的目的及用途,具体方案如下:

应用申请运行时权限时,可通过接口传输权限用途及描述,满足政府对于软件获取权限的合规要求,同时通过有效行为描述增加用户授权的可能性。

2.接口开放标准

2.1.填写权限使用申请

  • 仅支持通过小米应用商店上架的应用申请使用接口,申请时请按以下内容填写权限申请资料:
权限名称是否申请权限用途及说明(请提供简体中文及英语,中文字符不超过18个汉字)
Manifest.permission.READ_CONTACTS  
Manifest.permission.WRITE_CONTACTS  
Manifest.permission.GET_ACCOUNTS  
Manifest.permission.WRITE_CALENDAR  
Manifest.permission.SEND_SMS  
Manifest.permission.RECEIVE_SMS  
Manifest.permission.READ_SMS  
Manifest.permission.RECEIVE_MMS  
Manifest.permission.READ_EXTERNAL_STORAGE  
Manifest.permission.WRITE_EXTERNAL_STORAGE  
Manifest.permission.ACCESS_FINE_LOCATIONManifest.permission.ACCESS_COARSE_LOCATION  
Manifest.permission.READ_CALL_LOG  
Manifest.permission.WRITE_CALL_LOG  
Manifest.permission.PROCESS_OUTGOING_CALLS  
Manifest.permission.READ_PHONE_STATE  
Manifest.permission.READ_PHONE_NUMBERS  
Manifest.permission.CALL_PHONE  
Manifest.permission.ADD_VOICEMAIL  
Manifest.permission.USE_SIP  
Manifest.permission.ANSWER_PHONE_CALLS  
Manifest.permission.RECORD_AUDIO  
Manifest.permission.ACTIVITY_RECOGNITION  
Manifest.permission.CAMERA  
Manifest.permission.BODY_SENSORS  
  • 重要提示:以下权限,在MIUI 11 3.12 的开发版后将无法获取:
Manifest.permission.READ_PHONE_STATE

Manifest.permission.READ_PHONE_NUMBERS

Manifest.permission.CALL_PHONE Manifest.permission.ANSWER_PHONE_CALLS

2.2.发送权限申请至审核邮箱

填写权限使用申请后,请按如下格式将内容发送至miui-security-open@xiaomi.com

邮件主题:申请使用系统权限描述

【申请应用】填写应用名称

【应用包名】com.xxxx.xxxx

【公司主体】填写公司主体名称

【相关负责人】填写相关负责人

【联系方式】填写相关负责人联系方式

【权限申请目录】粘贴权限使用申请内容

2.3.等待审核

发送邮件后,请等待反馈,反馈时间在1-3个工作日内,若审核通过,将在反馈中提供调用方法并开设白名单。

2.4.技术接入

确定开放白名单后,请按以下方式接入:

申请示例:

private String[] permissions = new String[]{
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CAMERA,
        Manifest.permission.RECORD_AUDIO,
        Manifest.permission.ACCESS_FINE_LOCATION
};



private String[] permissionDescs = new String[] {
        "存储用户精修美图",
        "拍摄抖音短视频",
        "游戏中进行语音交流",
        "获取地理位置来提供导航功能"
};


private List<String> mPermissionList = new ArrayList<>();
private static final int PERMISSION_REQUEST = 1;

//开始申请
for (int i = 0; i < permissions.length; i++) {
    if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
 mPermissionList.add(permissions[i]);
 mPermissionList.add(permissionDescs[i]);
    }
}
if (mPermissionList.isEmpty()) {
    //业务操作
} else {
    String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);
    ActivityCompat.requestPermissions(MainActivity.this, permissions, PERMISSION_REQUEST);
}


//申请回调
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
 if (requestCode == PERMISSION_REQUEST) {
        //业务操作
    }
}

 以上是最新推荐的申请权限的方式,只需要在申请的权限数组中加上对应的权限描述即可。

2.5.注意事项

权限及传入的权限描述要一一对应,权限描述不能传入null,若不需要描述,可传入空字符串:” “。

面向隐私保护的权限使用行为管理说明

1.背景

自MIUI于2010年8月16日上线以来,用户的隐私及安全都是我们最关注的要点。

小米于2018年起草《移动智能终端补充设备标识规范》,应对IMEI等设备标识被篡改及滥用的信息安全问题,确保用户数据隐私不被泄露。

在用户的隐私方面,MIUI希望可以通过系统权限隐私保护逻辑,在用户的隐私及数据安全方面有进一步的突破与保护措施。

2.权限改动

2.1.禁止获取不可重置的设备标识

  • 安卓P版本中将不再支持通过READ_PHONE_STATE权限获取不可重置的设备标识。具体表现与Android Q一致,获取到空值不抛出异常。
  • 生效时间:开发版-MIUI11 3.12(小米6)。
  • 针对READ_PHONE_STATE权限在Android P各MIUI版本的表现为:
版本/设备标识IMEI/MEIDIMSIICCIDSerialOAID
MIUI 11开发版(3.12之前)可以获取可以获取可以获取可以获取可以获取
MIUI 11稳定版可以获取可以获取可以获取可以获取可以获取
MIUI 11开发版(3.12之后)不可获取不可获取不可获取不可获取可以获取
  • 适配方法:可以通过”1″.equals(SystemProperties.get(“ro.miui.restrict_imei_p”))为true判断Android P上已经开启了设备标识的限制策略。
  • 建议开发者使用OAID替代IMEI等设备标识作为用户标识。OAID获取方法:http://msalliance.icoc.bz/col.jsp?id=120

2.2.CALL_PHONE 及 ANSWER_PHONE_CALLS

  • 除应用被设置为默认拨号应用外,CALL_PHONE权限及ANSWER_PHONE_CALLS将默认禁止获取。
  • 生效时间:开发版-MIUI11 3.12。
  • 适配方法:若业务需要以上两项权限,可从产品逻辑角度引导用户将应用设置为默认拨号应用。

2.3.禁用后台拍照行为

  • CAMERA权限仅支持应用在前台时调用,应用处于后台时将禁止使用该权限进行拍照或录像等行为。
  • 生效时间:开发版-MIUI11 3.12。
  • 适配方法:请开发者检查业务是否有相关行为并修改相关业务逻辑,避免出现异常情况;若出现不可避免的后台使用相机行为,请通过调起前台服务实现。

2.4.定位、录音权限用途描述

当应用申请定位、录音权限时,系统会根据应用是否对权限进行用户说明来判断授权弹窗中出现的选项:

  • 若应用未对权限用途进行说明,则显示“拒绝”“允许本次”及“仅在应用使用中允许”选项;
  • 若应用已进行权限用途说明,则在以上选项的基础上,增加显示“始终允许”选项。

该显示逻辑不影响基础权限选项,若用户进入应用授权管理,仍可对权限设置始终允许。

  • 生效时间:开发版-MIUI11 3.12。
  • 适配方法:请开发者进行权限用途说明,接入权限用途说明请查看:”MIUI权限用途接入说明“。

小米手机深色模式适配说明

小米手机深色模式适配说明

1.深色模式背景与介绍

1.1.安卓原生深色模式介绍

Android 10 (API 级别 29) 及更高版本中提供深色主题背景。深色主题背景具有诸多优势:

  • 可大幅减少耗电量(具体取决于设备的屏幕技术)。
  • 为弱视以及对强光敏感的用户提高可视性。
  • 让所有人都可以在光线较暗的环境中更轻松地使用设备。

深色主题背景同时适用于 Android 系统界面和在设备上运行的应用。在 Android 10 (API 级别 29) 及更高版本中,您可以通过以下三种方法启用深色主题背景:

  • 使用系统设置(Settings -> Display -> Theme)启用深色主题背景。
  • 使用“快捷设置”图块,从通知托盘中切换主题背景(启用后)。
  • 在 Pixel 设备上,选择“省电模式”将同时启用深色主题背景。其他原始设备制造商 (OEM) 不一定支持这种行为。

可参考:https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#top_of_page

1.2.MIUI深色模式介绍

深色模式是一种将屏幕主色调转为深色的模式。如下图MIUI10界面为例,上图是正常浅色背景,下图为MIUI深色模式。

用户在MIUI中有两个方式可以打开深色模式:1.设置-显示-深色模式 2.下拉控制中心 中可以开启,开启后将全局变黑如上图显示:

对于适配深色模式的应用来说,我们会优先启用应用的深色模式。未接入的应用,则会通过算法进行反色。适配方式将在第三部分详细描述。如果用户不希望某个应用被反色,用户可以手动关闭该应用的反色功能,见下方:

目前已有众多知名头部三方应用适配了深色模式,例如微信、QQ、爱奇艺、优酷、知乎、小红书、钉钉等。

2.适配深色模式的好处

我们强烈建议您为您的应用适配深色模式,主要有如下原因:

  • 更酷、更时髦的流行趋势

作为一种全新的潮流,黑色界面受到众多用户、尤其是年轻用户的欢迎。目前,各大安卓系统、iOS系统都已经支持深色模式,众多主流头部应用也已适配或正在适配深色模式。                

  • 让用户更专注于内容

深色背景下,文字、图片、视频都能更清晰地呈现,尤其是暗光环境下。对于浏览器、资讯和视频类app,深色可以让用户沉浸其中,为应用贡献更多的使用时长:对于使用时段是晚上的应用,这一特性更加明显。                                               

  •  降低应用的耗电量                                               

省电是用户最关注的性能之一。低电情况下,用户更青睐使用深色模式的应用。根据小米实验室测试数据:

OLED屏幕100%亮度下,深色模式耗电相比浅色模式,最高降低83%;

OLED屏幕50%亮度下,深色模式耗电相比浅色模式,最高降低50%。

  • 推广优待适配深色模式时可以联系我们,小米可以为应用提供应用商店专题和微博宣传等方式,为应用增加额外的宣传。

3.适配方式

适配方式有两种:

  • 适配深色模式资源:开发者根据自身应用设计深色模式,按照适配规范进行适配。
  • 适配全局反色:利用安卓Q上提供的forcedark能力可以直接反色。

在适配前,开发者需要考虑是否在自有应用内增加深色模式开关。我们建议的方式:

  • 务必提供跟随系统深色模式的选项。可以默认跟随系统,或在监测到系统切换为深色/浅色时提示用户。 
  • 可以为用户提供手动切换的开关。

目前已有三方应用如下(左 小红书 右 QQ),仅供参考:

方式一 适配深色模式资源                                           

适配深色模式资源需要设计师先对所有页面设计深色页面,再由开发完成深色模式资源开发。

优点:在所有安卓版本、所有手机厂商用户均可以使用,且体验较好。

3.1.谷歌适配要求

开发者可基于谷歌深色模式适配标准进行适配:https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#top_of_page

已经适配过的页面要将ForceDarkAllowed()​参数值设置为false,若整个主题均已适配深色模式,则需要将这个主题的ForceDarkAllowed()参数值设置为false。

3.2.小米深色模式配色标准设计

其余适配建议详见设计文档:附件1-小米深色模式配色标准设计文档。

3.3.接入方式

3.3.1.接入介绍

  • 根据谷歌深色模式接入标准,如要支持深色主题背景,您必须将应用的主题背景(通常可在res/values/styles.xml中找到)设置为继承 ​DayNight​ 主题背景:
<style name="AppTheme" parent="Theme.AppCompat.DayNight">

您还可以使用 MaterialComponent 的深色主题背景

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">

这会将应用的主要主题背景与系统控制的夜间模式标记相关联,并将应用的默认主题背景设置为深色主题背景(如果已启用)。详细内容见:https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#force_dark

从开发的角度说,就是打开夜间模式后,系统会优先从xxx-night资源中寻找资源并替换。
Android系统从2.2开始就已经⽀支持了了DarkMode,其对应接口是名为“uimode”的系统服务,DarkMode所使⽤用到的接口方法是:setNightMode、getNightMode分别对应设置夜间模式和获取设置状态。

// 获取uimode系统服务
UiModeManager uiModeManager = (UiModeManager)
getSystemService(Context.UI_MODE_SERVICE);                                             
// 获取设置状态
int currentMode = uiModeManager.getNightMode();                                               
// 设置夜间状态
uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_AUTO); // ⾃动
uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_YES); // 启⽤
uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO); // 停⽤
                                             
在日志中的体现:
------------------------------------------------------                                                        
DUMP OF SERVICE uimode:
Current UI Mode Service state:                                                        
mDockState=0 mLastBroadcastState=0                                                        
mNightMode=2 mNightModeLocked=false
mCarModeEnabled=false mComputedNightMode=false
mCarModeEnableFlags=0 mEnableCarDockLaunch=true                                                        
mCurUiMode=0x2d mUiModeLocked=false mSetUiMode=0x2d
mHoldingConfiguration=false mSystemReady=true
mTwilightService.getLastTwilightState()=null                                                        
--------- 0.001s was the duration of dumpsys uimode,ending at: 2019-01-18 00:00:01--------------

从uimode服务dump出来的信息可以判断:

mNightMode的取值:0 → AUTO; 1 → NO; 2 → YES另外,在Android O开始,Android⽀支持adb命令启动和停⽤用DarkMode,具体命令是:adb shell cmd uimode night <auto | yes | no>

O以前的机型,只能通过代码调用uimode接口启动和停用DarkMode。需要注意的是,miui虽然从level 16开始支持DarkMode,但是并不意味着miui之前的版本不能切换DarkMode,用户完全可以通过命令或者代码调用系统接口,启动和关闭DarkMode。而Setting中的开关是阻⽌不了的,除⾮MIUI对这个权限进行收紧。   

MIUI SDK从level 16开始,支持DarkMode,所以的支持DarkMode,是指MiuiSDK增加了新的主题,DayNight,来自适应的适配Light和Dark主题。其实在16之前的SDK上,Light和Dark主题都是一直存在的,只是没有一个自动适配的机制存在,而且Dark主题存在一些Bug,并不是它应该是的样⼦。适配过程中,存在一些APP,之前就是在Dark主题下进行的开发,那么在sdk level 16以后,发现Dark模式存一些问题,比如弹窗变成了⿊⾊,均是因为Dark主题修改造成的。附录中会给出SDK针对Dark和Light进行的改动,包括所有受影响的资源和主题样式修改。

3.3.2.接入方式详细说明                                              

重点说明⼀下接⼊和使⽤⽅式。这⾥除了Theme.Light.DarkActionBar这个主题以外,所有Light(Dark)主题均有对应的DayNight主题。

  • 对于非解耦应⽤,可以直接使⽤Miui SDK的public的资源和属性。

代码接⼊方式:可以直接将使⽤MiuiSdk的Light或者Dark主题的地方,替换成DayNight主题,⽐如:将

<style name="MiuiDemo.Theme.Test" parent="miui:Theme.Light">
或者<style name="MiuiDemo.Theme.Test" parent="miui:Theme.Dark"> 
替换成<style name="MiuiDemo.Theme.Test" parent="miui:Theme.DayNight">

Java代码中:将使⽤Light主题的所有地⽅miui.R.style.Theme_Light替换成miui.R.style.Theme_DayNight

  • (如果本身就是⾃升级应用,就不⽤看这⼀步了)对于解耦自升级应⽤,需要在gradle中进行如下操作:   
1)修改build.gradle中的dependencies,使⽤用miui插件,如下:(以gradle 3.3.0为例)
dependencies {                                               
classpath 'com.miui.tools.build:gradle:3.3.0'
}
2)gradle/wrapper/gradle-wrapper.properties⽂文件中的gradle修改到5.0,即:
distributionUrl=http://sdk.pt.miui.com/miuisdk/software/gradle/gradle-5.0-all.zip
3)此步,3.2.0可以忽略略,在3.3.0下必须将:                                                
apply plugin: 'com.android.application'
改成
apply plugin: 'com.miui.application'                                       
4)如果gradlew的⽇日志中有如下输出:
add property to gradle.properties of this project:                                                
android.aapt2FromMavenOverride=/home/{username}/.miuisdk/build-tools/aapt/28/aapt2
则修改gradle.properties,最后加一行:
android.aapt2FromMavenOverride=//home/{username}/.miuisdk/build-tools/aapt/28/aapt2
5)增加依赖:
compileOnly 'com.miui:core:alpha-SNAPSHOT'

于是,miui sdk中的Theme.DayNight就接入完成,在APP中可以直接使⽤Theme.DayNight.<…>主题。针对之前的miui:Theme.Light主题或者miui:Theme.Dark主题,均有对应的Dark或者Light主题。所以,如果需要适配自动切换夜间和日间模式,只要替换成对应的DayNight主题即可,DayNight主题负责⾃动切换两种(Dark和Light)主题。

  • (非单发应⽤请忽略)对于单发应用:单发应用的接⼊⽅式,可以参考:MIUI SDK support包的使用指南将依赖由:compileOnly ‘com.miui:core:alpha-SNAPSHOT’改成 implementation ‘com.miui.support:core-compat:alpha-SNAPSHOT’
  • 对于单发或者⾃升级应⽤,在代码接入上完全可以参考1中的代码接入方式。即,替换Light或者Dark为DayNight。但是,对于⾃自升级来说(单发应⽤不会有这个问题,因为单发应用已经将DayNight主题打包进APK),由于不确定⾃升级的目标ROM是否⽀持DayNight主题,所以如果在没有DayNight主题的ROM上⾃自升级,就会崩溃。这⾥需要看下⾯的注意事项1,可以找到解决方案。详见开发文档:附件2-深色模式开发文档

方式二 适配全局反色

全局反色利用安卓Q上提供的forcedark能力可以直接反色,对于开发者来说较为友好。

  • 优点:开发工作量小,适配较快。
  • 缺点:仅安卓Q手机可以使用该功能,复杂页面用forcedark适配难度较大;非原生的Webview无法反色,图片无法反色。

可以在安卓Q手机上,打开以下开关即可体验安卓Q反色能力,查看本应用反色后的情况。开关位置如下:

3.4.谷歌Force Dark适配要求

Android 10 提供 Force Dark 功能。一如其名,此功能可让开发者快速实现深色主题背景,而无需明确设置 ​DayNight​ 主题背景。如果您的应用采用浅色主题背景,则 Force Dark 会分析应用的每个视图,并在相应视图在屏幕上显示之前,自动应用深色主题背景。有些开发者会混合使用 Force Dark 和本机实现,以缩短实现深色主题背景所需的时间。应用必须选择启用 Force Dark,方法是在其主题背景中设置 ​android:forceDarkAllowed=”true”​。此属性会在所有系统及 AndroidX 提供的浅色主题背景(例如 ​Theme.Material.Light​)上设置。使用 Force Dark 时,您应确保全面测试应用,并根据需要排除视图。如果您的应用使用深色主题背景(例如​Theme.Material​),则系统不会应用 Force Dark。同样,如果应用的主题背景继承自 DayNight​主题背景,则系统不会应用 Force Dark,因为会自动切换主题背景。

3.5.MIUI深⾊模式适配的目标和方法

在MIUI12上推出全局的深色模式,所有系统应用和主流三方应用适配。在MIUI12上用户开启深色模式后将默认开启全局反色。要达到的效果:系统切换到深⾊模式以后,应⽤也随之切换到深色模式,这是我们这次MIUI适配深色模式要达到的目标,也是我们对每个系统应⽤的要求。

适配的⽅法有三种:                                          

  • Android原生的深色主题
  • 全局反⾊
  • 第三方框架或者应用⾃自己实现深色模式  

目前只有Android Q深色模式支持全局反色:Android Q上提供了两种实现深色模式的⽅式:深色主题和全局反⾊。

深⾊主题即Theme.AppCompat.DayNight或者Theme.MaterialComponents.DayNight。深⾊主题是Android官⽅提供的实现深色模式的一种方法,应用也可以其它自己的方法实现深色模式。深⾊主题起作用后,将会加载-night⽬目录下的资源,如果没有找到,那么加载默认资源。对于标准控件,如果应用不提供深色模式的资源,系统也会提供一套默认的深色资源(不过比较难看,基本不可用)全局反色即ForceDark,系统会根据一套算法,计算出每个View属于前台还是后台。对于前台View,会使其变亮,对于后台View,会使其变暗,⽽不需要开发者提供两套资源。具体的原理可以移步Android Q Force Dark调研。如果一个activity使⽤了深色模式,那么全局反色对其将不生效。    

3.6.接入方式介绍

3.6.1.建议的整体适配步骤                                              

  • 现状评估

打开系统的深⾊模式,看看⾃⼰应用中那些⻚面有没有问题,一般可以分为三类:

A.适配了深色模式没有问题

B.没有适配深色模式的

C.适配了深⾊模式但是有问题的

  • 全局反色过滤

对于所有的A,请务必禁用全局反色,否则全局反色可能会和已有的深⾊模式效果冲突。对于所有的B,可以设置 <item name=”android:forceDarkAllowed”>true</item> ,然后可以打开全局反色,观察有没有问题。没有问题的,那就适配完成了,问题⽐较⼤的归为D。

  • 全局反色问题分析                                       

对于所有的D,分析问题的原因,是反色本身的问题还是⾃己应⽤导致的,⽐如布局存在有问题,有图片、webVIew等。其他的看下能不能通过调整布局等最后还是通过全局反⾊简单解决,剩下统一归为C。

  • 重新适配

对于C,看看是不是原来的适配方法有问题,有没有必要采用新的适配⽅法、框架,可不可以采用系统的深色主题等重新适配。                                              

  • 验证

打开系统深色模式,重新测试所有页⾯。

比较理想的做法是:建议采用深色主题和全局反色相结合的方式。整个应用用的主题使用DayNight,设置<item name=”android:forceDarkAllowed”>false</item>。对于已经⽀持深色主题或者用其他方法实现了深⾊模式的⻚面,没必要再支持全局反⾊,务必禁⽤。对于需要使用反⾊的⻚面,使⽤Light主题,设<itemname=”android:forceDarkAllowed”>true</item>。其他⻚面单独适配。                                             

3.6.2.深色主题的适配

深色主题在Android Q之前就是已经有了的,只不过其在Android Q上得到了了加强。一个activity如果想使用深色主题,让其主题继承于DayNight主题或者让整个应用的主题继承于DayNight主题即可。不过,上⾯的做法只适合跟随系统变化的需求,如果有高级的需求,⽐如应用想要主动切换到深⾊色主题或者不跟随系统变化,而是让⽤户选择,那么需要这样做:

1.监听UImode的变化。manifest中 activity 设置属性 android:configChanges=”uiMode”,并重写onConfigurationChanged。注意,声明了configChanges系统将不不会重建对应的activity,⽽而是回调onConfigurationChanged,需要activity⾃己处理变化的情况

2.让Activity继承于AppCompatActivity,这样子可以通过AppCompatDelegate.setDefaultNightMode(mode) 设置当前activity的mode,通过AppCompatDelegate.getDefaultNightMode()获取当前设置的mode。系统可以选择的mode有四种,具体解释可以看下面第1篇文章。

3.用户选择夜间模式的时候,保存用户选择的模式到SharedPreferences,调用recreate()重启activity,注意recreate()是重新创建activity,会回调所有生命周期方法。

4.activity启动的时候,取出之前保存的模式,通过AppCompatDelegate.setDefaultNightMode(mode) 进行当前activity的mode。                                            

5.系统UImode发⽣变化的时候,即onConfigurationChanged时,获取系统当前的UImode,根据应用⾃身的逻辑判断需不需要改变当前activity的mode,如果需要改变重复第3、4步。

切换到深⾊模式时,资源应用的顺序:                                  

  • 应用提供的-night资源
  • 应⽤设置的默认资源(通常是亮色下的资源,也可以是应用主动在深⾊模式下设置的主题)
  • 系统的默认深⾊资源
  • 系统默认的亮色资源

所以,凡是应用⾃己提供资源了的,那就提供两套,要么就全部⽤用系统的默认资源。如果一个应⽤没有使用DayNight主题,那么只会变化应用提供的-night深⾊资源,其他不会变化,系统也不会应⽤标准控件的默认深色资源。

具体实现,可以参考:  

https://segmentfault.com/a/1190000011472198
https://blog.csdn.net/xiaoxiaocaizi123/article/details/90370275

有两种方式,⼤同小异,相信大家能看得懂。

3.6.3.全局反色的适配      

⾸先来看下全局反色生效前提:

系统端:1.开启深色模式

应用端:1.activity对应的主题是Light的 2.对应的控件允许全局反色,默认是forceDarkAllowedDefault,这个值由系统属性debug.hwui.force_dark决定,debug.hwui.force_dark⼜是由全局反⾊的开关控制,默认是关闭的。         

以上几点缺⼀不可,需要详细说明几点是:

1.实现了深色主题的activity是不会受全局反色的影响,前面说了,深⾊主题是DayNight,不属于Light

2.如果一个控件没有申明forceDarkAllowed,那么forceDark是否⽣效取决于全局反色是否开启,如果全局反色开启,那么forceDark生效,否则不生效;

如果一个控件声明了forceDarkAllowed = false,那么无论如何都不会生效;

如果一个控件声明了forceDarkAllowed = true,那么只要开启深色模式,全局反色就会⽣效。             

3.forceDarkAllowed可以在主题xml中申明,也可以在代码中动态设置,动态设置可以具体到某⼀个view,后者会覆盖前者。遵循覆盖原则,即子View的声明会覆盖父View的声明,activity的会覆盖这个应⽤的申明。

适配全局反色的步骤:                                                

1.compileSdkVersion 设为29, 否则会编译失败,targetSdkVersion 貌似没有要求。

2.对于需要使用forceDark的activity,务必让其实现Light主题,Dark主题、DayNight主题都不会⽣效。

3.在activity的主题中申明<item name=”android:forceDarkAllowed”>true</item> 或者 在onCreate中,在setContentView之前,调⽤getWindow().getDecorView().setForceDarkAllowed(allowed)。

最后提供demo,需要的可以参考一下,源码:https://github.com/CQULittleMing/AndroidDemo/tree/master/demo

操作路径:  View – View 下面最后的两个。     

4.FAQ

4.1.全局反色的局限

  • 目前全局反色只是实验性功能,存在很多bug,不可过于依赖,更多可以参考Force Dark目前存在的问题。
  • 不会反色图⽚。
  • WebView/Flutter⽀持不完善所以如果一个⻚面存在Flutter书写、WebView或者亮色的图片,建议还是使⽤深色模式进行适配。

4.2.如何开启和禁用全局反色

设置是否⽀持全局反色有静态和动态两种方法:                                              

静态方式就是对应用或者activity的主题中声明<item name=”android:forceDarkAllowed”>true</item> 或者 <item name=”android:forceDarkAllowed”>false</item>;

动态⽅法是调用View.setForceDarkAllowed(true)或者View.setForceDarkAllowed(false),对DecorView设置可以对整个窗口起作⽤。

5.联系我们

有任何问题可以随时联系我们:

商务合作:liushuo3@xiaomi.com

产品问题:zhangyanan10@xiaomi.com

研发问题:darkmode@xiaomi.com

小米手机&平板设备规格

本文档描述了小米手机各个型号及小米平板的软硬件规格

表1:小米手机4、小米手机3联通&电信版、红米手机1S 3G&4G移动版、红米手机1S 3G联通版&电信版

项目小米手机4小米手机3联通&电信版红米手机1S 3G&4G移动版红米手机1S 3G联通版&电信版
屏幕尺寸5.0英寸5.0英寸4.7英寸4.7英寸
系统识别屏幕尺寸NORMALNORMALNORMALNORMAL
屏幕分辨率1920 * 10801920 * 10801280 * 7201280 * 720
像素密度xxhdpixxhdpixhdpixhdpi
CPU骁龙™ 8X74AC 801 四核高通骁龙 800 8274AB 四核MTK MT6582四核(联)高通骁龙400 MSM8228(电)高通骁龙400 MSM8628
GPUAdreno 330Adreno 330Mali-400Adreno 305
内存3072MB2048MB1024MB1024MB
WiFi802.11 a/b/g/n/acWIFI Display WIFI Direct 5GHzWiFi 802.11b/g/n802.11b/g/n
蓝牙BT4.0 + HIDBT4.0 + HIDBT4.0LE +BT3.0HSBT4.0 + HID
定位服务GPS + GLONASS +AGPS+北斗GPS+GLONASS AGPSGPS + AGPSGPS AGPS+GLONASS
系统版本Android 4.4+Android 4.2.1+Android 4.2+Android 4.3+
系统存储16G/64G16G/64G8G8G
外置存储Micro SDMicro SD
后置摄像头
前置摄像头
触摸屏10点触摸10点触摸10点触摸10点触摸
android.os.Build. MANUFACTURERXiaomiXiaomiXiaomiXiaomi
android.os.Build. MODELMI 4WMI 3W&MI 3CHM 1STD HM2014501HM 1SC HM 1SW
陀螺仪支持支持支持支持
距离感应器支持支持支持支持
光线传感器支持支持支持支持
加速度传感器支持支持支持支持
OTG支持支持支持支持
NFC支持

表2: 小米平板、红米手机Note 3G版、红米Note 4G 增强版

项目小米平板红米手机Note 3G版红米Note 4G 增强版
屏幕尺寸7.9英寸5.5英寸5.5英寸
系统识别屏幕尺寸Extra LargeNORMALNORMAL
屏幕分辨率2048 * 15361280 * 7201280 * 720
像素密度xhdpixhdpixhdpi
CPUNVIDIA Tegra K1 四核MTK MT6592 八核高通骁龙400 MSM8928 四核
GPUNVIDIA KeplerARM Mali-450Adreno 305
内存2048MB2048MB1024MB
WiFiWiFi Display/WiFi Direct802.11b/g/n802.11 a/b/g/n/ac
蓝牙BT4.0BT3.0HS+BT4.0(移) BT4.0LE +BT3.0HS(联)BT4.0LE
定位服务不支持GPS定位GPS+AGPSGPS+AGPS +GLONASS +北斗定位
系统版本Android 4.4+Android4.2+Android4.4+
系统存储16G/64G8G8G
外置存储
前置摄像头
后置摄像头
触摸屏10点触摸10点触摸10点触摸
android.os.Build. MANUFACTURERXiaomiXiaomiXiaomi
android.os.Build. MODELMI PADHM NOTE 1LTETD /HM NOTE 1LTEWHM NOTE 1LTETD
陀螺仪支持支持支持
光线传感器支持支持支持
加速度传感器支持支持支持
距离感应器不支持支持支持
OTG支持支持支持
NFC
电子罗盘支持支持支持
气压计不支持支持支持

表3: 小米手机2S、小米手机2A、红米手机、小米手机3 TD版

项目小米手机2S小米手机2A红米手机小米手机3 TD版
屏幕尺寸4.3英寸4.5英寸4.7英寸5.0英寸
系统识别屏幕尺寸NORMALNORMALNORMALNORMAL
屏幕分辨率1280 * 7201280 * 7201280 * 7201920 * 1080
像素密度xhdpixhdpixhdpixxhdpi
CPU高通 骁龙600 1.7G四核高通 骁龙S4 Pro 1.7G双核MTK MT6589T Tagra 4NVIDIA Tegra 4
GPUAdreno 320Adreno 320PowerVR SGX 544MPTagra
内存2048MB1024MB1024MB2048MB
WiFiWIFI Display WIFI DirectWIFI Display WIFI DirectWIFI DirectWIFIDisplay/WIFI Direct
蓝牙BT4.0 + HIDBT4.0 + HIDBT4.0LE +BT3.0HSBT4.0 + HID
定位服务GPS + GLONASS AGPSGPS + GLONASS AGPSGPS + AGPSGPS + GLONASS AGPS
系统版本Android 4.1+Android 4.1+Android 4.2.1+Android 4.2.1+
系统存储16G/32G16G4G16G/64G
外置存储Micro SD
后置摄像头
前置摄像头
触摸屏10点触摸10点触摸10点触摸10点触摸
android.os.Build. MANUFACTURERXiaomiXiaomiXiaomiXiaomi
android.os.Build. MODELMI 2S 或 MI 2SCMI 2A2013022MI 3
陀螺仪支持支持支持支持
距离感应器支持支持支持支持
光线传感器支持支持支持支持
加速度传感器支持支持支持支持
OTG支持支持支持支持
NFC支持支持

表4: 小米手机、小米手机1S、1S青春版、小米手机2

项目小米手机小米手机1S1S青春版小米手机2
屏幕尺寸4.0英寸4.0英寸4.0英寸4.3英寸
系统识别屏幕尺寸NORMALNORMALNORMALNORMAL
屏幕分辨率854 * 480854 * 480854 * 4801280 * 720
像素密度hdpihdpihdpixhdpi
CPU高通 MSM8x60 1.5G双核高通 MSM8260 1.7G双核高通 MSM8260 1.5G双核高通 APQ8064 1.5G四核
GPUAdreno 220Adreno 220Adreno 220Adreno 320
内存1024MB1024MB1024MB2048MB
WiFi
蓝牙BT2.1BT2.1BT2.1BT4.0 + HID
定位服务GPS + AGPSGPS + AGPSGPS + AGPSGPS + GLONASS AGPS
系统版本Android 2.3+Android 2.3+Android 2.3+Android 4.0.3+
系统存储4G4G4G16G/32G
外置存储Micro SDMicro SDMicro SD
后置摄像头
前置摄像头
触摸屏10点触摸10点触摸10点触摸10点触摸
android.os.Build. MANUFACTURERXiaomiXiaomiXiaomiXiaomi
android.os.Build. MODELMI-ONE PlusMI 1S M1 1SCMI 1S M1 1SCMI2
陀螺仪支持支持支持支持
距离感应器支持支持支持支持
光线传感器支持支持支持支持
加速度传感器支持支持支持支持
OTG支持
NFC

文件过滤以及芯片支持的技术文档

小米手机3TD版和小米平板使用的是NVDIA的显卡,apk的supports-gl-texture声明中至少有一个texture是该设备支持的texture。这也是该apk在小米应用商店中不被过滤,可以被现实的前提。 文件过滤以及芯片支持的技术文档 Android的所有应用,都可以通过其中的AndroidManifest.xml文件中的< supports-gl-texture >标签声明该apk文件支持的gl-texture。 同时,设备根据GPU的不同支持的gl-texture也不相同。 小米手机3TD版和小米平板使用的是NVDIA的显卡,apk的supports-gl-texture声明中至少有一个texture是该设备支持的texture。这也是该apk在小米应用商店中不被过滤,可以被现实的前提。

  • 小米平板支持的gl-texture GL_EXT_color_buffer_half_float, GL_EXT_debug_label, GL_EXT_debug_marker, GL_EXT_map_buffer_range, GL_EXT_robustness, GL_EXT_texture_compression_dxt1, GL_EXT_texture_compression_s3tc, GL_EXT_texture_format_BGRA8888, GL_EXT_unpack_subimage, GL_KHR_debug, GL_NV_bgr, GL_NV_secure_context, GL_NV_texture_compression_s3tc, GL_OES_EGL_image, GL_OES_EGL_image_external, GL_OES_EGL_sync, GL_OES_compressed_ETC1_RGB8_texture, GL_OES_compressed_paletted_texture, GL_OES_draw_texture, GL_OES_element_index_uint, GL_OES_fbo_render_mipmap, GL_OES_framebuffer_object, GL_OES_matrix_get, GL_OES_packed_depth_stencil, GL_OES_point_size_array, GL_OES_point_sprite, GL_OES_read_format, GL_OES_rgb8_rgba8, GL_OES_stencil8, GL_OES_texture_cube_map, GL_OES_texture_npot, GL_OES_vertex_half_float,
  • 小米手机3 TD版支持的gl-texture GL_EXT_bgra, GL_EXT_debug_label, GL_EXT_debug_marker, GL_EXT_texture_compression_dxt1, GL_EXT_texture_compression_s3tc, GL_EXT_texture_format_BGRA8888, GL_EXT_unpack_subimage, GL_NV_texture_npot_2D_mipamap, GL_OES_EGL_image, GL_OES_EGL_image_external, GL_OES_EGL_sync, GL_OES_byte_coordinates, GL_OES_compressed_ETC1_RGB8_texture, GL_OES_compressed_paletted_texture, GL_OES_draw_texture, GL_OES_extended_matrix_palette, GL_OES_fbo_render_mipmap, GL_OES_fixes_point, GL_OES_framebuffer_object, GL_OES_matrix_get, GL_OES_matrix_palette, GL_OES_point_size_array, GL_OES_point_sprite, GL_OER_query_martrix, GL_OES_read_format, GL_OES_rgb8_rgba8, GL_OES_single_precision, GL_OES_stencil8, GL_OES_texture_cube_map, GL_OES_vertex_half_float,

VersionCode和VersionName是什么意思?

VersionCode和VersionName是什么意思?

各位Android应用开发爱好者和运营团队在小米应用商店的运营中,常常遇到因为不明白一些Android的概念而造成的困扰。因此我们准备了一些基础知识。

一、简单讲讲

Google为APK定义了两个属性:VersionCode和VersionName,他们有不同的用途。

  • VersionCode:对消费者不可见,仅用于应用市场、程序内部识别版本,判断新旧等用途。
  • VersionName:展示给消费者,消费者会通过它认知自己安装的版本,下文提到的版本号都是说VersionName。

结尾有三个常见问题的解决方案

  • 同一个版本号,对应了多个VersionCode怎么办
  • 发布了一个VersionCode错误的版本怎么办
  • 发出去的应用有Bug要换回旧版,怎么操作?

二、然后讲讲前因后果

大家在使用软件和应用时,都会涉及到版本的概念,大家都知道的,比如Win XP,QQ2012,小米桌面1.6。之所以会有版本,主要是因为软件产品一直在发展、变化的。版本的概念可以帮助消费者识别不同时期的产品。

而展现在消费者面前的版本,和开发者内部使用的通常是不同的版本。开发时通常会使用数字作为标志,比如6.1.7600.16385,其实是Win 7第一个正式版的版本号,而Win 7 SP1的版本号是6.1.7601.17514,这样长长一串数字对消费者毫无意义,所以在产品发布时通常会起一个更容易懂的版本。下文中会把Win 7这样的用于展示的版本叫做[VersionName],6.1.7601.17514这样用于程序标识的版本叫做[VersionCode]

早年因为软件主要自己负责自己的分发、升级等方面,所以版本号也相当自由,各家都有不同的规范。但是近年来移动设备崛起,AppStore这样的应 用商店集中分发成了主流。以升级为例,应用商店会负责检查消费者手机上应用的版本,并和商店里面最新的版本比较,如果商店里面的版本比较新,消费者手机上 的版本比较旧,就会提醒消费者升级。

这就涉及到如何识别新、旧的问题。 对于计算机来说,最可靠的判断方式就是数字,数字有很多好处:程序容易判断、格式简单不容易出错、肉眼容易识别等。所以Google要求每个应用都要在 APK安装包中记录这个安装包的[VersionCode],只要拿到这个APK文件,就可以知道它对应的[VersionCode]是多少,应用商店就 会以这个[VersionCode]为准,来判断版本。安装包的[VersionCode]数字越大就越新。这样开发者在开发过程中,每有一个新版本只要 加大一点这个数字就可以了。比如第一个版本的[VersionCode]是1,第二个版本是2。因为开发者可能每天可能会产生多个没有发布的版本,所以这 个数字会增长的很快。

经过一段时间的开发,这个数字会变得比较大,比如16385,这时对一个消费者,这样的数字其实不太具有可识别性,比如说Win 16385和Win 17514在传达信息方面效果并不好,不利于产品的市场推广。因此Google也支持在AKP安装包内记录[VersionName],你可以叫Win 7、Win Vista都没问题,可以满足市场、传播方面的需求,这样[VersionName]其实不具备比较新、旧版本的能力,只是用来展示给消费者看的。

综上所述 VersionCode:对消费者不可见,仅用于应用市场、程序内部识别版本,判断新旧等用途。 VersionName:展示给消费者,消费者会通过它认知自己安装的版本。一般我们说的版本号就是这个。

三、我们在运营应用商店的过程中,发现有的开发者会遇到一些问题

1、同一个VersionName(版本号),对应了多个VersionCode 这种情况很常见。 比如说新版本发布之后,某个商店反馈说存在xxx问题,需要修复、定制等等操作,于是商务找工程师出了个新版本,考虑到是小版本升级,版本号没变化,但是VersionCode已经变了。

  • 可能遇到的问题:如果这个新版只在部分商店上线,就会出现都是3.1版,A商店的版本其实比B商店的新。已经安装了新版本的用户,还会被提示升级,这时候用户会困扰,为什么我装了3.1还要升级到3.1?部分商店为了最新会抓包,导致渠道包流窜,影响运营监控和分析。
  •  解决方案:a.版本号应该和VersionCode一起涨,而且一旦发布新版本,就在所有渠道上架新版。

2、发布了一个VersionCode错误的版本 有时候因为工程师不小心,发布了一个VersionCode过大的版本。 比如1.1.1.20版本的VersionCode写成了111,而1.1.1.27版本的VersionCode写成了11127,但是后面发布1.1.2版希望延续旧的VersionCode,用112。

  • 可能遇到的问题:1.1.1.27版的用户将无法获得1.1.2版本的升级,因为在程序看来1.1.1.27版本是比较新的,同时,已经使用了1.1.2版本的用户,可能会收到旧版本的升级提示,比并降级回旧版
  • 解决方案:其实很简单,因为VersionCode对最终用户是不可见的,只要增加就好了,上文的例子,新版VersionCode直接取11200就齐活了。

3、发布了一个有Bug的版本,好捉急 偶尔会遇到版本已经发布了,第二天突然发现,糟糕,有Bug,用户开始骂了!于是商务同学到各家市场要求退回旧版本。

  • 可能遇到的问题:已经升级到有Bug版本的用户是无法回滚到旧版的,因此这样直接退回旧版本的方式对这些热心升级的用户是非常不负责任的。而且人肉召回的力度实在有限,这个有Bug的版本一定会流传的。
  • 解决方案:最好是不要浪费时间退回旧版,赶紧修复Bug发个新版本(记得加VersionCode),如果Bug比较棘手,建议把旧版本的VersionCode改大一些后,提交新版本,这样可以保证所有用户都能下载/升级到一个相对可靠的版本。

什么是包名 (Package Name)?

小米应用商店按照符合Android标准的原则进行设计,使用包名(Package Name)作为应用的唯一标识。即:包名必须唯一,一个包名代表一个应用,不允许两个应用使用同样的包名。包名主要用于系统识别应用,几乎不会被最终用户看到。

包名的命名规则

只能包含大写字母(A到Z)、小写字母(a到z)、数字和下划线,以用点(英文句号)分隔称为断,至少包含2个断,隔开的每一段都必须以字母开头。

避免包名冲突

因为包名是唯一标识,为了避免与其他应用的包名重复,产生冲突,您可以这样命名:

将您的域名反转过来作为前缀,比如如果您的域名是zan.com,那么包名可以用com.zan开头,这样可以有效的避免重复

在后面增加描述产品名称的字符,比如您的应用是视频应用,可以命名为com.zan.video

如果您没有域名,可以使用自己的邮箱作为前缀,比如 com.xiaomi.WoDeYouXiang

包名冲突如何处理?

如果您发现您尚未发布的应用,包名和其他开发者已经发布的应用重复了,建议立刻修改应用的包名,避免冲突。

如果您的应用已经发布了,但是在小米开发者站上传应用时,被告知已经有其他开发者上传了同包名的应用,可以按照指示,进入问题工单系统,联系我们进行处理。

请注意

应用发布后,请不要修改包名,一旦您修改了包名,就会被当作一个新的应用,旧版用户也无法收到应用商店的升级提醒。

VIVO消息推送 接入push服务注意事项

VIVO消息推送 接入push服务注意事项

开发者接入push服务存在的共性问题排查指南:

一、请接入方先通过本地工具【postmen】先调用我们提供的接口,保证本地调用我们的接口是没有问题【减少在开发过程沟通成本】

二、如果是本地工具接口测试:请先检查一下事项

 1、请先测试推送鉴权接口,获取到 authToken 才可以进行消息推送 【可以确保接入方本地调用push服务是通的】

 2、检查一下当前应用是否是受限应用(受限应用将在2-3个工作日内转为正式)

①如果是受限应用,则只能测试单播接口,测试其他推送接口会有对应提示

②如果是受限应用,那么需要在vivo推送营运平台后台添加要测试的设备【设备id(regId)】最多可以添加20个设备

③如果是受限应用,在调用单播接口的时候,需要在请求参数中确认pushMode==1字段(0:正式推送;1:测试推送,不填默认为0)

   测试推送没有频控限制(受限应用发不了正式推送)

3、检查一下当前推送的消息是运营消息还是系统消息【前提:推送为正式推送】

(接入方在推送的时候 参数 classification==0 , 0:运营类消息,1:系统类消息。不填默认为0)

如果客户端多次收到消息后,又出现收不到的情况

检查消息是否被管控,单用户单应用每天收到的消息条数上限5条,系统消息不受应用频控管控,受系统消息推送总量限制

建议:如果只是检验功能,建议使用测试推送【测试消息不受频控、推送量级管控】

三、关于消息数据统计问题【vivo推送运营后台有相关消息统计明细分布情况】

请各个接入方先到 vivo推送管理后台查看当前应用消息大体的数据统计分布情况

统计分两种:

 ①应用级别的消息统计明细分布情况

 ②单推统计明细分布情况

【可以通过这两个指标,进一步分析消息没有达到的原因】    

同时:建议接入方在关键地方也收集数据。比如消息达到客户端,建议应用方也做一个记录。

对我们接口返回的regId(1.userId不存在;2.卸载或者关闭了通知;3.七天不在线;4.非测试用户),这些状态也存储一下,可以预防无效的推送

四、如遇接口返回状态码 10206 sign 不正确提示 【前提:一样的签名方法, 偶现签名不正确】

如果出现这种情况:

就是业务方在进行签名的时候 appId/appKey/appSecret 存在本来给“应用A”生成的签名,结果把sign拿给“应用B”进行签名了

【签名:使用MD5算法,字符串trim后拼接(appId+appKey+timestamp+appSecret),然后通过MD5加密得到的值(字母小写)】

请接入方在有多个应用的时候,要注意签名方法的使用,防止签名误传

五、如遇接口返回状态码 10000 权限认证失败,则表示应用方获取的authToken 失效了 ,请重新获取

六、regId升级

原有token(regId)生成规则是固定23位数字。已不能满足后续增长需求,推送平台从2022年5月开始升级token(regId)生成规则,取消现有固定23位长度及数字限制,新规则长度可变,包含字符“0-9”、“a-z”、“A-Z”及特殊字符。2022年7月30号全量升级。老的regId不变,新订阅会按照新regId规则生成。

七、如何发送测试消息图解

接入Vpush后的应用均可以发送测试消息。发送测试消息的步骤如下:

1、  先在推送运营后台添加测试设备。

1)  在推送平台找到你的应用名称

2)  在刚才的基础之前要点击测试设备

3)  到了这个页面  要点击添加测试设备

4)  添加具体信息点击确定

2、然后接入服务端API,通过调用/message/send,pushMode设置为1,给第一步绑定成功的测试设备发送消息。详情请见《服务端API接口文档》

说明:

1、  添加测试设备为接入客户端SDK,订阅获取到的regId,通过调用客户端api接口的getRegId方法获取,详情请见《客户端API接口文档》

2、最多支持添加20个测试设备

3、测试消息不受量级和频次限制。

VIVO消息推送 Android PUSH-SDK集成指南

点击此处下载 PUSH SDK接入文档(若公司网络下载压缩包解压异常,建议切换其他网络下载)

版本信息具体说明
版本号:484、版本名:3.0.0.4更新内容:
1.优化代码,去掉非必要逻辑;
版本号:483、版本名:3.0.0.3更新内容:
1.修复了读取外部存储的问题;
版本号:482、版本名:3.0.0.2更新内容:
1.恢复了仅用于兼容v3.0.0.0_480以前点击回调接口:onNotificationMessageClicked;
版本号:481、版本名:3.0.0.1更新内容:
1.修复统一推送联盟接口的已知问题;
版本号:480、版本名:3.0.0.0更新内容:
1.修复安全漏洞:通知不再支持拉起非导出的Activity;
2.优化push通知点击启动慢的问题;
3.移除onNotificationMessageClicked回调,自定义参数需要统一在被拉起的Activity中通过Intent接收;

注意:

1.vivo推送服务SDK支持的最低android版本为Android 6.0。

2.当通过”自定义/打开应用页面”方式启动应用内Activity时,该Activity在AndroidManifest.xml必须配置属性android:exported=”true”。

3.由于项目架构变动,可能会导致您在更新sdk版本时类的路径错误,重新导入类的路径即可。

一、集成sdk

1. 导入aar 包

将解压后的libs文件夹中vivopushsdk-VERSION.aar(vivopushsdk-VERSION.aar为集成的jar包名字,VERSION为版本名称)拷贝到您的工程的libs文件夹中。

在android项目app目录下的build.gradle中添加aar依赖。

dependencies {

  implementation fileTree(include: ['*.jar'],   dir: 'libs')

  implementation   files("libs/vivo_pushSDK_v3.0.0.4_484.aar")

}

2. 添加权限

vivo Push集成只需要配置网络权限,请在当前工程AndroidManifest.xml中的manifest节点下添加以下代码:

<!—Vivo Push需要的权限--> 

<uses-permission  android:name="android.permission.INTERNET"/>

3. 配置appid 、api key等信息

vivo Push集成需要配置对应的appid 、app key信息,其中appid 和app key是在开发者平台中申请的,详见 vivo push 操作手册。

请在当前工程AndroidManifest.xml中的Application节点下添加以下代码(建议复制粘贴防止出错):

<!--Vivo Push开放平台中应用的appid 和api key--> 
<meta-data 
   android:name="api_key" 
   android:value="xxxxxxxx"/> 

<meta-data 
   android:name="app_id" 
   android:value="xxxx"/>

4. 自定义通知回调类

在当前工程中新建一个类 PushMessageReceiverImpl(自定义类名)继承OpenClientPushMessageReceiver 并重载实现相关方法。并在当前工程的AndroidManifest.xml文件中,添加自定义Receiver信息,代码如下:

<!--push应用定义消息receiver声明--> 
<receiver android:name="xxx.xxx.xxx.PushMessageReceiverImpl(自定义类名)" 
   android:exported="false">    
<intent-filter> 
	<!--接收push消息--> 
   <action android:name="com.vivo.pushclient.action.RECEIVE"/> 
</intent-filter>
</receiver>

5. 注册service

接入SDK,需注册相关服务以确保正常。

请在当前工程AndroidManifest.xml中的Application节点下添加以下代码(建议复制粘贴防止出错):

<!--Vivo Push需要配置的service、activity--> 
<service 
   android:name="com.vivo.push.sdk.service.CommandClientService" 
   android:permission="com.push.permission.UPSTAGESERVICE"
   android:exported="true"/>

6. 配置sdk版本信息(仅通过jar包集成方式需要配置,通过aar包集成无需配置)

通过jar包方式接入SDK,需配置SDK版本信息确保正常。

请在当前工程AndroidManifest.xml中的Application节点下添加以下代码(建议复制粘贴防止出错):

<!--Vivo Push SDK的版本信息--> 
<meta-data 
   android:name="sdk_version_vivo" 
   android:value="484"/>

二、启动推送

在工程的Application中,添加以下代码,用来启动打开push开关,成功后即可在通知消息到达时收到通知。

//在当前工程入口函数,建议在Application的onCreate函数中,添加以下代码:

//初始化push
PushClient.getInstance(getApplicationContext()).initialize(); 

// 打开push开关, 关闭为turnOffPush,详见api接入文档
PushClient.getInstance(getApplicationContext()).turnOnPush(new IPushActionListener() { 
    @Override
    public void onStateChanged(int state) { 
       // TODO: 开关状态处理, 0代表成功
    } 
});

三、获取token

即获取regId,使用PushClient.getInstance(context).getRegId() 函数获取;

在 Api 接口 turnOnPush回调成功之后,即可获取到注册id。

四、点击通知消息

当设备接收到通知消息后,查看手机的通知栏,当点击通知时,打开通知动作分为打开App首页、打开特定Uri 网址页面、 打开用户自定义、打开应用指定页面。

注意: Sdk 3.0.0.0 以前版本的页面跳转类型打开自定义、打开指定应用页面,在Sdk 3.0.0.0及以后版本中已统一作为打开自定义页面处理。 服务端Api 字段 skipType 跳转类型分别是: 1 是打开App 首页, 2 是打开特定Url 网址页面, 4 是打开自定义页面。

打开App首页或者打开自定义页面,是通过VIVO手机通知中心跨应用启动Activity来实现,需要App保证被拉起的目标Activity exported属性默认设置为true,无权限配置,可以在点击通知时打开指定的Activity。

1. 打开App 首页

在AndroidManifest.xml文件配置主Activity。

在AndroidManifest.xml文件注册的首页Activity 中,配置
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

在Activity 中接受数据:

开发者在首页的Activity 的onCreate 或者 onNewIntent 中,通过如下方式获取数据。

获取消息id,即messageId:

String messageId = intent.getLongExtra("vivo_push_messageId");

获取透传的自定义键值对值,如下,

遍历所有key(遍历clientCustomMap和skipContent的自定义key-value):

Bundle bundle = intent.getExtras();
if (bundle != null) {
    for (String key : bundle.keySet()) {
        if (!TextUtils.isEmpty(key)) {
            //注意传递的参数类型
            String content = bundle.getString(key);
        }
    }
}

取单个key(取clientCustomMap和skipContent特定key对应的value):

Intent intent = getIntent();
if (intent != null) {
    String key1 = intent.getStringExtra("key1");
    int key2 = intent.getIntExtra("key2", -1);
}
其中key1为用户自定义String型键值对参数值;key2为用户自定义Integer型键值对参数值。

2. 打开自定义页面

注意:原有通过onNotificationMessageClicked回调接收自定义参数的方式已经废弃,自定义参数需要统一在被拉起的Activity中通过Intent接收。

跨应用启动客户端App需要显示启动,通过Intent 携带透传参数到App,生成好对应的 Intent 参数,然后调用服务端Api 指定Intent 参数来打开自定义App页面;

生成 Intent 参数:

在Android 开发工具中,参考如下代码生成 Intent
Intent intent = new Intent(this,CustomActivity.class);
//Scheme协议(vpushscheme://com.vivo.push.notifysdk/detail?)开发者可以自定义
intent.setData(Uri.parse("vpushscheme://com.vivo.push.notifysdk/detail?"));
//intent 中添加自定义键值对,value 为 String 型
intent.putExtra("key1", "xxx"); 
//intent 中添加自定义键值对,value 为 Integer 型
intent.putExtra("key2", xxx);
//得到intent url 值
//示例:intent://com.vivo.pushtest/detail?#Intent;scheme=vpushscheme;component=com.vivo.pushdemo.test/com.vivo.pushsdk.CustomActivity;S.key1=xxx;i.key2=2;end
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
备注 : 开发者以自己实际定义的为准。

注意:在AndroidStudio里生成intentUri后,开发者通过服务端Api或者在管理后台发送通知时,跳转内容(Api 对应字段 为skipContent)透传上例生成的intentUri值,然后在点击通知时打开自定义的 CustomActivity。

在AndroidManifest.xml文件注册被启动的Activity

比如被启动的自定义页面 CustomActivity,其中host、path、scheme 一定要与上面的 Intent 生成参数匹配。

注意:该属性必须设置android:exported=”true”

配置如下:

<activity android:name=".CustomActivity"   
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="com.vivo.push.notifysdk"
            android:path="/detail"
            android:scheme="vpushscheme" />
        </intent-filter>
</activity>

注意: activity 名称用户自己定义.

在自定义的 CustomActivity 中接收数据

如下:

public class CustomActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.xxx);
        //获取通知消息的messagId
        String messageId = intent.getStringExtra("vivo_push_messageId");
        //获取自定义透传参数值
        Intent intent = getIntent();
        if (null != intent) {
            String key1 = intent.getStringExtra("key1");
            int kye2 = intent.getIntExtra("key2", -1);
        }
    }
}

3. 打开特定Uri 网址

开发者通过Api(Api 对应字段 为skipContent)或者管理后台传自己要打开的Url 网址地址即可。

4. 恢复了仅用于兼容v3.0.0.0_480以前点击回调接口:onNotificationMessageClicked

注意Push SDKv3.0.0.2_482特性:该接口仅用于解决v3.0.0.0_480之前的版本升级Push SDK过程中发送的老版本打开自定义通知(skiptype=3)需要依赖点击回调完成跳转时使用,
  新版本通知点击该点击回调是不可用的。

五、混淆说明

若需要混淆app,请在混淆文件中添加以下说明,防止SDK内容被二次混淆,自定义回调类切勿混淆。

-dontwarn com.vivo.push.** 

-keep class com.vivo.push.**{*; } 

-keep class com.vivo.vms.**{*; }

-keep class   xxx.xxx.xxx.PushMessageReceiverImpl{*;}

六、统一推送联盟接入

说明:请完成上述 ‘1.集成SDK’ 和 ‘2.配置信息’ 两个步骤再开始统一推送联盟的接入。

1. 打开push开关

这里只是做了相应的初始化操作,建议用户在自己应用的Application中onCreate()方法中调用turnOnPush操作。

示例代码:

VUpsManager.getInstance().turnOnPush(this, new UPSTurnCallback() {
    @Override
    public void onResult(CodeResult codeResult) {
        if(codeResult.getReturnCode()   == 0){
            Log.d(TAG, "初始化成功");
        }else {
            Log.d(TAG, "初始化失败");
        }
    }
});

2. 注册push

注册push,获取申请的regId,即token。

示例代码:

VUpsManager.getInstance().registerToken(this, "XXX", "XXX", "XXX", new UPSRegisterCallback() {
    @Override
    public void onResult(TokenResult tokenResult) {
        if (tokenResult.getReturnCode() == 0) {
            Log.d(TAG, "注册成功 regID = " +   tokenResult.getToken());
        } else {
            Log.d(TAG, "注册失败");
        }
    }
});

VIVO消息推送 Android PUSH-SDK API接口文档

VIVO消息推送 Android PUSH-SDK API接口文档

点击此处下载 PUSH SDK接入文档

版本号:3.0.0.4

一、 接口概述

本SDK中有两个开放类,分别为:Push操作类PushClient、回调接收类OpenClientPushMessageReceiver/ IPushActionListener。

PushClient 为功能接口,用于调用Push相关功能; 

IPushActionListener 为操作回调接口,用于功能接口状态回调;

OpenClientPushMessageReceiver 为回调接口,用于Push的数据结果返回;

1. PushClient功能类

PushClient提供Push服务的对外API列表,采用单例模型,通过getInstance(Context context)获得该对象。

initialize      初始化Push服务;

checkManifest   检查AndroidManifest是否正确声明组件和权限;

turnOnPush      打开PUSH;

turnOffPush     关闭PUSH;

getRegId        获取当前设备的当前应用的唯一标识;

bindAlias       设置应用别名;

unBindAlias     取消应用别名;

getAlias        获取应用别名;

setTopic        设置主题;

delTopic        删除主题;

getTopics       获取主题;

isSupport       当前系统是否支持PUSH;

2. IPushActionListener操作回调类

IPushActionListener类提供PushClient的操作回调。

onStateChanged  操作状态返回,详见操作码;

3.OpenClientPushMessageReceiver操作回调类

OpenClientPushMessageReceiver类提供基础消息的接收和操作结果的反馈,需要开发者继承本类,并重载相关的方法;同时,还需要在AndroidManifest.xml静态注册。

onReceiveRegId  RegId结果返回,只有首次获取到或regId发生变化时才会回调;

onNotificationMessageClicked  通知被点击时回调(仅用于兼容老版本)。

4. 公共状态码

状态码用于返回各项操作的结果,常用于回调接收类中状态返回,以下为公共状态码:

0       操作成功;

1       操作成功,此动作在未操作前已经设置成功;

101     系统不支持;

102     PUSH初始化异常,请重现初始化PUSH;

1001    一天内调用次数超标;

1002    操作频率过快;

1003    操作超时;

1004    应用处于黑名单;

1005    当前push服务不可用;

10000   未知异常;

10001   topic错误,例如传入appid/;

10002   topic错误, 例如appid/null;

10003   app包名与配置不匹配,例如传入com.yyy;

10004   appkey不匹配,例如传入appkey:bcd不存在;

10005   appid传入错误,例如未申请此appid,传入111;

10006   别名长度超过40;

10007   别名订阅时appkey不存在;

10008   开放平台暂不支持tag订阅;

二、 API接口

PushClient类

① Initialize

功能介绍:初始化push服务,可以提高后台发送消息的实时性。

接口定义:void initialize();

补充:建议每次手机启动后,都调用一次,确保Push服务能够正常运行。

② turnOnPush

功能介绍:打开应用push开关,绑定应用,成功后便可接收到当前应用的推送消息。

接口定义:void turnOnPush(IPushActionListener listener);

参数说明:listener: 状态监听;

补充:打开push成功后无需重复调用。

③ turnOffPush

功能介绍:关闭应用push开关,解除绑定应用,解绑后将收不到当前应用的推送消息。

接口定义:void turnOffPush(IPushActionListener listener);

参数说明:listener: 状态监听;

补充:关闭push成功后无需重复调用。

④ getRegId

功能介绍: 获取当前设备的当前应用的唯一标识,后台可基于此标识发送通知。

接口定义:String getRegId();

返回值:当前设备的当前应用的唯一标识;

补充:此方法仅在打开PUSH成功后可以获取,否则为null。

⑤ bindAlias

功能介绍:在注册成功,收到regId之后,即可设置别名,绑定当前设备的当前应用的别名,可以理解为regId的别名,开发者可以将别名设置为自己应用帐号系统的帐号,或者设备标识等。然后通过此别名发送消息。

接口定义:bindAlias(String alias, IPushActionListener listener);

参数说明:alias:别名; listener: 状态监听。

**状态码 描述**

30001   设置别名失败:请打开push开关;

30002   设置别名失败:订阅别名为空;

30003   设置别名失败:别名设置超长,字符长度超过70;

补充:绑定别名,同一个别名仅能绑定一个regId。当regId已绑定了别名A,若调用此接口绑定别名B,则与别名A的绑定关系会自动解除。此接口与 unBindAlias 一天内最多调用100次,两次调用的间隔需大于2s。

⑥ unBindAlias

功能介绍:删除别名,解除绑定当前应用别名,解绑成功后后台将无法通过别名的方式向应用发消息。

接口定义:

void unBindAlias(String alias);
void unBindAlias(String alias, IPushActionListener listener);

参数说明: alias:别名; listener:状态监听。

**状态码 描述**

30001   删除别名失败:请打开push开关;

30002   删除别名失败:订阅别名为空;

30003   删除别名失败:别名设置超长,字符长度超过70;

补充:此接口与 bindAlias 一天内最多调用100次,两次调用的间隔需大于2s。

⑦ getAlias

功能介绍:获取当前设备的应用别名,后台可基于此别名发送通知。

接口定义:String getAlias();

返回值:当前设备的应用别名。

⑧ checkManifest

功能介绍:校验接入是否异常。通过调用该API来检查AndroidManifest.xml是否正确声明了本SDK要求的所有组件和权限。当有组件和权限未定义,或者组件的属性声明错误时抛出异常VivoPushException。

接口定义:void checkManifest()。

⑨ setTopic

功能介绍:在注册成功,收到regId之后,即可设置主题;开发者可根据用户订阅的主题实现分组。

接口定义:setTopic(String topic, IPushActionListener listener);

参数说明:topic : 需要订阅的主题名; listener : 状态监听。

**状态码 描述**

20001   设置主题失败:请打开push开关;

20002   设置主题失败:订阅主题为空;

20003   设置主题失败:别名设置超长,字符长度超过70;

20004   设置主题失败:订阅次数太频繁或已订阅数过多;

补充:同一个regId可设置多个主题,最多可订阅500个主题。当regId已设置了topicA,若调用此接口设置topicB,则regId同时订阅了topicA和topicB。此接口与 delTopic 一天内最多调用500次,两次调用的间隔需大于2s。

⑩ delTopic

功能介绍:删除已经设置的主题。

接口定义:delTopic(String topic, IPushActionListener listener);

参数说明:topic 需要取消订阅的主题名; listener 状态监听。

**状态码 描述**

20001   设置主题失败:请打开push开关;

20002   设置主题失败:订阅主题为空;

20003   设置主题失败:别名设置超长,字符长度超过70;

20004   设置主题失败:订阅次数太频繁或已订阅数过多;

补充:此接口与 setTopic 一天内最多调用500次,两次调用的间隔需大于2s。

⑪ getTopics

功能介绍:获取当前设备的应用主题,后台可基于此主题发送通知。

接口定义:List getTopics();

返回值:当前设备已经设置的应用主题;

⑫ isSupport

功能介绍:用于判断当前系统是否支持PUSH服务。

接口定义:boolean isSupport();

返回值:true 系统支持; false 系统不支持。

⑬ onReceiveRegId

功能介绍:RegId结果返回。当开发者首次调用turnOnPush成功或regId发生改变时会回调该方法。

接口定义:void onReceiveRegId(Context context, String regId);

参数说明:context : 应用上下文; regId: 当前设备的当前应用的唯一标识;

⑭ onNotificationMessageClicked(仅用于兼容老版本)

功能介绍:通知被点击后的结果返回。当push发出的通知被点击后便会触发onNotificationClicked通知应用。

接口定义:void onNotificationMessageClicked(Context context, UPSNotificationMessage msg);

参数说明:context : 应用上下文; msg: UPSNotificationMessage通知消息结构体;

**UPSNotificationMessage 包含以下字段**
msgId:通知id。
title:通知标题。
content:通知内容。
skipContent:通知自定义内容。
params:自定义键值对。

三、统一推送联盟API介绍

① turnOnPush

功能介绍:做了相应的初始化操作,建议用户在自己应用的Application中的onCreate()方法中调用turnOnPush操作。

接口定义:

void turnOnPush(Context context, UPSTurnCallback callback)

参数说明:

context : 应用上下文;

Callback:UPSTurnCallback 回调结构,包含以下方法;

 .getReturnCode()  获取返回状态,0代表成功,其他值代表失败。

② registerToken

功能介绍:注册push,获取申请的regId

接口定义:

void registerToken(final Context context, String appID, String appKey, String appSecret, final UPSRegisterCallback callback)

参数说明:

context : 应用上下文;

appID: 应用在Vivo开放平台申请的APPId;

appKey: 应用在Vivo开放平台申请的APPKey;

appSecret: 应用在Vivo开放平台申请的APPSecret;

callback: UPSRegisterCallback回调结构,包含以下方法;

 .getReturnCode() 获取返回状态,0代表成功,其他值代表失败;

 .getToken()  获取应用申请的regId。

③ unRegisterToken

功能介绍:接注册push,关闭push功能

接口定义:

void unRegisterToken(Context context, final UPSRegisterCallback callback)

参数说明:

context : 应用上下文;

Callback:UPSRegisterCallback回调结构,包含以下方法;

.getReturnCode():获取返回状态,0代表成功,其他值代表失败。

④ turnOffPush

功能介绍:该功能暂时未具体实现,要关闭push功能,请调用上面的unRegisterToken接口

接口定义:

void turnOffPush(Context context, final UPSTurnCallback callback)

参数说明:

context : 应用上下文;

Callback:UPSTurnCallback回调结构,包含以下方法;

.getReturnCode():获取返回状态,0代表成功,其他值代表失败。

VIVO消息推送服务端SDK文档

VIVO消息推送服务端SDK文档

点击此处下载PUSH-JAVA-SDK 文档

版本:2.3 

升级内容:

      1.  新增推必安审核参数auditReview。

      2.  取消regId23位校验限制。

点击此处下载push-python3-SDK 文档

版本:2.2

一、接入SDK

1.运行环境

该SDK使用Java编写,接入前请确认是否安装Java环境,并在Java环境下运行。

2.获取SDK并导入

开发者需要注册登录开发平台网站获取应用的appId,appKey,appSecret;

在开发者网站上,下载并解压vivoPush_sdk_JAVA.zip;

将文件夹下所有jar文件放入项目工程的libs目录;

刷新工程,确保文件出现在libs目录下。如果没有的话请手动添加;

3.示例:给测试手机发送一条单推

集成sdk后运行该main函数,标红部分为需要使用者填写的内容。运行成功后设备会收到推送(需提前确认设备通知栏权限已打开)

public   static void main(String[] args) throws Exception {
      Sender sender = new Sender(“appSecret”);//注册登录开发平台网站获取到的appSecret
      Result result = sender.getToken(appId ,   “appKey”);//注册登录开发平台网站获取到的appId和appKey
      sender.setAuthToken(result. getAuthToken());
      Message singleMessage = new Message.Builder()
              //该测试手机设备订阅推送所得的regid,且已添加为测试设备.regId(“regId”)              .notifyType(3)
                .title(“try_title”)
                .content(“try-content”)
              .timeToLive(1000)
                .skipType(2)
                .skipContent(“http://www.vivo.com”)
                .networkType(-1)
                .requestId(“1234567890123456”)              .pushMode(1)              .build();
      Result resultMessage = sender.sendSingle(singleMessage);
      System.out.println(resultMessage);
  }

4.SDK类定义说明

类名使用说明
Message消息对象
Builder构建要发送的Message对象
TargetMessage构建批量推送的发送目标
TagMessage标签相关的消息体
TagGroupMessage标签分类的消息体
TagSegMessage标签组合相关的消息体
Sender发送消息工具类,可以发送鉴权、单推、批量推、全推、标签推消息
TagManage创建标签工具类,用于创建,更新标签
TagGroup标签分类管理工具类,用于创建,更新标签分类
TagSegment标签组合管理工具类,用于创建,更新标签组合
Result服务器返回的结果
Validation对构建的消息体进行基本参数校验
ExceptionStatusEnum消息体参数错误类型

二、发送消息

①发送消息依赖Sender类

com.vivo.push.sdk.server.Sender

标签相关的设置依赖以下三个类

com.vivo.push.sdk.server.TagManage

com.vivo.push.sdk.server.TagGroup

com.vivo.push.sdk.server.TagSegment

②实例化Sender

Sender(String appSecret),(鉴权时使用)appSecret是在开发者网站上注册时生成的。

sender.setAuthToken(String authToken);,(推送时使用)除鉴权方法外,推送前都需要设置authToken,authToken是在调用鉴权方法后获得。

③设定连接池参数(可选项)

Sender.initPool(int connection, int route) 设定连接池最大连接数为“connection”,路由最大连接数为“route”,不设定该项则使用默认参数:最大连接数 10,路由最大连接数 5

④返回结果Result

com.vivo.push.sdk.server.Result

1.鉴权

要进行PUSH推送,任何接入方都要有个鉴权操作。获得authToken用于各类推送。

限制:一天限制调用不超过10000次。

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
getToken(int   appId,String appKey)根据appId,appKey(用户申请推送业务时生成)进行鉴权操作。

Demo

public void testGetToken() throws Exception   {          Sender sender = new     Sender(APP_SECRET);//实例化Sender              sender.initPool(20,10);//设置连接池参数,可选项          Result result =   sender.getToken(APP_ID,APP_KEY);//发送鉴权请求            result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述              result.getAuthToken();//如鉴权请求发送成功,获得authToken    }

2.单推

接入方携带消息内容以及用户regId(或alias:别名)进行通知消息推送。针对每个用户发送不同的通知。

使用场景:如物流、订单状态、游戏预约状态、行程状态、聊天(如微信、评论)等。

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
sendSingle(Message   singleMessage)根据消息体singleMessage中设定的regId或alias发送消息到指定设备上。

Demo

public   void singeSend() throws Exception {          Sender sender = new     Sender(APP_SECRET);sender.initPool(20,10);//设置连接池参数,可选项sender.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          Message singleMessage     = new Message.Builder().~.build();//构建单推消息体          Result result =     sender.sendSingle(singleMessage);//发送单推请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result.getTaskId();//如单推请求发送成功,将获得该条单推消息的任务编号,即taskId          result. getInvalidUser();//非法用户信息,包括status和userid          result.   getInvalidUser().getStatus();//非法用户信息状态,包括四种情况, 1 userId不存在。 2卸载或者关闭了通知。 3 14天不在线。4 非测试用户          result.   getInvalidUser().getUserid();//非法的用户信息,即接入方传的regid或者alias      }

3.批量推送

3.1保存群推消息

同一条信息覆盖多个用户。此方法需与批量推送用户方法2.3.2配套使用,批量推送用此方法返回的taskId批量发送用户。

使用场景:活动、系统升级提醒等。

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
saveListPayLoad(Message   listPayLoad)把构建的消息体listPayLoad发送保存至服务器上,返回该消息的taskId

Demo

public void saveListPayload()   throws   Exception {          Sender sender = new   Sender(APP_SECRET);sender.initPool(20,10);//设置连接池参数,可选项sender.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          Message saveList =   new   Message.Builder().~.build();//构建要保存的批量推送消息体          Result result =     sender. saveListPayLoad(saveList);//发送保存群推消息请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result.getTaskId();//如请求发送成功,将获得该条消息的任务编号,即taskId    }

3.2批量推送用户

批量发送给用户。该方法与保存群推消息方法2.3.1配套使用,首先通过2.3.1获得taskId,然后使用该taskId,根据regIds或者aliases进行批量推送。

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
sendToList(TargetMessage   targetMessage)把某条消息批量发送给多个用户

Demo

public   void listSend() throws Exception {          Sender sender = new     Sender(APP_SECRET);              sender.initPool(20,10);//设置连接池参数,可选项sender.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          Set<String>     regid = new HashSet<>();//构建批量推送用户群          regid.add(taskId1);          regid.add(taskId2);          …          TargetMessage     targetMessage = new   TargetMessage.Builder().~.build();//构建批量推送的消息体          Result result =     sender.sendToList(targetMessage);//批量推送给用户result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result. getInvalidUsers();//非法用户信息列表,其中每个非法用户信息包括status和userid两个属性,userid为接入方传的regid或者alias,status有四种情况:1 userId不存在 2卸载或者关闭了通知 3 14天不在线 4非测试用户      }

4.全量推送

向所有设备推送某条消息。

使用场景:活动、系统升级提醒等。

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
sendToAll(Message   allMessage)把构建的消息allMessage发送给所有设备

Demo

public void allSend() throws     Exception {          Sender sender = new     Sender(APP_SECRET);              sender.initPool(20,10);//设置连接池参数,可选项sender.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          Message allSendMessage     = new Message.Builder().~.build();//构建要全量推送的消息体          Result result =     sender. sendToAll(allSendMessage);//发送全量推送消息请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result.getTaskId();//如请求发送成功,将获得该条消息的任务编号,即taskId    }

5.标签推

接入方携带消息内容、标签信息进行通知消息推送。根据标签把消息推送给指定用户

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
sendToTag(Message   tagMessage)把构建的消息发送给标签圈定的用户

Demo

public void tagSend() throws Exception     {          Sender sender = new   Sender(APP_SECRET);              sender.initPool(20,10);//设置连接池参数,可选项sender.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          Message   tagSendMessage   = new Message.Builder().~.build();//构建要全量推送的消息体          Result result =     sender. sendToTag(tagSendMessage);//发送标签推送消息请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result.getTaskId();//如请求发送成功,将获得该条消息的任务编号,即taskId    }

6.消息体创建

6.1通知栏消息体

com.vivo.push.sdk.server.Message.Builder

Builder方法列表

方法说明
Builder()构造方法
regId(String value)仅单推时需设定(其它推送无需设定该项),单推可通过regId推送给指定用户。应用订阅PUSH服务器得到的id ,长度23个字符(regId,alias 两者需一个不为空,当两个不为空时,取regId)
alias(String value)仅单推时需设定(其它推送无需设定该项),单推可通过alias推送给指定用户。应用订阅PUSH服务器别名,长度不超过40字符(regId,alias 两者需一个不为空,当两个不为空时,取regId)
orTagss(List<String> valus)仅标签推送时需设定(其他推送无需设定该项),标签表达式包含三种数组: notTags表示非操作、andTags表示与操作,orTagss表示或操作,例如:                     “notTags”:[“琴”,”棋”,”书”,”画”],                      “andTags”:[“深圳”,”广东”],                      “orTagss”:[“本科生”,”研究生”]可以表示为,不会琴、棋、书、画的广东省深圳市的本科生或研究生的所有用户。这些标签需要先在平台,接口,或调用该说明文档3部分的方法,创建相应标签后再使用。具体使用方式可参考下面的DEMO和文档5.3部分
andTags(List<String> valus)
notTags(List<String> valus)
title(String value)必填项,设置通知标题(用于通知栏消息),最大20个汉字(一个汉字等于两个英文字符,即最大不超过40个英文字符)
content(String value)必填项,设置通知内容(用于通知栏消息)   最大50个汉字(一个汉字等于两个英文字符,即最大不超过100个英文字符)
notifyType(int value)必填项,设置通知类型,value类型支持以下值:1:无2:响铃3:振动4:响铃和振动
timeToLive(int value)可选项, 消息的生命周期, 若用户离线, 设置消息在服务器保存的时间, 单位: 秒默认时间:1天最长时间:7天最少时间:单推,60秒         其它,900秒
skipType(int value)必填项,设置点击跳转类型,value类型支持以下值:1:打开APP首页2:打开链接3:自定义4:打开app内指定页面
skipContent(String value)可选项,跳转内容跳转类型为2时,跳转内容最大1000个字符,跳转类型为3或4时,跳转内容最大1024个字符
networkType(int value)可选项,发送推送使用的网络方式,value支持以下值:-1:方式不限1:仅在wifi下发送不填默认为-1
clientCustomMap(String key, String         value)可选项,客户端自定义键值对,自定义key和value键值对个数不能超过10个,且长度不能超过1024字符,   key和value键值对总长度不能超过1024字符。
extra(String callback, String param)可选项,仅单推中使用,提供了高级特性(消息送达回执)。callback参数:不能为null,是第三方接收回执的http接口,最大长度128个字符,vivo推送服务器将已送达或和设备对应的alias或者regId通过调用第三方设置的回调http接口传给开发者服务器。param参数:可以为null,第三方自定义回执参数,最大长度64个字符
requestId(String value)必填项,用户请求唯一标识 最大64字符
classification(int value)消息类型 0:运营类消息,1:系统类消息
pushMode(int   value)推送模式 0:正式推送;1:测试推送,不填默认为0(测试推送,只能给web界面录入的测试用户推送;审核中应用,只能用测试推送)
build()根据设置的属性, 生成Message对象

Demo

public Message buildMessage() throws     Exception {            List<String> andTags = new ArrayList<>();            andTags.add(“TAG1”);            List<String> orTagss = new ArrayList<>();            orTags.add(“TAG2”);            List<String> notTags = new ArrayList<>();            notTags.add(“TAG3”);            Message message = new Message.Builder()                    .regId(“12345678901234567890123”)//仅构建单推消息体需要                  .alias(ALIAS) //仅构建单推消息体需要                  .orTagss(orTagss)     //仅构建标签推消息体需要                  .andTags(andTags)//仅构建标签推消息体需要                  .notTags(notTags) //仅构建标签推消息体需要                  .notifyType(1)                    .title(“YOUR_TITLE”)                    .content(“YOUR_CONTENT”)                  .timeToLive(1000)                  .skipType(2)                    .skipContent(“http://www.vivo.com”)                  .networkType(-1)                    .clientCustomMap(“key1”, “value1”)                    .extra(“http://www.vivo.com”, “vivo”)                    .requestId(“1234567890123456”)                  .classification(1).build();          Return message;    }
6.2批量推送用户消息体

com.vivo.push.sdk.server.TargetMessage.Builder

Builder方法列表

方法说明
Builder()构造方法
regIds(Set<String> regIds)regId列表,个数大于等于2,小于等于1000,regId长度23个字符(regIds,aliases 两者需一个不为空,两个都不为空时,取regIds)
aliases(Set<String> aliases)别名列表,个数大于等于2,小于等于1000,长度不超过40字符(regIds,aliases 两者需一个不为空,两个都不为空时,取regIds)
taskId(String taskId)必填项,公共消息任务号,即调用com.vivo.push.sdk.server.Sender.saveListPayLoad返回的taskId
requestId(String requestId)必填项,用户请求唯一标识   最大64字符
build()根据设置的属性, 生成TargetMessage对象

Demo

public TargetMessage buildTargetMessage()     throws Exception {          Set<String>     regids = new HashSet<>();              regids.add(“12345678901234567890123”);            regids.add(“12345678901234567890321”);          Set<String>     aliases = new HashSet<>();              aliases.add(“ALIAS1”);              aliases.add(“ALIAS2”);          TargetMessage     targetMessage = new TargetMessage.Builder()                      .regIds(regids)                      .aliases(aliases)                      .requestId(“1234567890123456”)                      .taskId(“123456789012345678”).build();          Return targetMessage;    }

7.获取消息推送的统计值

获取批量推送或全量推送返回的taskId对应的统计信息,单次查询的taskIds最多100个。

接口说明:

com.vivo.push.sdk.server.Sender

方法说明
getStatistics(Set<String>     taskIds)查询taskIds里面所有taskId对应的统计信息,taskIds里最多存放100个taskId

Demo

public void testGetStatistics() throws   IOException {          Sender sender = new     Sender(APP_SECRET,authToken);              sender.initPool(20,10);//设置连接池参数,可选项          Set<String>     taskIds = new HashSet<>();              taskIds.add(“123456789012345678”);              taskIds.add(“123456789087654321”);          Result result =     sender.getStatistics(taskIds);result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result. getStatistics     ();//如请求发送成功,将获得各个taskId对应的统计数据    }

三、标签管理

1.新增标签

为应用方增加标签,用于后续标签推送。

接口说明:

com.vivo.push.sdk.server.TagMange

方法说明
addTag(TagMessage   tagMessage)根据消息体tagMessage中设定的相关信息创建新标签。

Demo

public void tagAdd() throws Exception {        TagManage   tagManage   =   new TagManage (APP_SECRET);tagManage.initPool(20,10);//设置连接池参数,可选项tagManage.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          TagMessage tagMessage = new     TagMessage.Builder()                      .name(“TAG_NAME”) //必填项,标签名称                      .desc(“TAG_DESCRIPTION”)//可选项,标签描述                    .group(“GROUP_NAME”)//可选项,标签分类名称(参考4部分)                    .build(); //构建创建标签的消息体          Result result =   tagManage.addTag(tagMessage);//发送创建标签请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

2.更新单个标签

更新一个标签的信息,更新标签名字、描述、所属分类。

接口说明:

com.vivo.push.sdk.server.TagMange

方法说明
updateTag (TagMessage   tagMessage)根据消息体tagMessage中设定的相关信息更新已存在的标签信息。

Demo

public void tagUpdate() throws Exception {          TagManage tagManage   =   new TagManage (APP_SECRET);tagManage.initPool(20,10);//设置连接池参数,可选项tagManage.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          TagMessage tagMessage = new     TagMessage.Builder()                      .oldName(“OLD_NAME”)//必填项,旧的标签名称                      .newName(“NEW_NAME”)//必填项,新的标签名称                      .desc(“TAG_DESCRIPTION”)//可选项,更新标签描述                    .group(“GROUP_NAME”)//可选项,更新标签分类(参考4部分)                    .build(); //构建更新标签的消息体        Result   result =   tagManage.updateTag(tagMessage);//发送更新标签请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

3.给标签添加用户设备

给标签添加用户设备信息,单次不超过1000个设备。

接口说明:

com.vivo.push.sdk.server.TagMange

方法说明
addMembers(TagMessage   tagMessage)把tagMessage中指定的用户设备添加到指定的标签中。

Demo

public void tagAddMembers () throws   Exception {          TagManage tagManage   =   new TagManage (APP_SECRET);tagManage.initPool(20,10);//设置连接池参数,可选项tagManage.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)Set<String>   ids = new   HashSet<>();ids.add(“REGID1”);ids.add(“REGID2”);          TagMessage tagMessage     = new TagMessage.Builder()                      .name(“TAG_NAME”)//必填项,要添加用户设备的标签名称                    .type(1)// 必填项,用户类型:1是regId ,2是别名                    .ids(ids)//必填项,用户id                    .build();//构建给标签添加用户设备的消息体          Result result =   tagManage.addMembers   (tagMessage);//发送给标签添加用户设备的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述        result.getData();//非法用户信息列表,其中每个非法用户信息包括status和userid两个属性,userid为接入方传的regid或者alias,status有三种情况:1是用户不存在,2是用户push开关关闭,3是用户14天未联网}

4.移除标签中的用户设备

移除标签中的用户设备信息,单次不超过1000个设备。

接口说明:

com.vivo.push.sdk.server.TagMange

方法说明
removeMembers(TagMessage   tagMessage)把tagMessage中指定的用户设备从指定标签中移除。

Demo

public void tagRemoveMembers () throws   Exception {          TagManage tagManage   =   new TagManage (APP_SECRET);tagManage.initPool(20,10);//设置连接池参数,可选项tagManage.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)Set<String>   ids = new   HashSet<>();ids.add(“REGID1”);ids.add(“REGID2”);          TagMessage   tagMessage   = new TagMessage.Builder()                    .name(“TAG_NAME”)//必填项,要移除用户设备的标签名称                    .type(1)// 必填项,用户类型:1是regId ,2是别名                    .ids(ids)//必填项,用户id                    .build();//构建移除标签用户设备的消息体          Result result = tagManage.     addMembers (tagMessage);//发送移除标签中的指定用户设备的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述          result.getData();//非法用户信息列表,其中每个非法用户信息包括status和userid两个属性,userid为接入方传的regid或者alias,status有三种情况:1是用户不存在,2是用户push开关关闭,3是用户14天未联网}

四、标签分类管理

1.新增标签分类

为应用方增加标签分类,用于后续标签分类管理。

接口说明:

com.vivo.push.sdk.server.TagGroup

方法说明
addTagGroup(TagGroupMessage     groupMessage)根据消息体groupMessage中设定的相关信息创建新标签分类。

Demo

public void addGroup() throws Exception {          TagGroup tagGroup =     new TagGroup (APP_SECRET);tagGroup.initPool(20,10);//设置连接池参数,可选项tagGroup.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          TagGroupMessage   groupMessage   = new TagGroupMessage.Builder()                      .name(“GROUP_NAME”)//必填项,标签分类名称                    .type(1)//必填项,标签分类类型:1是普通标签,2是互斥标签                      .desc(“one group”)//可选项,标签分类的描述信息                    .build();//构建新增标签分类的消息体       Result result   = tagGroup.addTagGroup   (groupMessage);//发送创建标签分类的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

2.更新单个标签分类

更新一个标签分类的信息,包括标签分类名称和描述。

接口说明:

com.vivo.push.sdk.server.TagGroup

方法说明
updateTag(TagGroupMessage     groupMessage)根据消息体groupMessag中设定的相关信息更新已存在的标签分类信息。

Demo

public void updateGroup() throws Exception {          TagGroup tagGroup =     new TagGroup (APP_SECRET);tagGroup.initPool(20,10);//设置连接池参数,可选项tagGroup.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          TagGroupMessage     groupMessage = new TagGroupMessage.Builder()                      .oldName(“OLD_NAME”)//必填项,旧的标签分类名称                      .newName(“NEW_NAME”)//必填项,新的标签分类名称                      .desc(“TAG_DESCRIPTION”)//可选项,更新标签分类的描述                    .build(); //构建更新标签分类的消息体          Result result =   tagGroup.updateTagGroup   (groupMessage);//发送更新标签分类的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

3.添加标签到标签分类中

把标签添加进标签分类里面,一次可添加一个或者多个标签,最多不超过100个。

接口说明:

com.vivo.push.sdk.server.TagGroup

方法说明
addTagToGroup(TagGroupMessage groupMessage)把groupMessag中指定的标签添加到指定的标签分类中。

Demo

public void tagsToGroup() throws Exception {          TagGroup tagGroup =     new TagGroup (APP_SECRET);tagGroup.initPool(20,10);//设置连接池参数,可选项tagGroup.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)List<String>   tagList = new   ArrayList<>();tagList.add(“TAG1”);tagList.add(“TAG2”);          TagGroupMessage     groupMessage = new TagGroupMessage.Builder()                    .name(“TAG_GROUP_NAME”)//必填项,需添加标签的标签分类名称                    .tagList(tagList)//必填项,标签列表                    .build(); //构建添加标签到标签分类的消息体          Result result =   tagGroup.addTagToGroup   (groupMessage);//发送添加标签到标签分类的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

五、标签组合管理

1.新增标签组合

为应用方增加标签组合。 一个标签组合由多个标签组成。

接口说明:

com.vivo.push.sdk.server.TagSegment

方法说明
addTagSegment(TagSegMessage segMessage)根据消息体segMessage中设定的相关信息创建新标签组合。

Demo

public void addSegment() throws Exception {          TagSegment   tagSegment   = new TagSegment (APP_SECRET);tagSegment.initPool(20,10);//设置连接池参数,可选项tagSegment.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          List<String> andTags     = new ArrayList<>();            andTags.add(“TAG1”);          List<String> orTagss     = new ArrayList<>();          orTags.add(“TAG2”);          List<String> notTags     = new ArrayList<>();            notTags.add(“TAG3”);          TagSegMessage     segMessage = new TagSegMessage.Builder()                    .name(“SEGMENT_NAME”)//必填项,标签组合的名称                    .andTags(andTags)//与操作                    .orTagss(orTags)//或操作                    .notTags(notTags)//非操作(具体与,或,非含义,操作参考5.3)                    .build();//构建新增标签组合的消息体      Result result   =   tagSegment.addTagSegment (segMessage);//发送创建标签组合的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

2.更新标签组合

更新一个标签组合的信息。

接口说明:

com.vivo.push.sdk.server.TagSegment

方法说明
addTagSegment(TagSegMessage     segMessage)根据消息体segMessage中设定的相关信息创建新标签组合。

Demo

public void updateSegment() throws Exception   {          TagSegment   tagSegment   = new TagSegment (APP_SECRET);tagSegment.initPool(20,10);//设置连接池参数,可选项tagSegment.setAuthToken(authToken);//设置推送的必要参数authToken(调用鉴权方法获得)          List<String> andTags     = new ArrayList<>();            andTags.add(“TAG1”);          List<String> orTagss     = new ArrayList<>();            orTagss.add(“TAG2”);          List<String> notTags     = new ArrayList<>();            notTags.add(“TAG3”);          TagSegMessage     segMessage = new TagSegMessage.Builder()                      .oldName(“OLD_NAME”)//必填项,旧的标签组合名称                    .newName(“NEW_NAME”)//必填项,新的标签组合名称                    .andTags(andTags)//与操作                    .orTagss(orTags)//或操作                    .notTags(notTags)//非操作(具体与,或,非含义,操作参考5.3)                    .build();//构建新增标签组合的消息体      Result result   =   tagSegment.updateTagSegment (segMessage);//发送更新标签组合的请求result.getResult();//获取服务器返回的状态码,0成功,非0失败          result.getDesc();//获取服务器返回的调用情况文字描述}

3.标签组合表达式

List<String> andTags = new   ArrayList<>();andTags.add(“深圳”,”广东”);List<String> orTagss = new   ArrayList<>();orTagss.add(“本科生”,”研究生”);List<String> notTags = new   ArrayList<>();notTags.add(“琴”,”棋”,”书”,”画”);TagSegMessage segMessage = new   TagSegMessage.Builder()                      .name(“SEGMENT_NAME”)//必填项,标签组合的名称                    .andTags(andTags)//与操作                    .orTagss(orTags)//或操作                    .notTags(notTags)//非操作                    .build();
标签表达式包含三种数组: notTags表示非操作、andTags表示与操作,orTagss表示或操作,例如如上面所示创建标签表达式,即代表:                 “notTags”:[“琴”,”棋”,”书”,”画”],                  “andTags”:[“深圳”,”广东”],                  “orTagss”:[“本科生”,”研究生”]可以表示为,不会琴、棋、书、画的广东省深圳市的本科生或研究生的所有用户。这些标签需要先在平台,接口,或调用该说明文档3部分的方法,创建相应标签后再使用。

VIVO消息推送服务端API接口文档

VIVO消息推送服务端API接口文档

当前版本:2.9.2

修改记录:

(1)/message/auth接口,鉴权码生成方式优化,增加调用频率为10次/s,取消每天10000次数量限制;

(2)各接口请求体,新增appId,用于跟鉴权信息进行比对,确认是否为应用信息一致,不一致返回错误码10094

一.公共

1.推送超量说明

如果调用接口出现超量限制的返回码,请不要在当天高频次调用服务器相应接口,否则将调低推送量级;

出现“10070:发送总量超出限制”。当天不要调用/message/send 单推接口;

出现“10252:批量发送消息体超出限制”。当天不要调用/message/saveListPayload 保存群推消息公共体接口;

出现“10070:发送总量超出限制”。当天不要调用/message/saveListPayload 保存群推消息公共体接口,以及/message/pushToList 批量推送用户接口;

出现“10254:全量发送超过次数限”。当天不要调用/message/all 全量发送接口;

关于推送量的说明可以参考【vivo推送常见问题汇总】

2.vivo服务器地址

https://api-push.vivo.com.cn

3.公共传入参数

HTTP Header中(推送鉴权接口除外)。

属性名字类型是否必填Y/N描述
authTokenstringY当鉴权成功时会返回该字段,推送消息时需要提供authToken,有效期默认为1天,过期后无法使用

4.高级特性extra

注意:回执目前仅支持单推接口且是正式消息 

属性名字类型是否必填Y/N描述
callbackstringY第三方接收回执的http接口,最大长度128个字符
callback.paramstringN第三方自定义回执参数,最大长度64个字符

二.接口定义

1.鉴权

1.1推送鉴权接口

接口说明

要想调用PUSH接口,任何接入方都要有个鉴权操作。其他接口header中必须携带该参数。

接口返回的参数authToken,一个appId可对应多个token,24小时过期,业务方做中心缓存,1-2小时更新一次。

限制:频率限制,单个app 10次/s。超频返回错误码10094。

访问方式

URL编码方式协议methodContent-Type
/message/authUtf-8httpsPOSTapplication/json
Curl e.g.:curl -X POST -H     ‘Content-Type:application/json’ -d   ‘${your_request_body}’     https://api-push.vivo.com.cn/message/authRequest body e.g.:{        “appId”:10004,          “appKey”:”25509283-3767-4b9e-83fe-b6e55ac6243e”,        “timestamp”:1501484120000,          “sign”:”8424f52fd5eaedc16474e4f702d230d2″}Response body e.g.:http status 200:业务成功:{         “result”:   0,         “desc”:   “请求成功”,        “authToken”:     “24ojds98fu3jqrioeu982134jieds9fq43u09uaf”}业务异常:{         “result”:   xxx,         “desc”:   “xxx不合法”}http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId
appKeystringY用户申请推送业务时获得的appKey
timestamplongYUnix时间戳 做签名用,单位:毫秒,且在vivo服务器当前utc时间戳前后十分钟区间内。
signstringY签名 使用MD5算法,字符串trim后拼接(appId+appKey+timestamp+appSecret),然后通过MD5加密得到的值(字母小写)

 输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
authTokenstring当鉴权成功时才会有该字段,推送消息时,需要提供authToken,有效期默认为1天,过期后无法使用。一个appId可对应多个token,24小时过期,业务方做中心缓存,1-2小时更新一次。

2.单播

2.1单推接口

接口说明

接入方携带消息内容以及用户regId(或alias)进行通知消息推送。针对每个用户发送不同的通知。

使用场景:如物流、订单状态、游戏预约状态、行程状态、聊天(如微信、评论)等。

限制:根据客户端SDK订阅数自动配置,可发送的用户总量可以在开发者后台查看。

访问方式

URL编码方式协议methodContent-Type
/message/sendUtf-8httpsPOSTapplication/json
Curl e.g.:curl -X POST -H ‘authToken:${your_auth_token}’   -H     ‘Content-Type:application/json’  -d     ‘${your_request_body}’   https://api-push.vivo.com.cn/message/sendRequest body e.g.:{      “appId”:10004,      “regId”:”12345678901234567890123″,      “notifyType”:1,      “title”:”标题1″,      “content”:”内容1″,      “timeToLive”:86400,      “skipType”:2,          “skipContent”:”http://www.vivo.com”,        “networkType”:”1″,      “clientCustomMap”:{              “key1″:”vlaue1”,              “key2″:”vlaue2”    },    “extra”:{              “callback”:”http://www.vivo.com”,              “callback.param”:”vivo”    },          “requestId”:”25509283-3767-4b9e-83fe-b6e55ac6b123″}Response body e.g.:http status 200:业务成功:{         “result”:   0,         “desc”:   “请求成功”,”taskId”:   “121397329”}推送使用的regid或alias不合法,无法送达:{        “result”: 10302,        “desc”: “regId 不合法”,        “invalidUser”: {            “status”: 1,            “userid”:   “15638535410301000000001”      }}业务异常:{         “result”:   xxx,”desc”: “xxx不合法”} http status 500:Internet server error!

接口定义

输入参数:

intent uri

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
regIdstringN应用订阅PUSH服务器得到的id   长度23个字符(regId,alias 两者需一个不为空,当两个不为空时,取regId)
aliasstringN别名 长度不超过40字符(regId,alias两者需一个不为空,当两个不为空时,取regId)
notifyTypeintY通知类型 1:无,2:响铃,3:振动,4:响铃和振动
titlestringY通知标题(用于通知栏消息) 最大20个汉字(一个汉字等于两个英文字符,即最大不超过40个英文字符)
contentstringY通知内容(用于通知栏消息) 最大50个汉字(一个汉字等于两个英文字符,即最大不超过100个英文字符)
timeToLiveintN消息保留时长 单位:秒,取值至少60秒,最长7天。当值为空时,默认一天
skipTypeintY点击跳转类型 1:打开APP首页 2:打开链接 3:自定义 4:打开app内指定页面
skipContentstringN跳转内容 跳转类型为2时,跳转内容最大1000个字符,跳转类型为3或4时,跳转内容最大1024个字符,skipType传3需要在onNotificationMessageClicked回调函数中自己写处理逻辑。关于skipContent的内容可以参考【vivo推送常见问题汇总】
networkTypeintN网络方式 -1:不限,1:wifi下发送,不填默认为-1
classificationintN消息类型 0:运营类消息,1:系统类消息。不填默认为0
clientCustomMapJSON ObjectN客户端自定义键值对 自定义key和Value键值对个数不能超过10个,且长度不能超过1024字符, key和Value键值对总长度不能超过1024字符。app可以按照客户端SDK接入文档获取该键值对
extraJSON ObjectN高级特性(详见目录:一.公共——5.高级特性 extra)
requestIdstringY用户请求唯一标识 最大64字符
pushModeintN推送模式 0:正式推送;1:测试推送,不填默认为0(测试推送,只能给web界面录入的测试用户推送;审核中应用,只能用测试推送)
auditReviewJSON ArrayN第三方审核结果,参见:基于第三方审核结果的消息推送

 输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
taskIdstring任务编号
 invalidUserJSON Object非法用户信息,包括status和userid,userid为接入方传的regid或者alias,status有三种情况:1.userId不存在;2.卸载或者关闭了通知;3.七天不在线;4.非测试用户

3.广播

3.1保存群推消息公共体接口

接口说明

同一条信息覆盖多个用户。此接口需与批量推送用户接口3.2配套使用,批量推送接口用此接口生成taskId批量发送用户。

使用场景:活动、系统升级提醒等。

限制:默认根据客户端SDK订阅数自动配置。

访问方式

URL编码方式协议methodContent-Type
/message/saveListPayloadUtf-8httpsPOSTapplication/json
Curl e.g.:curl -X POST  -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’    -d   ‘${your_request_body}’   https://api-push.vivo.com.cn/message/saveListPayloadRequest body e.g.:{        “appId”:10004,        “title”:”标题1″,        “content”:”内容1″,        “notifyType”:1,        “timeToLive”:86400,        “skipType”:2,          “skipContent”:”http://www.vivo.com”,        “networkType”:”1″,        “clientCustomMap”:{              “key1″:”vlaue1”,              “key2″:”vlaue2”},          “requestId”:”25509283-3767-4b9e-83fe-b6e55ac6b123″}Response body e.g.:http status 200:业务成功:{         “result”:   0,         “desc”:   “请求成功”,”taskId”:   “342982232646905856”}业务异常:{         “result”:   xxx,”desc”: “xxx不合法”}http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
notifyTypeintY通知类型 1:无,2:响铃,3:振动,4:响铃和振动
titlestringY通知标题(用于通知栏消息) 最大20个汉字(一个汉字等于两个英文字符,一个表情占一个字符,即最大不超过40个英文字符)
contentstringY通知内容(用于通知栏消息) 最大50个汉字(一个汉字等于两个英文字符,一个表情占一个字符,即最大不超过100个英文字符)
timeToLiveintN消息保留时长 单位:秒,取值至少900秒,最长7天。当值为空时,默认一天。
skipTypeintY点击跳转类型 1:打开APP首页 2:打开链接 3:自定义 4:打开app内指定页面
skipContentstringN跳转内容 跳转类型为2时,跳转内容最大1000个字符,跳转类型为3或4时,跳转内容最大1024个字符,skipType传3需要在onNotificationMessageClicked回调函数中自己写处理逻辑。关于skipContent的内容可以参考【vivo推送常见问题汇总】 pushSDK版本号:480以上,不在支持skipType=3,自定义跳转统一使用skipType=4,详见【vivo推送常见问题汇总】中API接入问题的Q11中的intent uri示例。
networkTypeintN网络方式 -1:不限,1:wifi下发送,不填默认为-1
classificationintN消息类型 0:运营类消息,1:系统类消息。不填默认为0
clientCustomMapJSON ObjectN客户端自定义键值对 自定义key和Value键值对个数不能超过10个,且长度不能超过1024字符, key和Value键值对总长度不能超过1024字符。app可以按照客户端SDK接入文档获取该键值对。
requestIdstringY用户请求唯一标识 最大64字符
auditReviewJSON ArrayN第三方审核结果,参见:基于第三方审核结果的消息推送

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
taskIdstring任务编号

3.2批量推送用户接口

接口说明

批量发送用户。此接口与群推消息接口3.1配套使用,首先通过群推消息接口3.1返回taskId,然后此接口带上taskId批量发送用户,可以根据regIds或者aliases分批调用。每次调用时,regIds或者aliases的个数必须大于等于2,小于等于1000。

限制:根据客户端SDK订阅数自动配置,可发送的用户总量可以在开发者后台查看。

访问方式

URL编码方式协议methodContent-Type
/message/pushToListUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST -H   ‘authToken:${your_auth_token}’ -H       ‘Content-Type:application/json’  -d   ‘${your_request_body}’   https://api-push.vivo.com.cn/message/pushToListRequest body e.g.:{      “appId”:10004,      “regIds”:[              “12345678901234567890121”,              “12345678901234567890122”        ],          “taskId”:”342982232646905856″,          “requestId”:”25509283-3767-4b9e-83fe-b6e55ac6b123″}Response body e.g.:http status 200:业务成功:{    “requestId”: “25509283-3767-4b9e-83fe-b6e55ac6b123”,    “result”: 0,    “desc”: “请求成功”,    “invalidUsers”: [{        “status”: 1,        “userid”: “12345678901234567890121”    }]}
业务异常:{         “result”:   xxx,         “desc”:   “xxx不合法”}http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
regIdsstring[]NregId列表 个数大于等于2,小于等于1000(regIds,aliases   两者需一个不为空,两个不为空,取regIds)
aliasesstring[]N别名列表个数大于等于2,小于等于1000,长度不超过40字符(regIds,aliases 两者需一个不为空,两个不为空,取regIds)
taskIdstringY公共消息任务号,取saveListPayload返回的taskId
requestIdstringY请求唯一标识,最大64字符
pushModeintN推送模式 0:正式推送;1:测试推送,不填默认为0(测试推送,只能给web界面录入的测试用户推送;审核中应用,只能用测试推送)

输出参数:

  属性名字  类型  描述
  result  int  接口调用是否成功的状态码 0成功,非0失败
  desc  string  文字描述接口调用情况
  invalidUser  JSON Object  非法用户信息,包括status和userid,userid为接入方传的regid或者alias,status有三种情况:1.userId不存在;2.卸载或者关闭了通知;3.七天不在线;4.非测试用户

3.3全量发送接口

接口说明

向所有设备推送某条消息。

使用场景:活动、系统升级提醒等。

限制:默认是每个app每日可发送一条。

访问方式

URL编码方式协议methodContent-Type
/message/allUtf-8httpsPOSTapplication/json
Curl e.g.:curl -X POST -H     ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’     https://api-push.vivo.com.cn/message/allRequest body e.g.:{        “appId”:10004,        “notifyType”:1,        “title”:”标题1″,        “content”:”内容1″,        “timeToLive”:86400,        “skipType”:2,          “skipContent”:”http://www.vivo.com”,        “networkType”:”1″,      “clientCustomMap”:{              “key1″:”vlaue1”,              “key2″:”vlaue2”      },          “requestId”:”25509283-3767-4b9e-83fe-b6e55ac6b123″}Response body e.g.:http status 200:业务成功:{         “result”:   0,         “desc”:   “请求成功”,”taskId”:     “12139732”}业务异常:{         “result”:   xxx,”desc”: “xxx不合法”}http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
notifyTypeintY通知类型 1:无,2:响铃,3:振动,4:响铃和振动
titlestringY通知标题(用于通知栏消息) 最大20个汉字(一个汉字等于两个英文字符,一个表情占一个字符,即最大不超过40个英文字符)
contentstringY通知内容(用于通知栏消息) 最大50个汉字(一个汉字等于两个英文字符,一个表情占一个字符,即最大不超过100个英文字符)
timeToLiveintN消息保留时长 单位:秒,取值至少900秒,最长7天。当值为空时,默认一天
skipTypeintY点击跳转类型 1:打开APP首页 2:打开链接 3:自定义 4:打开app内指定页面
skipContentstringN跳转内容 跳转类型为2时,跳转内容最大1000个字符,跳转类型为3或4时,跳转内容最大1024个字符,skipType传3需要在onNotificationMessageClicked回调函数中自己写处理逻辑。关于skipContent的内容可以参考【vivo推送常见问题汇总】 pushSDK版本号:480以上,不在支持skipType=3,自定义跳转统一使用skipType=4,详见【vivo推送常见问题汇总】中API接入问题的Q11中的intent uri示例。
networkTypeintN网络方式 -1:不限,1:wifi下发送,不填默认为-1
classificationintN消息类型 0:运营类消息,1:系统类消息。不填默认为0
clientCustomMapJSON ObjectN客户端自定义键值对 自定义key和Value键值对个数不能超过10个,且长度不能超过1024字符, key和Value键值对总长度不能超过1024字符。app可以按照客户端SDK接入文档获取该键值对
requestIdstringY用户请求唯一标识 最大64字符
auditReviewJSON ArrayN第三方审核结果,参见:基于第三方审核结果的消息推送

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
taskIdstring任务编号

3.4获取消息推送的统计值接口

接口说明

获取taskId对应的统计信息,taskIds最多100个。 注意:查询的消息类型 【群推送消息/列表推消息】

访问方式

URL编码方式协议methodContent-Type
/report/getStatisticsUtf-8httpsGETapplication/json
Curl e.g.:   curl -X GET  -H   ‘authToken:${your_auth_token}’ -H       ‘Content-Type:application/json’     https://api-push.vivo.com.cn/report/getStatistics?appId=10004&taskIds=123138209,23498102,3240910940,109283018Request body e.g.:Response body e.g.:http status 200:业务成功:{        “result”:0,        “desc”:”请求成功”,      “statistics”:[    {          “taskId”:   “298475091219”,          “target”: 10000,          “valid”: 9500,          “send”: 9000,          “receive”: 9000,          “display”: 8000,          “click”: 200,          “targetInvalid”:   200,          “targetUnSub”:   200,          “targetInActive”: 100,          “covered”: 200,          “controlled”:   200,          “targetOffline”:   100    },    {          “taskId”:   “298475091220”,          “target”: 10000,          “valid”: 9500,          “send”: 9000,          “receive”: 9000,          “display”: 8000,          “click”: 200,          “targetInvalid”:   200,          “targetUnSub”:   200,            “targetInActive”: 100,          “covered”: 200,          “controlled”:   200,          “targetOffline”:   100    }]}业务异常:{         “result”:   xxx,         “desc”:   “xxx不合法”}http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
taskIdsstringY查询的任务列表taskIds 用,分隔开 e.g.:   “234567,234568”

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
taskIdstring任务号
targetlong目标总数
targetInvalidlong不存在的用户总数,根据id找不到任何信息
targetUnSublong解订阅的用户总数,用户已卸载或者客户端主动调用turnOffPush()解订阅
targetInActivelong14天不在网的用户数,手机14天没有联网,信息被后台删除
validlong有效目标总数
coveredlong被覆盖的用户消息总数,群推、全推、标签推消息属于营销消息,会被覆盖
controlledlong被管控的用户消息总数,例如接收的群推消息总数一天超过5条
targetOfflinelong推送后不在线的用户数,截止到当前统计时间为止,没有联网的用户数,呈下降趋势
sendlong下发总数
receivelong到达总数
displaylong展示总数
clicklong点击总数

4.回执

4.1消息送达回执

接口说明

vivo推送服务器将已送达或和对应设备的alias或者regId通过调用第三方设置的回调,http接口传给开发者服务器。仅单播支持回执(每次调用后,推送服务器会清空这些数据。)

使用:

① 发送消息接口设置扩展参数extra(详见目录:一.公共——5.高级特性 extra), 包含callback、callback.param。

② vivo推送服务器调用第三方设置的callback url接口。 

③ 字段ackType  【达回执类型】目前只有到达回执ackType=0

访问方式

URL编码方式协议methodContent-Type
第三方设置的callback url(详见:高级特性 extra)Utf-8https/httpPOSTapplication/json
Curl e.g.:   curl -X POST -H   ‘Content-Type:application/json’ -d     ‘${your_request_body}’   https://callbackurlRequest body e.g.:{      “taskId1”:{              “param”:”param1″,              “targets”:”alias1,alias2,alias3″,              “ackTime”:1612776166257    },      “taskId2”:{              “param”:”param2″,              “targets”:”regId1,regId2,regId3″,              “ackTime”:1612776166258    }}Response body e.g.:http status 200:http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
taskIdstringY任务编号
paramstringY开发者上传的自定义参数值
targetsstringY一批alias或者regId列表,之间是用逗号分割
ackTimelongN回执到达时间,毫秒时间戳

 回执流程

设备在线:

设备不在线:

5.标签管理

5.1 新增标签接口

接口说明

为应用方增加标签,用于后续标签推送。

访问方式

URL编码方式协议methodContent-Type
/tag/addUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d     ‘${your_request_body}’ https://host:port/tag/addRequest   body e.g.:{          “appId”:10004,          “name”:   “shenzhen”,          “desc”:”深圳用户标签”,       “group”:”city”}Response body   e.g.:http status   200:{         “result”: 0,         “desc”: “成功”,}业务异常:{         “result”: xxx,”desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
namestringY标签名称
descstringN标签描述
groupstringN标签分类名

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

5.2 更新单个标签接口

接口说明

更新一个标签的信息,更新标签名字、描述、所属分类。

访问方式

URL编码方式协议methodContent-Type
/tag/updateUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’       https://host:port/tag/updateRequest   body e.g.:{           “appId”:10004,           “oldName”:”shenzhen”,           “newName”:”shenzhenbaoan”}Response body   e.g.:http status   200:{    “result”:   0,    “desc”:   “成功”}业务异常:{         “result”: xxx,”desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
oldNamestringY旧标签名称
newNamestringY新标签名称
descstringN更新标签描述
groupstringN更新标签所属分类

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

5.3 给标签添加用户设备接口

接口说明

给标签添加用户设备信息,单次不超过1000个设备。

访问方式

URL编码方式协议methodContent-Type
/tag/addMembersUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H ‘Content-Type:application/json’      -d ‘${your_request_body}’   https://host:port/tag/addMembersRequest   body e.g.:{         “appId”:10004,         “name”:”shenzhen”,         “type”:1,             “ids”:[“15549635570031000000216″,”15549635980031000001086”]}Response body   e.g.:http status   200:{    “result”:   0,    “desc”:   “success”,    “data”: [          {                “status”: 1,                “userid”:   “00000000000000000000004”          },          {                “status”: 1,                “userid”:   “00000000000000000000005”          }    ]}业务异常:{         “result”: xxx,”desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
namestringY标签名字
typeintY用户类型:1是regId   ,2是别名
idsJSON ArrayY用户id

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
dataJSON Arrayuserid是非法用户id,status有3种状态:1是用户不存在,2是用户push开关关闭,3是用户14天未联网。

5.4 移除标签中的用户设备接口

接口说明

移除标签中的用户设备信息,单次不超过1000个设备。

访问方式

URL编码方式协议methodContent-Type
/tag/removeMembersUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’       https://host:port/tag/removeMembersRequest   body e.g.:{         “appId”:10004,         “name”:”shenzhen”,         “type”:1,         “ids”:[“15554239157791000000009″,”15554239157791000000008”]}Response body   e.g.:http status   200:{    “result”:   0,    “desc”:   “success”,    “data”: [          {                “status”: 1,                “userid”:   “15554239157791000000008”          },          {                “status”: 1,                “userid”:   “15554239157791000000009”          }    ]}业务异常:{         “result”: xxx,         “desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
namestringY标签名字
typeintY用户类型:1是regId   ,2是别名
idsJSON ArrayY用户id

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
dataJSON Arrayuserid是非法用户id,status有3种状态:1是用户不存在,2是用户push开关关闭,3是用户14天未联网。

6.标签分类管理

6.1 新增标签分类接口

接口说明

为应用方增加标签分类,用于后续标签分类管理。

访问方式

URL编码方式协议methodContent-Type
/tagGroup/addUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d   ‘${your_request_body}’ https://host:port/tagGroup/addRequest body e.g.:{    “appId”:10004,    “name”:   “guangzhou”,     “type”:”city”}Response body   e.g.:http status   200:{         “result”: 0,         “desc”: “成功”,}业务异常:{         “result”: xxx,         “desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
namestringY标签分类名称
typeintY标签分类类型:1是普通标签,2是互斥标签
descstringN标签分类描述

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

6.2 更新单个标签分类接口

接口说明

更新一个标签分类的信息,包括标签分类名称和描述。

访问方式

URL编码方式协议methodContent-Type
/tagGroup/updateUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’       https://host:port/tagGroup/updateRequest   body e.g.:{      “appId”:10004,      “oldName”: “city”,      “newName”:   “province”,      “desc”:   “这是更新后的描述”}Response body   e.g.:http status   200:{    “result”:   0,    “desc”:   “成功”}业务异常:{         “result”: xxx,         “desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
oldNamestringY旧标签分类名称
newNamestringY新标签分类名称
descstringN新标签分类的描述

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

6.3 添加标签到标签分类接口

接口说明

把标签添加进标签分类里面,一次可添加一个或者多个标签,最多不超过100个。

访问方式

URL编码方式协议methodContent-Type
/tagGroup/addToGroupUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’       https://host:port/tagGroup/addToGroupRequest   body e.g.:{         “appId”:10004,         “name”:”city”,         “tagList”:[“shenzhen”,”guangzhou”]}Response body   e.g.:http status   200:{    “result”:   0,    “desc”:   “成功”}业务异常:{         “result”: xxx,”desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
namestringY标签分类名称
tagListJSON ArrayY一个或多个标签

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

7.标签组合管理

7.1 新增标签组合接口

接口说明

为应用方增加标签组合。 一个标签组合由多个标签组成。

访问方式

URL编码方式协议methodContent-Type
/tagSegment/addUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d     ‘${your_request_body}’ https://host:port/tagSegment/addRequest   body e.g.:{    “appId”:10004,    “name”:   “segment1”,          “expression”:{                   “notTags”:[“shenzhen”],                  “andTags”:[],                  “orTags”:[]          }}Response body   e.g.:http status   200:{         “result”: 0,         “desc”: “成功”,}业务异常:{         “result”: xxx,”desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
namestringY标签组合名称
expressionJSON ObjectY标签组合表达式:包含三种JSON数组:notTags表示非操作、andTags表示与操作,orTags表示或操作,例如:”tagExpression”:{                 “notTags”:[“琴”,”棋”,”书”,”画”],                  “andTags”:[“深圳”,”广东”],                  “orTags”:[“本科生”,”研究生”]          }可以表示为,不会琴、棋、书、画的广东省深圳市的本科生或研究生的所有用户。当然这些标签需要先在平台或者接口创建后再使用。

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

7.2 更新单个标签组合接口

接口说明

更新一个标签组合的信息

访问方式

URL编码方式协议methodContent-Type
/tagSegment/updateUtf-8httpsPOSTapplication/json
Curl e.g.:   curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’       https://host:port/tagSegment/updateRequest   body e.g.:{            “appId”:10004,           “oldName”:”segment1″,           “newName”:”segment2″,”expression”:   {                    “orTags”: [“shenzhen”],                    “andTags”:     [],                    “notTags”: []    }}Response body   e.g.:http status   200:{    “result”:   0,    “desc”:   “成功”}业务异常:{         “result”: xxx,”desc”:     “xxx”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
oldNamestringY旧标签组合名称
newNamestringY新标签组合名称
expressionJSON ObjectN新标签组合表达式:包含三种JSON数组:notTags表示非操作、andTags表示与操作,orTags表示或操作,例如:”tagExpression”:{                 “notTags”:[“琴”,”棋”,”书”,”画”],                  “andTags”:[“深圳”,”广东”],                  “orTags”:[“本科生”,”研究生”]          }可以表示为,不会琴、棋、书、画的广东省深圳市的本科生或研究生的所有用户。当然这些标签需要先在平台或者接口创建后再使用。

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况

8.标签推

8.1标签推接口

接口说明

接入方携带消息内容、标签信息进行通知消息推送。

  标签个数的限制:20个

访问方式

URL编码方式协议methodContent-Type
/message/tagPushUtf-8httpsPOSTapplication/json
Curl e.g.:curl -X POST   -H   ‘authToken:${your_auth_token}’ -H     ‘Content-Type:application/json’  -d ‘${your_request_body}’       https://host:port/message/tagPushRequest   body e.g.:{          “appId”:10004,          “tagExpression”:{                   “notTags”:[“tag1″,”       tag2″,”tag3″,” tag4″],                  “andTags”:[“tag5″,”   tag6″],                  “orTags”:[“tag7″,”tag8”]          },  “segmentName”:   “组合名”,      “notifyType”: 4,    “title”:   “123”,      “content”: “456”,      “timeToLive”: 86400,      “skipType”: 1,      “skipContent”:   “assda”,      “networkType”: -1,      “requestId” :       “25509283-3767-4b9e-83fe-b6e55ac6b123”}Response body   e.g.:http status   200:业务成功:{    “result”:   0,    “desc”:   “请求成功”,    “taskId”:     “2199912448”}业务异常:{         “result”: xxx,”desc”:   “xxx不合法”}http status   500:Internet   server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
tagExpressionJSON ObjectY标签表达式。包含三种JSON数组:notTags表示非操作、andTags表示与操作,orTags表示或操作,例如:”tagExpression”:{                 “notTags”:[“琴”,”棋”,”书”,”画”],                  “andTags”:[“深圳”,”广东”],                  “orTags”:[“本科生”,”研究生”]          }可以表示为,不会琴、棋、书、画的广东省深圳市的本科生或研究生的所有用户。当然这些标签需要先在平台或者接口创建后再使用。
segmentNamestringN之前创建好的组合名,如果传递组合名,默认用组合名推送,否则如果传递tagExpression,按照标签表达式推送
notifyTypeintY通知类型 1:无,2:响铃,3:振动,4:响铃和振动
titlestringY通知标题(用于通知栏消息) 最大20个汉字(一个汉字等于两个英文字符,一个表情占一个字符,即最大不超过40个英文字符)
contentstringY通知内容(用于通知栏消息) 最大50个汉字(一个汉字等于两个英文字符,一个表情占一个字符,即最大不超过100个英文字符)
timeToLiveintN消息保留时长 单位:秒,取值至少60秒,最长7天。当值为空时,默认一天
skipTypeintY点击跳转类型 1:打开APP首页 2:打开链接 3:自定义 4:打开app内指定页面
skipContentstringN跳转内容 跳转类型为2时,跳转内容最大1000个字符,跳转类型为3或4时,跳转内容最大1024个字符,skipType传3需要在onNotificationMessageClicked回调函数中自己写处理逻辑。pushSDK版本号:480以上,不在支持skipType=3,自定义跳转统一使用skipType=4,详见【vivo推送常见问题汇总】中API接入问题的Q11中的intent uri示例。
networkTypeintN网络方式 -1:不限,1:wifi下发送,不填默认为-1
classificationintN消息类型 0:运营类消息,1:系统类消息。不填默认为0
clientCustomMapJSON ObjectN客户端自定义键值对 自定义key和Value键值对个数不能超过10个,且长度不能超过1024字符, key和Value键值对总长度不能超过1024字符。
requestIdstringY用户请求唯一标识 最大64字符
auditReviewJSON ArrayN第三方审核结果,参见:基于第三方审核结果的消息推送

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
taskIdstring任务编号

9.消息状态查询

9.1消息状态查询

接口说明

由于目前只返回审计相关信息,单推没有同步返回消息审计状态,其他类型的推送有同步返回。所以可通过调用此接口传递消息id,查询消息的状态。目前有调用频率限制,单个app 1次/s, 建议一批类似的消息体查询一次。

使用:

① 发送消息后查询消息的状态(延时在一分钟内)。

②‘审计通过’或 ‘审计不通过的状态还未入库’,返回 【消息状态未知】,审计不通过状态已入库,返回【消息包含敏感词】

访问方式

URL编码方式协议methodContent-Type
https://api-push.vivo.com.cn/search/msgStatusUtf-8https/httpGETapplication/json
Curl e.g.:   curl -X GET -H   ‘authToken:${your_auth_token}’ -H   ‘Content-Type:application/json’   -d     ‘${your_request_body}’ https://api-push.vivo.com.cn/search/msgStatus?appId=10004&taskIds=taskId1,taskId2Request body e.g.:{    “result”:   0,    “desc”:   “success”,    “data”: [          {                “taskId”: taskId1,                “desc”: “消息包含敏感词”          },          {                ” taskId “: taskId2,                “desc”: “消息状态未知”          }    ]}Response body e.g.:http status 200:http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
taskIdsstringY由多个taskId组成的字符串,多个taskId之间用逗号分隔,一次最多查询100个

10.查询失效id

10.1失效id查询

接口说明

由于用户卸载、客户端主动调用turnOffPush()解订阅、设备14天不联网还有一部分历史原因,可能造成推送的id无效。开发者可以根据推送时返回的InvalidUser对失效id做标记或者清除处理,或者单独查询本接口,将无效的id过滤,避免占用推送额度。

使用:

① 传递要查询的id,以及id的类型,后台根据保存的id,返回无效的id。

② 建议在推送低峰期,例如晚上或者凌晨调用,将保存的id一批批查询,避免影响应用的推送性能。勿高频调用。

访问方式

URL编码方式协议methodContent-Type
/invalidUser/checkUtf-8https/httpPOSTapplication/json
Curl e.g.:   curl -X GET -H   ‘authToken:${your_auth_token}’ -H   ‘Content-Type:application/json’   -d     ‘${your_request_body}’ https://api-push.vivo.com.cn/invalidUser/check    Request body e.g.:{      “appId”:10004,      “userType”: 1,      “userIds”: [            “15547801220021000000000”,            “15547801220021000000001”    ]}Response body e.g.:http status 200:{      “invalidUsers”: [            “15547801220021000000000”,            “15547801220021000000001”    ]}http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
userIdsstring[]Y用户id数组 ,单次最大100个
userTypeintYuserId的类型1:regId,2:alias

11.消息回收

11.1 消息回收接口

接口说明

此接口用于回收已发送给用户的消息。通过传递推送的消息id和具体的用户id、用户类型进行消息回收,消息回收接口调用量和调用速度会占用推送量级和推送速度。

限制:由我司运营人员配置。

消息撤回功能是平台提供给开发者紧急处理运营事故的工具,切勿日常频繁使用,以免对用户体验不当影响。

对于推送内容、应用行为等存在违规的,平台将按《vivo推送运营规则》进行相应处罚。

访问方式

URL编码方式协议methodContent-Type
/message/recycleUtf-8httpsPOSTapplication/json
Curl e.g.:curl -X POST -H ‘   authToken:${your_auth_token}’ -H ‘Content-Type:application/json’  -d ‘${your_request_body}’   https://host:port/message/recycleRequest body e.g.:{         “appId”:10004,         “taskId”:656079923690082304,         “userIds”:[“15762048080021000000007″,”15762048080021000000008″,”15762048080021000000009”],         “userType”:1}Response body e.g.:http status 200:业务成功:{         “result”:   0,         “desc”:   “请求成功”,”invalidUsers”: [         {            “status”: 1,            “userid”:   “15762048080021000000008”         },         {            “status”: 1,            “userid”:   “15762048080021000000008”         }      ]}业务异常:{         “result”:   xxx,”desc”: “xxx不合法”} http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送
taskIdstringY单播或广播返回的taskId
userIdsstring[]YuserId列表。个数大于等于1小于等于100
userTypeintY用户类型。1:regId;2:alias

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
invalidUsersJSON Array非法用户信息,包括status和userid,userid为接入方传的regid或者alias,status有三种情况:1.userId不存在 2.卸载或者关闭了通知 3.七天不在线

12.应用配置信息查询 

12.1 应用配置信息查询接口

接口说明

此接口用于查询应用配置信息,系统消息总量、运营消息总量、群推消息体总量、配置速度等信息、SDK订阅数。此接口限制了调用频率,请勿频繁调用。

访问方式

URL编码方式协议methodContent-Type
/report/getAppConfigUtf-8httpsGETapplication/json
Curl e.g.:curl -X GET -H ‘authToken:${your_auth_token}’   -H ‘Content-Type:application/json’  -d ‘${your_request_body}’     https://host:port/report/getAppConfig?appId=10004Response body e.g.:http status 200:业务成功:{      “result”: 0,      “desc”: “请求成功”,      “data”: {          “sysMsgCount”: 10000,          “marketMsgCount”: 100000,          “sdkSubCount”: 124,          “speed”: 3000,          “groupMsgBodyCount”: 12000,       “remainSysMsgCount”:1200,       “remainMarketMsgCount”:1300
      }}业务异常:{           “result”:   xxx,”desc”:   “xxx不合法”} http status 500:Internet server error!

接口定义

输入参数:

属性名字类型是否必填Y/N描述
appIdintY用户申请推送业务时生成的appId,用于与获取authToken时传递的appId校验,一致才可以推送

输出参数:

属性名字类型描述
resultint接口调用是否成功的状态码 0成功,非0失败
descstring文字描述接口调用情况
datajson object详细内容

data:

属性名字类型描述
sysMsgCountlong系统消息配置量
marketMsgCountlong运营消息配置量
sdkSubCountlongsdk订阅数
speedlong速度配置
groupMsgBodyCountlong群推消息体配置量
remainSysMsgCountlong剩余可发送系统消息量级
remainMarketMsgCountlong剩余可发送运营消息量级


全局公共返回码详解

resultdesc
0请求成功
10000权限认证失败
10040资源已达上限,稍后重试
10044该接口未开放测试模式
10045应用审核中不可发送正式消息
10050alias和regId 不能都为空
10051暂不支持该消息类型
10054notifyType 不合法
10055title 不能为空
10056title 长度不能超过40个字符
10057content 不能为空
10058content 长度不能超过100个字符
10059timeToLive 不合法
10060skipType 不合法
10061skipType = 2, skipContent 不能为空
10062skipType = 2, skipContent 不能超过1000个字符
10063skipType = 3, skipContent 不能为空
10064skipType = 3, skipContent 不能超过1024个字符
10065networkType 不合法
10066自定义key和Value键值对个数不能超过10个
10067自定义key和value键值对不合法
10068skipType = 4, skipContent 不能为空
10069skipType = 4, skipContent 不能超过1024个字符
10070运营消息发送量总量超出限制
10071超出发送时间允许范围
10072推送速度过快,请稍后再试
10073系统消息发送量总量超出限制。系统消息量级申请,请参见:系统消息量级说明
10082系统消息未开通
10084查询速度过快,请稍后再试
10085title 或 content 不能为纯表情
10093获取鉴权码速度过快
10094鉴权码与请求体对应的appId不一致
10101消息内容审核不通过
10102服务器端未知异常
10103推送内容含敏感信息
10104请发送正式信息,请检查title、content,不要发送测试内容
10105推必安内容审核不通过
10106auditReview参数错误
10110请配置商业化消息发送频率
10111今天已发送商业化消息
10112商业化消息发送超出周次数限制
10150aliases 和 regIds 不能都为空
10151taskId 不能为空
10152taskId 不合法
10153regIds 个数不在指定范围[2-1000]
10154aliases 个数不在指定范围[2-1000]
10155消息不存在或已过期
10200appId 不能为空
10201appKey 不能为空
10202appKey 不合法
10203timestamp 不能为空
10204sign 不能为空
10205appId 不存在
10206sign 不正确
10207timestamp 不合法
10250认证接口超过调用次数限制
10252批量发送创建消息体超出限制
10253批量发送regId或alais超过总量限制
10254全量发送超过次数限制
10301alias 长度不能超过40个字符
10302regId 不合法, regId为无效的regId, regId可能已经失效
10304extra 包含不支持的key
10305extra callback长度不能超过128个字符
10306extra callback.param长度不能超过64个字符
10307alias 不合法
10352requestId 不能为空
10353requestId 长度不能超过64个字符
10354Internet server error
10471taskIds 数量不能超过100个
10472taskIds 格式错误
10473taskIds 为空
10600name参数不合法,只能使用中文、英文字母、阿拉伯数字和下划线命名,且不能以数字开头,且长度不超过50字符
10601标签名字不能为空
10602标签描述不能超过300字符
10603oldName参数不能为空
10604newName参数不能为空
10605oldName参数不合法,只能使用中文、英文字母、阿拉伯数字和下划线命名, 且不能以数字开头,且长度不超过50字符
10606newName参数不合法,只能使用中文、英文字母、阿拉伯数字和下划线命名, 且不能以数字开头,且长度不超过50字符
10607id参数不能为空
10608type参数不能为空
10609ids参数不能为空
10610标签名已经存在
10611标签分类名已经存在
10612标签组合名已经存在
10613group参数不合法,只能使用中文、英文字母、阿拉伯数字和下划线命名, 且不能以数字开头,且长度不超过50字符
10614ids数量不能超过1000
10615tag数量不能超过100
10616type参数不合法
10700userids不能为空
10701userid个数超过限制
10702optionType错误
10703register接口调用超频,稍后再试
10704register调用过快,稍后再试
10705app不支持
10706userType错误
10800registration_tokens个数不在指定范围
10801notification不能为空
10802original_source_name不能为空
10803original_source_name长度非法
10804original_source_ip不能为空
10806click_action非法
10807url长度超过限制
10808intent长度超过限制
10255全量推送接口未开放
10901dyeKey长度不能超过限制
10900dye设置个数超过限制
10811超出限制
10810clientId非法
10809click_action不能为空
10805notification_channel长度超过限制
10617系统msgId生成异常
10500订阅标签超出限制
10501标签长度超出限制
10502标签已经删除完成
10503标签不能为空
10504订阅标签超出限制
10505标签长度超出限制
10506标签已经删除完成
10507标签不能为空
10508标签个数超出限制
10550标签操作类型无效
10551标签列表不能为空
10552标签个数超过限制
10553标签组合名不能为空
10309audienceId不合法,alias长度不超过40