npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cordova-plugin-aliyun-push-compat-capacitor

v1.0.16

Published

A aliyun push cordova plugin for CapacitorJS.

Downloads

383

Readme

cordova-plugin-aliyun-push-compat-capacitor

  • 此插件为兼容CapacitorJS而修改的Cordova插件,目的是能在CapacitorJS下使用阿里云移动推送
  • Android包含小米华为荣耀OPPOVIVO魅族 厂商辅助通道,并支持多Channel,支持配置厂商通道列表

版本说明

  • CapacitorJS: V5
  • Gradle: V8
  • xCode: V15.3
  • Android Studio: Flamingo
  • 阿里云推送SDK - Android: V3.9.0
  • 阿里云推送SDK - iOS: V2.1.0

安装

npm install --save-dev cordova-plugin-aliyun-push-compat-capacitor

配置

重要说明

1、CapacitorJS不支持Cordova的Variable和Hook特性

2、CapacitorJS为兼容Cordova插件而禁止了Objective-C的AppDelegate分类

所以:

1、插件需要借助.env文件方式存放ID和KEY

2、插件内部不能使用Objective-C的分类(AppDelegate+AliyunPush.m)常用的swizzled method大法,『无痛』启动SDK和处理通知事件

因此相比一般的Cordova插件我们需要多一些配置步骤:

CapacitorJS

步骤一:根目录下创建.env文件并添加Id和Key信息(参照.env章节)

步骤二:相应业务逻辑适当时候调用AliyunPush API:

  Aliyun.onMessage = message => this.messageHandler(message);
  Aliyun.onError = err => this.errorHandler(err);
  await AliyunPush.boot();

iOS

步骤一:配置读取.env(参照.env章节 - 如何在xCode中读取.env文件?- 步骤一、二、三、四

步骤二:AppDelegate.swift中相关的通知函数中添加发送自定义通知的代码:

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        NotificationCenter.default.post(name: Notification.Name(rawValue: "CDApplicationDidRegisterForRemoteNotificationsNotification"), object: deviceToken)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: any Error) {
        NotificationCenter.default.post(name: Notification.Name(rawValue: "CDApplicationDidFailToRegisterForRemoteNotificationsNotification"), object: error)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        NotificationCenter.default.post(name: Notification.Name(rawValue: "CDApplicationDidReceiveRemoteNotificationNotification"), object: application, userInfo: userInfo)
    }

步骤三:同步插件到app:

npx cap sync

Android

步骤一:配置读取.env(参照.env章节 - 如何在Android Studio中读取.env文件?- 步骤一

步骤二:在项目Project下的variables.gradle添加aliyunPushDebug和aliyunPushChannelId配置:(channelId支持多个)

ext {
    ...
    aliyunPushDebug = false
    aliyunPushChannelId = 'CHANNEL1:应用公告,CHANNEL2:其他通知'
}

步骤三:res/values/strings.xml中添加如下内容:(cordova中的plugin.xml有写但是capacitor不知道什么原因没有插入相应内容)

<string name="aliyun_dialog_title">消息提醒需要通知权限</string>
<string name="aliyun_dialog_message">请前往设置打开应用通知权限。</string>
<string name="aliyun_dialog_negative_text">忽略</string>
<string name="aliyun_dialog_positive_text">设置</string>

步骤四:res/drawable/中添加通知小图标名字为:ic_notification_icon.png

简单生成通知小图标线上工具:https://romannurik.github.io/AndroidAssetStudio/icons-notification.html

步骤五:同步插件到app:

npx cap sync

.env

=== CapacitorJS、iOS、Android工程都使用了.env可以忽略此章节 ===

此插件使用了.env文件方式存放必要的id和secret设置(因为CapacitorJS不支持Cordova的Variables特性)

请先在根目录下创建以下内容的.env文件:

# iOS
EMAS_IOS_APP_KEY=***
EMAS_IOS_APP_SECRET=***
# Android
EMAS_ANDROID_APP_KEY=***
EMAS_ANDROID_APP_SECRET=***
# Xiao Mi
EMAS_MI_APP_ID=***
EMAS_MI_APP_KEY=***
# Huawei
EMAS_HUAWEI_APP_ID=***
# Honor
EMAS_HONOR_APP_ID=***
# Vivo
EMAS_VIVO_APP_ID=***
EMAS_VIVO_APP_KEY=***
# Oppo
EMAS_OPPO_APP_KEY=***
EMAS_OPPO_APP_SECRET=***
# Meizu
EMAS_MEIZU_APP_ID=***
EMAS_MEIZU_APP_KEY=***

如何在CapacitorJS中读取.env文件?

步骤一:安装 dotenv

npm install --save-dev dotenv

步骤二:在capacitor.config.js文件内引用dotenv

require('dotenv').config();

const {
  EMAS_ANDROID_APP_KEY,
  EMAS_ANDROID_APP_SECRET,
  EMAS_MI_APP_ID,
  EMAS_MI_APP_KEY,
  ...
} = process.env;

如何在xCode中读取.env文件?

思路:添加Build前脚本 -> 读取.evn文件 -> 写入Env-App.xcconfig -> Info.plist使用xcconfig变量 -> 代码读取Info.plist

步骤一:创建App.debug.xcconfig / App.release.xcconfig / Env-App.xcconfig 文件

1、项目结构如下:

2、在App.debug.xconfig / App.release.xconfig内include相应的Pods和Env的xcconfig:

//根据不同的环境(debug/release)修改以下对应的Pods的xcconfig路径
#include? "Pods/Target Support Files/Pods-App/Pods-App.XXXXXXXX.xcconfig"
#include? "Env/Env-App.xcconfig"

3、Env-App.xcconfig内容留空(因为脚本会读.env文件并写入此文件)

步骤二:在PROJECT -> App -> Info -> Configurations -> Debug / Release -> 选择刚创建的App.debug / App.release

步骤三:在Build Pre-action中添加脚本

1、打开:xCode菜单 -> Product -> Scheme -> Edit Scheme... -> Build -> Pre-actions -> +

2、在『Provide build settings from』选项里选择自己的App

3、加入如下脚本:

# Target Key Settings
ID_KEY="EMAS_IOS_APP_KEY"
SECRET_KEY="EMAS_IOS_APP_SECRET"
# write env variables into xcconfig file from .env
dotEnvFilePath="${SRCROOT}/../../.env"
envAppConfigPath="${SRCROOT}/Env/Env-App.xcconfig"
targetExp="/^(${ID_KEY}|${SECRET_KEY}).*/!d"
sed -E $targetExp $dotEnvFilePath > $envAppConfigPath

步骤四:在Info.plist加入相应key和dict:

  <key>Aliyun Push Config</key>
  <dict>
    <key>Debug</key>
    <false/>
    <key>App Key</key>
    <string>$(EMAS_IOS_APP_KEY)</string>
    <key>App Secret</key>
    <string>$(EMAS_IOS_APP_SECRET)</string>
  </dict>

步骤五:在代码中读取Info.plist获取相关Id和Key(插件内部实现,无需手动设置)

// 使用Info.plist中的Aliyun Push Config
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSDictionary *aliyunPushConfig = [infoDictionary objectForKey:@"Aliyun Push Config"];

// 获取config信息
NSString *appKey = [aliyunPushConfig objectForKey:@"App Key"];
NSString *appSecret = [aliyunPushConfig objectForKey:@"App Secret"];
Boolean enableDebug = [[aliyunPushConfig objectForKey:@"Debug"] boolValue];

如何在Android Studio中读取.env文件?

思路:Project下的build.gradle添加task -> 读取.evn文件 -> 写入System properties -> 用properties设置build.gradle的manifestPlaceholders -> 使用manifestPlaceholders设置AndroidManifest.xml的<meta-data> -> 代码读取<meta-data>

步骤一:在Project下的build.gradle底部添加task读取.env到System.props:

task setPropsFromDotEnv(type: Exec) {
  file('../.env').readLines().each() {
    def (key, value) = it.tokenize('=')
    if (key.charAt(0) != "#") System.setProperty(key, value)
  }
//  println(System.props)
}

步骤二:Module的build.gradle中加入android.defaultConfig.manifestPlaceholders,并设置对应的System.props:(插件内部实现,无需手动设置)

android {
    defaultConfig {
        manifestPlaceholders.EMAS_ANDROID_APP_KEY = System.props.EMAS_ANDROID_APP_KEY
        manifestPlaceholders.EMAS_ANDROID_APP_SECRET = System.props.EMAS_ANDROID_APP_SECRET
        manifestPlaceholders.EMAS_MI_APP_ID = System.props.EMAS_MI_APP_ID
        manifestPlaceholders.EMAS_MI_APP_KEY = System.props.EMAS_MI_APP_KEY
        manifestPlaceholders.EMAS_HUAWEI_APP_ID = System.props.EMAS_HUAWEI_APP_ID
        manifestPlaceholders.EMAS_HONOR_APP_ID = System.props.EMAS_HONOR_APP_ID
        manifestPlaceholders.EMAS_VIVO_APP_ID = System.props.EMAS_VIVO_APP_ID
        manifestPlaceholders.EMAS_VIVO_APP_KEY = System.props.EMAS_VIVO_APP_KEY
        manifestPlaceholders.EMAS_OPPO_APP_KEY = System.props.EMAS_OPPO_APP_KEY
        manifestPlaceholders.EMAS_OPPO_APP_SECRET = System.props.EMAS_OPPO_APP_SECRET
        manifestPlaceholders.EMAS_MEIZU_APP_ID = System.props.EMAS_MEIZU_APP_ID
        manifestPlaceholders.EMAS_MEIZU_APP_KEY = System.props.EMAS_MEIZU_APP_KEY
    }
}

步骤三:在AndroidManifest.xml中内加入读取manifestPlaceholders中的值:(插件内部实现,无需手动设置)

<application>
    ...
    <meta-data android:name="com.alibaba.app.appkey" android:value="${EMAS_ANDROID_APP_KEY}"/>
    <meta-data android:name="com.alibaba.app.appsecret" android:value="${EMAS_ANDROID_APP_SECRET}"/>
    <meta-data android:name="MI_PUSH_APP_ID" android:value="${EMAS_MI_APP_ID}"/>
    <meta-data android:name="MI_PUSH_APP_KEY" android:value="${EMAS_MI_APP_KEY}"/>
    <meta-data android:name="com.huawei.hms.client.appid" android:value="appid=${EMAS_HUAWEI_APP_ID}"/>
    <meta-data android:name="com.hihonor.push.app_id" android:value="appid=${EMAS_HONOR_APP_ID}"/>
    <meta-data android:name="com.vivo.push.app_id" android:value="${EMAS_VIVO_APP_ID}"/>
    <meta-data android:name="com.vivo.push.api_key" android:value="${EMAS_VIVO_APP_KEY}"/>
    <meta-data android:name="OPPO_PUSH_APP_KEY" android:value="${EMAS_OPPO_APP_KEY}"/>
    <meta-data android:name="OPPO_PUSH_APP_SECRET" android:value="${EMAS_OPPO_APP_SECRET}"/>
    <meta-data android:name="MZ_PUSH_APP_ID" android:value="${EMAS_MEIZU_APP_ID}"/>
    <meta-data android:name="MZ_PUSH_APP_KEY" android:value="${EMAS_MEIZU_APP_KEY}"/>
    ...
</application>

步骤四:在代码中读取获取相关Id和Key(插件内部实现,无需手动设置)

    ApplicationInfo appInfo = application.getPackageManager().getApplicationInfo(application.getPackageName(), PackageManager.GET_META_DATA);
    boolean enableDebug = appInfo.metaData.getBoolean("ALIYUN_PUSH_DEBUG", false);
    String miPushAppId  = appInfo.metaData.getString("MI_PUSH_APP_ID", "").trim();
    String miPushAppKey  = appInfo.metaData.getString("MI_PUSH_APP_KEY", "").trim();

JS API

初始化API

  Aliyun.onMessage = message => this.messageHandler(message);
  Aliyun.onError = err => this.errorHandler(err);
  await AliyunPush.boot("xiaomi,huawei,honor,vivo,oppo,meizu");

返回消息Message结构:

{

type:string 消息类型,

title:string '阿里云推送',

body:string '推送的内容',

params:string | Object<k,v> 外健,

url:路由(后台发送推送时,在ExtParameters参数里写入url如{url:'demoapp://...'})

id: url中的id

}

消息Type类型:

{

message:透传消息,

notification:通知接收,

notificationOpened:通知点击,

notificationReceived:通知到达,

notificationRemoved:通知移除,

notificationClickedWithNoAction:通知到达,

notificationReceivedInApp:通知到达打开 app

}

其他API

  /**
   * 启动推送
   * @param  {string} androidVendors Android厂商通道列表: xiaomi,huawei,honor,vivo,oppo,meizu
   * @return {void}
   */
  boot: async function (androidVendors) -> void

  /**
   * 检查通知的权限
   * @param  {boolean} force 检查到没权限时直接申请权限
   * @return {object} flags -> granted, denied, asked, neverAsked, unknown (iOS only)
   */
  checkPermission: async function (force) -> object

  /**
   * 打开App设置页
   * @return {void}
   */
  openAppSettings: async function () -> void

  /**
   * 没有权限时,请求开通通知权限
   * @return {void}
   */
  requestPermission: async function () -> void
  
  /**
   * 获取设备唯一标识deviceId,deviceId为阿里云移动推送过程中对设备的唯一标识(并不是设备UUID/UDID)
   * @return {string} 设备注册码
   */
  getRegisterId: async function () -> string

  /**
   * 阿里云推送绑定账号名
   * @param  {string} account 账号
   * @return {void}
   */
  bindAccount: async function (account) -> void

  /**
   * 阿里云推送解除账号名,退出切换账号时调用
   * @return {void}
   */
  unbindAccount: async function () -> void

  /**
   * 阿里云推送绑定标签
   * @param  {string} target 目标
   * @param  {string[]} tags 标签列表
   * @param  {string} alias 别名
   * @return {void}
   */
  bindTags: async function (target, tags, alias) -> void

  /**
   * 阿里云推送解除绑定标签
   * @param  {string} target 目标
   * @param  {string[]} tags 标签列表
   * @param  {string} alias 别名
   * @return {void}
   */
  unbindTags: async function (target, tags, alias) -> void

  /**
   * 阿里云推送列出标签
   * @return {void}
   */
  listTags: async function () -> void

  /**
   * 添加别名
   * @param  {string} alias 别名
   * @return {void}
   */
  addAlias: async function (alias) -> void

  /**
   * 解绑别名
   * @param  {string} alias 别名
   * @return {void}
   */
  removeAlias: async function (alias) -> void

  /**
   * 获取别名列表
   * @return {void}
   */
  listAliases: async function () -> void

  /**
   * 设置服务端角标数量 - iOS ONLY
   * @param  {string} badgeNum 角标数量
   * @return {void}
   */
  syncBadgeNum: async function (badgeNum) -> void

  /**
   * 设置本地角标数量 - iOS ONLY
   * @param  {string} badgeNum 角标数量
   * @return {void}
   */
  setBadgeNum: async function (badgeNum) -> void
  

常见问题

  • Android

    • 查看日志显示通知已经从服务器发送到客户端但没有在通知栏显示

      Android 8.0以上需要设置NotificationChannel,详情:https://help.aliyun.com/document_detail/67398.html

      客户端和服务器设置的Channel必须一致,默认客户端端口是1!

      如果配置了厂商通道,调用API时候必须加入辅助弹窗需要的参数如下:

        AndroidOpenType: ACTIVITY
        AndroidActivity: com.example.myFirstApp.MainActivity
        AndroidPopupActivity:com.example.myFirstApp.MainActivity
        AndroidPopupTitle: <通知标题>
        AndroidPopupBody: <通知内容>

      注意:辅助弹窗仅在当前厂商通道设备的应用后台进程被清理时生效,对非接入厂商通道设备和在线的设备不生效并优先走阿里云推送。

    • 厂商通道每个都不同,如何优化客户端创建的通道数量

      建议先创建小米通知类别,再根据小米生成的通道ID手动设置oppo通道ID,这样可以统一客户端的通知类别。

      在客户端设置variables.gradle添加aliyunPushChannelId配置:

      ext {
        ...
        aliyunPushChannelId = '123456:应用公告'
      }

      在服务器调用API时候添加如下参数:

        ......
        "androidNotificationChannel": "123456",
        "androidNotificationXiaomiChannel": "123456"
        ......
    • 杀死App点击通知无法打开APP

      后端推送时添加 AndroidExtParameters {open_type:"application"}

    • com.android.tools.build:gradle:3.3.0打包报错

      使用3.3.3版

    • Android 8.0以上无法获取到Token

      检查是否配置了network_security_config.xml信息,具体百度了解

    • 构建apk时候报错Missing classes detected while running R8.或者启动App时闪退?

      这是构建时使用了混淆导致的,在appproguard-rules.pro中添加以下内容:

        # Rules for general channel of aliyun EMAS
        -keepclasseswithmembernames class ** {
            native <methods>;
        }
        -keepattributes Signature
        -keep class sun.misc.Unsafe { *; }
        -keep class com.taobao.** {*;}
        -keep class com.alibaba.** {*;}
        -keep class com.alipay.** {*;}
        -keep class com.ut.** {*;}
        -keep class com.ta.** {*;}
        -keep class anet.**{*;}
        -keep class anetwork.**{*;}
        -keep class org.android.spdy.**{*;}
        -keep class org.android.agoo.**{*;}
        -keep class android.os.**{*;}
        -keep class org.json.**{*;}
        -dontwarn com.taobao.**
        -dontwarn com.alibaba.**
        -dontwarn com.alipay.**
        -dontwarn anet.**
        -dontwarn org.android.spdy.**
        -dontwarn org.android.agoo.**
        -dontwarn anetwork.**
        -dontwarn com.ut.**
        -dontwarn com.ta.**
      
        # Rules for xiaomi push channel of aliyun EMAS
        -keep class com.xiaomi.** {*;}
        -dontwarn com.xiaomi.**
      
        # Rules for huawei push channel of aliyun EMAS
        -keep class com.huawei.** {*;}
        -dontwarn com.huawei.**
      
        # Rules for honor push channel of aliyun EMAS
        -ignorewarnings
        -keepattributes *Annotation*
        -keepattributes Exceptions
        -keepattributes InnerClasses
        -keepattributes Signature
        -keepattributes SourceFile,LineNumberTable
        -keep class com.hihonor.push.**{*;}
      
        # Rules for vivo push channel of aliyun EMAS
        -keep class com.vivo.** {*;}
        -dontwarn com.vivo.**
      
        # Rules for oppo push channel of aliyun EMAS
        -keep public class * extends android.app.Service
      
        # Rules for meizu push channel of aliyun EMAS
        -keep class com.meizu.cloud.** {*;}
        -dontwarn com.meizu.cloud.**
  • iOS

    • iOS无法获取到Token

      Xcode中确认开启以下两项

    • 角标数字不正确

      当前iOS角标做法是打开APP或点击通知就读取通知个数并同步到阿里云服务器,请在通知添加 { iOSBadgeAutoIncrement: true }