共计 24706 个字符,预计需要花费 62 分钟才能阅读完成。
前言:在集成 ReactNative 推送之前,须要理解 ReactNative 与 Android 原生交互
一、RN 与 Android 原生交互
RN 给原生传递参数
步骤:
1. 用 Android Studio 关上一个曾经存在的 RN 我的项目,即用 AS 关上 我的项目文件夹 /android, 如下图所示
2. 在 Android 原生这边创立一个类继承 ReactContextBaseJavaModule,这个类里边放咱们须要被 RN 调用的办法,将其封装成一个原生模块。
MyNativeModule.java 代码如下:
package com.awesomeproject; | |
import com.facebook.react.bridge.ReactApplicationContext; | |
import com.facebook.react.bridge.ReactContextBaseJavaModule; | |
import com.facebook.react.bridge.ReactMethod; | |
import com.facebook.react.modules.core.DeviceEventManagerModule; | |
import com.xiaomi.mipush.sdk.MiPushClient; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
public class PushModule extends ReactContextBaseJavaModule { | |
private ReactApplicationContext reactContext; | |
public PushModule(ReactApplicationContext reactContext) {super(reactContext); | |
this.reactContext = reactContext; | |
} | |
@Override | |
public String getName() {return "PushModule";} | |
/** | |
从 RN 界面外面调用该办法 | |
**/ | |
@ReactMethod | |
public void getDeviceToken(){MainApplication.getReactPackage().mModule.sendDataToJS(MiPushClient.getRegId(MainApplication.getContext())); | |
} | |
public void sendDataToJS(String deviceToken){JSONObject jsonObject = new JSONObject(); | |
try {jsonObject.put("deviceToken",deviceToken); | |
jsonObject.put("deviceName",""); | |
} catch (JSONException e) {throw new RuntimeException(e); | |
} | |
this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) | |
.emit("deviceToken",jsonObject.toString()); | |
} | |
} |
本类中寄存咱们要复用的原生办法,继承了 ReactContextBaseJavaModule 类,并且实现了其 getName()办法,构造方法也是必须的。按着 Alt+Enter 程序会主动提醒。接着定义了一个办法,该办法必须应用注解 @ReactMethod 表明,阐明是 RN 要调用的办法。
3. 在 Android 原生这边创立一个类实现接口 ReactPackage 包管理器,并把第二步创立的类加到原生模块(NativeModule)列表里。
PushPackage.java 代码如下:
package com.awesomeproject; | |
import com.facebook.react.ReactPackage; | |
import com.facebook.react.bridge.NativeModule; | |
import com.facebook.react.bridge.ReactApplicationContext; | |
import com.facebook.react.uimanager.ViewManager; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
public class PushPackage implements ReactPackage { | |
public PushModule mModule; | |
@Override | |
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {List<NativeModule> list = new ArrayList<>(); | |
mModule = new PushModule(reactContext); | |
list.add(mModule); | |
return list; | |
} | |
@Override | |
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {return Collections.emptyList(); | |
} | |
} |
4. 将第三步创立的包管理器增加到 ReactPackage 列表里(getPackage 办法里)
MainApplication.java 代码如下:
package com.awesomeproject; | |
import android.app.Application; | |
import android.content.Context; | |
import android.util.Log; | |
import com.facebook.react.PackageList; | |
import com.facebook.react.ReactApplication; | |
import com.facebook.react.ReactInstanceManager; | |
import com.facebook.react.ReactNativeHost; | |
import com.facebook.react.ReactPackage; | |
import com.facebook.react.config.ReactFeatureFlags; | |
import com.facebook.soloader.SoLoader; | |
import com.awesomeproject.newarchitecture.MainApplicationReactNativeHost; | |
import com.vivo.push.IPushActionListener; | |
import com.vivo.push.PushClient; | |
import com.vivo.push.PushConfig; | |
import com.vivo.push.util.VivoPushException; | |
import com.xiaomi.channel.commonutils.logger.LoggerInterface; | |
import com.xiaomi.mipush.sdk.Logger; | |
import com.xiaomi.mipush.sdk.MiPushClient; | |
import java.lang.reflect.InvocationTargetException; | |
import java.util.List; | |
public class MainApplication extends Application implements ReactApplication { | |
private final ReactNativeHost mReactNativeHost = | |
new ReactNativeHost(this) { | |
@Override | |
public boolean getUseDeveloperSupport() {return BuildConfig.DEBUG;} | |
@Override | |
protected List<ReactPackage> getPackages() {@SuppressWarnings("UnnecessaryLocalVariable") | |
List<ReactPackage> packages = new PackageList(this).getPackages(); | |
packages.add(mCommPackage); | |
// Packages that cannot be autolinked yet can be added manually here, for example: | |
// packages.add(new MyReactNativePackage()); | |
return packages; | |
} | |
@Override | |
protected String getJSMainModuleName() {return "index";} | |
}; | |
private final ReactNativeHost mNewArchitectureNativeHost = | |
new MainApplicationReactNativeHost(this); | |
@Override | |
public ReactNativeHost getReactNativeHost() {if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {return mNewArchitectureNativeHost;} else {return mReactNativeHost;} | |
} | |
static Context context; | |
public static Context getContext() {return context;} | |
private static final PushPackage mCommPackage = new PushPackage(); | |
public static PushPackage getReactPackage() {return mCommPackage;} | |
@Override | |
public void onCreate() {super.onCreate(); | |
context = this; | |
// If you opted-in for the New Architecture, we enable the TurboModule system | |
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; | |
SoLoader.init(this, /* native exopackage */ false); | |
initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); | |
// 初始化 push | |
try { | |
//PushConfig.agreePrivacyStatement 属性及含意阐明请参考接口文档 | |
// 应用办法 | |
PushConfig config = new PushConfig.Builder() | |
.agreePrivacyStatement(true) | |
.build(); | |
PushClient.getInstance(MainApplication.this).initialize(config); | |
} catch (VivoPushException e) {Log.d("VivoPushException","-------------"+e.toString()); | |
// 此处异样阐明是有必须的 vpush 配置未配置所致,须要仔细检查集成指南的各项配置。e.printStackTrace();} | |
// 关上 push 开关, 敞开为 turnOffPush,详见 api 接入文档 | |
PushClient.getInstance(this).turnOnPush(new IPushActionListener() { | |
@Override | |
public void onStateChanged(int state) { | |
// TODO: 开关状态解决,0 代表胜利,获取 regid 倡议在 state= 0 后获取;Log.d("vivo 初始化 ------","开关状态解决,0 代表胜利,获取 regid 倡议在 state= 0 后获取 ----"+state); | |
} | |
}); | |
// 小米初始化 push 推送服务 | |
MiPushClient.registerPush(this, "2882303761517520571", "5841752092571"); | |
// 关上 Log | |
LoggerInterface newLogger = new LoggerInterface() { | |
@Override | |
public void setTag(String tag) {Log.d("MainApplication-------",tag); | |
// ignore | |
} | |
@Override | |
public void log(String content, Throwable t) {Log.d("MainApplication-------",content+"-----"+t.toString()); | |
} | |
@Override | |
public void log(String content) {Log.d("MainApplication-------",content); | |
} | |
}; | |
Logger.setLogger(this, newLogger); | |
} | |
/** | |
* Loads Flipper in React Native templates. Call this in the onCreate method with something like | |
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); | |
* | |
* @param context | |
* @param reactInstanceManager | |
*/ | |
private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {if (BuildConfig.DEBUG) { | |
try { | |
/* | |
We use reflection here to pick up the class that initializes Flipper, | |
since Flipper library is not available in release mode | |
*/ | |
Class<?> aClass = Class.forName("com.awesomeproject.ReactNativeFlipper"); | |
aClass | |
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) | |
.invoke(null, context, reactInstanceManager); | |
} catch (ClassNotFoundException e) {e.printStackTrace(); | |
} catch (NoSuchMethodException e) {e.printStackTrace(); | |
} catch (IllegalAccessException e) {e.printStackTrace(); | |
} catch (InvocationTargetException e) {e.printStackTrace(); | |
} | |
} | |
} | |
} |
5. 在 RN 中去调用原生模块,必须 import NativeModule 模块。
批改 App.js 文件,须要从‘react-native’中援用‘NativeModules’,
App.js 代码如下:
NativeModules.PushModule.getDeviceToken();
来剖析一下程序运行流程:
(1)在配置文件 AndroidManifest.xml 中,android:name=”.MainApplication”,则 MainApplication.java 会执行。
(2)在 MainApplication.java 中,有咱们创立的包管理器对象。程序退出 PushPackage.java 中。
(3)在 PushPackage.java 中,将咱们本人创立的模块退出了原生模块列表中,程序进入 PushModule.java 中。
(4)在 PushModule.java 中,提供 RN 调用的办法 getDeviceToken
实现数据从 Android 原生回调到 RN 前端界面
咱们都晓得,要被 RN 调用的办法必须是 void 类型,即没有返回值,然而我的项目中很多中央都须要返回数据。那怎么实现呢?
步骤:
1. 在 Android 原生这边创立一个类继承 ReactContextBaseJavaModule,这个类里边放咱们须要被 RN 调用的办法,将其封装成一个原生模块。
在下面的 PushModule 中曾经继承了 ReactContextBaseJavaModule
咱们须要调用 sendDataToJS 将数据传到 RN 层。
PushModule.java 代码如下
package com.awesomeproject; | |
import com.facebook.react.bridge.ReactApplicationContext; | |
import com.facebook.react.bridge.ReactContextBaseJavaModule; | |
import com.facebook.react.bridge.ReactMethod; | |
import com.facebook.react.modules.core.DeviceEventManagerModule; | |
import com.xiaomi.mipush.sdk.MiPushClient; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
public class PushModule extends ReactContextBaseJavaModule { | |
private ReactApplicationContext reactContext; | |
public PushModule(ReactApplicationContext reactContext) {super(reactContext); | |
this.reactContext = reactContext; | |
} | |
@Override | |
public String getName() {return "PushModule";} | |
/** | |
从 RN 界面外面调用该办法 | |
**/ | |
@ReactMethod | |
public void getDeviceToken(){MainApplication.getReactPackage().mModule.sendDataToJS(MiPushClient.getRegId(MainApplication.getContext())); | |
} | |
public void sendDataToJS(String deviceToken){JSONObject jsonObject = new JSONObject(); | |
try {jsonObject.put("deviceToken",deviceToken); | |
jsonObject.put("deviceName","2882303761517520571"); | |
} catch (JSONException e) {throw new RuntimeException(e); | |
} | |
this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) | |
.emit("deviceToken",jsonObject.toString()); | |
} | |
} |
步骤:
1、在 RN 中调用原生的办法
NativeModules.PushModule.getDeviceToken(); |
2、原生提供对应的办法,将数据传递
3、RN 接管原生传递的数据
至此,咱们实现了 RN 复用原生代码,行将原生模块封装成一个接口,在 RN 中调用。并且能够封装更加简单的办法,同时实现了数据回调,行将数据从原生模块中传递到 RN 前端。
二、原生获取设施信息和 ReactNative 进行绑定信息
本文介绍如何如何从原生获取推送所须要的设施信息以及ReactNative 绑定信息
前提条件
集成环信即时通讯 React-Native,并且能够失常运行,初始化以及登录
集成文档见环信官网:https://docs-im-beta.easemob.com/document/react-native/quicks…
原生获取设施信息:
华为:
在获取华为推送 token 之前,咱们须要先集成华为 sdk,能够参考华为官网官网的集成,也能够参考环信官网进行集成;
获取推送 token 参考华为官网文档
获取代码如下:
private void getToken() { | |
// 创立一个新线程 | |
new Thread() { | |
@Override | |
public void run() { | |
try { | |
// 从 agconnect-services.json 文件中读取 APP_ID | |
String appId = "your APP_ID"; | |
// 输出 token 标识 "HCM" | |
String tokenScope = "HCM"; | |
String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, tokenScope); | |
Log.i(TAG, "get token:" + token); | |
// 判断 token 是否为空 | |
if(!TextUtils.isEmpty(token)) {sendRegTokenToServer(token); | |
} | |
} catch (ApiException e) {Log.e(TAG, "get token failed," + e); | |
} | |
} | |
}.start();} | |
private void sendRegTokenToServer(String token) {Log.i(TAG, "sending token to server. token:" + token); | |
} |
华为官网有具体的集成介绍,能够仔细阅读,getToken() 办法获取到的就是推送所须要的 token。
小米:
1. 前提条件
您已启用推送服务,并取得利用的 AppId、AppKey 和 AppSecret。
2. 接入筹备
- 下载 MiPush Android 客户端 SDK 软件包
MiPush Android 客户端 SDK 从 5.0.1 版本开始,提供 AAR 包接入形式,其反对的最低 Android SDK 版本为 19。
下载地址:https://admin.xmpush.xiaomi.com/zh_CN/mipush/downpage
建议您下载最新版本。 - 如您之前通过 JAR 包形式接入过 MiPush 客户端 SDK,需将原 JAR 包接入配置齐全删除,具体配置请参见《Android 客户端 SDK 集成指南(JAR 版)》。
-
接入领导
增加依赖
首先将 MiPush SDK 的 AAR 包如 MiPush_SDK_Client_xxx.aar 复制到我的项目 /libs/ 目录,而后在我的项目 APP module 的 build.gradle 中依赖:android{ repositories { flatDir {dirs 'libs'} } } dependencies {implementation (name: 'MiPush_SDK_Client_xxx', ext: 'aar') } 而后须要把该自定义 BroadcastReceiver 注册到 AndroidManifest.xml 文件中,注册内容如下:
<receiver android:exported="true" android:name="com.xiaomi.mipushdemo.DemoMessageReceiver"> <!-- 这里 com.xiaomi.mipushdemo.DemoMessageRreceiver 改成 app 中定义的残缺类名 --> <intent-filter> <action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" /> </intent-filter> <intent-filter> <action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" /> </intent-filter> <intent-filter> <action android:name="com.xiaomi.mipush.ERROR" /> </intent-filter> </receiver>
留神:请务必确保该自定义 BroadcastReceiver 所在过程与调用注册推送接口(MiPushClient.registerPush())的过程为同一过程(强烈建议都在主过程中)。
注册推送服务
通过调用 MiPushClient.registerPush 来初始化小米推送服务。注册胜利后,您能够在自定义的 onCommandResult 和 onReceiveRegisterResult 中收到注册后果,其中的 regId 即是以后设施上以后 app 的惟一标示。您能够将 regId 上传到本人的服务器,不便向其发消息。
为了进步 push 的注册率,您能够在 Application 的 onCreate 中初始化 push。您也能够依据须要,在其余中央初始化 push。代码如下:
public class DemoApplication extends Application { | |
public static final String APP_ID = "your appid"; | |
public static final String APP_KEY = "your appkey"; | |
public static final String TAG = "your packagename"; | |
@Override | |
public void onCreate() {super.onCreate(); | |
// 初始化 push 推送服务 | |
if(shouldInit()) {MiPushClient.registerPush(this, APP_ID, APP_KEY); | |
} | |
// 关上 Log | |
LoggerInterface newLogger = new LoggerInterface() { | |
@Override | |
public void setTag(String tag) {// ignore} | |
@Override | |
public void log(String content, Throwable t) {Log.d(TAG, content, t); | |
} | |
@Override | |
public void log(String content) {Log.d(TAG, content); | |
} | |
}; | |
Logger.setLogger(this, newLogger); | |
} | |
private boolean shouldInit() {ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)); | |
List<RunningAppProcessInfo> processInfos = am.getRunningAppProcesses(); | |
String mainProcessName = getApplicationInfo().processName; | |
int myPid = Process.myPid(); | |
for (RunningAppProcessInfo info : processInfos) {if (info.pid == myPid && mainProcessName.equals(info.processName)) {return true;} | |
} | |
return false; | |
} | |
} |
最初获取推送 token,代码如下
MiPushClient.getRegId(MainApplication.getContext()) |
vivo:
vivo sdk 下载地址:https://swsdl.vivo.com.cn/appstore/developer/uploadFile/20230602/qrmgtt/vivopushsdk_3.0.0.7_488.rar
一、集成 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.7_488.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="488"/> |
二、启动推送
在工程的 Application 中,增加以下代码,用来启动关上 push 开关,胜利后即可在告诉音讯达到时收到告诉。
// 在以后工程入口函数,倡议在 Application 的 onCreate 函数中,在获取用户的批准后,增加以下代码:
// 初始化 push | |
try { | |
//PushConfig.agreePrivacyStatement 属性及含意阐明请参考接口文档 | |
// 应用办法 | |
PushConfig config = new PushConfig.Builder() | |
.agreePrivacyStatement(true/false) | |
.build(); | |
PushClient.getInstance(this).initialize(config); | |
} catch (VivoPushException e) { | |
// 此处异样阐明是有必须的 vpush 配置未配置所致,须要仔细检查集成指南的各项配置。e.printStackTrace();} | |
// 关上 push 开关, 敞开为 turnOffPush,详见 api 接入文档 | |
PushClient.getInstance(getApplicationContext()).turnOnPush(new IPushActionListener() { | |
@Override | |
public void onStateChanged(int state) {// TODO: 开关状态解决,0 代表胜利,获取 regid 倡议在 state= 0 后获取;} | |
}); |
三、获取 token
即获取 regId,应用 getRegId() 函数获取参考如下:PushClient.getInstance(context).getRegId(new IPushQueryActionListener() { | |
@Override | |
public void onSuccess(String regid) {// 获取胜利,回调参数即是以后利用的 regid;} | |
@Override | |
public void onFail(Integer errerCode) {// 获取失败,能够联合错误码参考查问失败起因;}}); | |
在 Api 接口 turnOnPush 回调胜利之后,即可获取到注册 id。 |
注:详情及别的性能见 vivo 官网文档:https://dev.vivo.com.cn/documentCenter/doc/365
oppo:
SDK 集成步骤
注册并下载 SDK
Android 的 SDK 以 aar 模式提供,第三方 APP 只须要增加大量代码即可接入 OPPO 推送服务。
代码参考 demo 下载:heytapPushDemo
下载 aar 文件,即 3.1.0 版本 sdk:com.heytap.msp_3.1.0.aar
aar 依赖
第一步:增加 maven 仓库
repositories {google() | |
mavenCentral()} |
第二步:增加 maven 依赖
implementation(name: 'com.heytap.msp_3.1.0', ext: 'aar') | |
// 以下依赖都须要增加 | |
implementation 'com.google.code.gson:gson:2.6.2' | |
implementation 'commons-codec:commons-codec:1.6' | |
implementation 'com.android.support:support-annotations:28.0.0'(SDK 中的接入最小依赖项,也能够参考 demo 中的依赖) |
第三步:增加 aar 配置
在 build 文件中增加以下代码
Android{ | |
.... | |
repositories { | |
flatDir {dirs 'libs'} | |
} | |
.... | |
} |
配置 AndroidManifest.xml
1)OPPO 推送服务 SDK 反对的最低安卓版本为 Android 4.4 零碎。<uses-sdk android:minSdkVersion="19"/> | |
2)推送服务组件注册 | |
// 必须配置 | |
<service | |
android:name="com.heytap.msp.push.service.XXXService" | |
android:permission="com.heytap.mcs.permission.SEND_PUSH_MESSAGE" | |
android:exported="true"> | |
<intent-filter> | |
<action android:name="com.heytap.mcs.action.RECEIVE_MCS_MESSAGE"/> | |
<action android:name="com.heytap.msp.push.RECEIVE_MCS_MESSAGE"/> | |
</intent-filter> | |
</service>(兼容 Q 版本,继承 DataMessageCallbackService)<service | |
android:name="com.heytap.msp.push.service.XXXService" | |
android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE" | |
android:exported="true"> | |
<intent-filter> | |
<action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE"/> | |
</intent-filter> | |
</service>(兼容 Q 以下版本,继承 CompatibleDataMessageCallbackService) |
注册推送服务
1) 利用举荐在 Application 类主过程中调用 HeytapPushManager.init(…)接口,这个办法不是耗时操作,执行之后能力应用推送服务
2) 业务须要调用 api 接口,例如利用内开关开启 / 敞开,须要调用注册接口之后,才会失效
3) 因为不是所有平台都反对 MSP PUSH,提供接口 HeytapPushManager.isSupportPush()不便利用判断是否反对, 反对能力执行后续操作
4) 通过调用 HeytapPushManager.register(…)进行利用注册,注册胜利后, 您能够在 ICallBackResultService 的 onRegister 回调办法中失去 regId, 您能够将 regId 上传到本人的服务器,不便向其发消息。初始化相干参数具体要求参考具体 API 阐明中的初始化局部。
5)为了进步 push 的注册率,你能够在 Application 的 onCreate 中初始化 push。你也能够依据须要,在其余中央初始化 push。如果第一次注册失败, 第二次能够间接调用 PushManager.getInstance().getRegister()进行重试, 此办法默认会应用第一次传入的参数掉调用注册。
至此,咱们获取到了不同设施的 device_token
三、从原生将 device_token 传到 RN 并且绑定
1、原生调用办法
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) | |
.emit("deviceToken",jsonObject.toString()); |
通过 PushModule 类进行传递,PushModule 代码如下:
package com.awesomeproject; | |
import com.facebook.react.bridge.ReactApplicationContext; | |
import com.facebook.react.bridge.ReactContextBaseJavaModule; | |
import com.facebook.react.bridge.ReactMethod; | |
import com.facebook.react.modules.core.DeviceEventManagerModule; | |
import com.xiaomi.mipush.sdk.MiPushClient; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
public class PushModule extends ReactContextBaseJavaModule { | |
private ReactApplicationContext reactContext; | |
public PushModule(ReactApplicationContext reactContext) {super(reactContext); | |
this.reactContext = reactContext; | |
} | |
@Override | |
public String getName() {return "PushModule";} | |
/** | |
从 RN 界面外面调用该办法 | |
**/ | |
@ReactMethod | |
public void getDeviceToken(){MainApplication.getReactPackage().mModule.sendDataToJS(MiPushClient.getRegId(MainApplication.getContext())); | |
} | |
public void sendDataToJS(String deviceToken){JSONObject jsonObject = new JSONObject(); | |
try {jsonObject.put("deviceToken",deviceToken); | |
jsonObject.put("deviceName","2882303761517520571"); | |
} catch (JSONException e) {throw new RuntimeException(e); | |
} | |
this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) | |
.emit("deviceToken",jsonObject.toString()); | |
} | |
} |
2、RN 层进行获取数据
NativeModules.PushModule.getDeviceToken(); | |
DeviceEventEmitter.addListener('deviceToken',(res)=>{const goosid = JSON.parse(res); | |
deviceToken = goosid.deviceToken; | |
manufacturer = goosid.deviceName; | |
console.log('React Native 界面, 收到数据:',goosid); |
3、获取到数据后调用环信 RN sdk 办法进行绑定
ChatClient.getInstance().updatePushConfig(push);
js 代码如下
// 导入依赖库 | |
import React, {useEffect} from 'react'; | |
import { | |
DeviceEventEmitter, | |
NativeModules, | |
SafeAreaView, | |
ScrollView, | |
StyleSheet, | |
Text, | |
TextInput, | |
View, | |
} from 'react-native'; | |
import { | |
ChatClient, | |
ChatMessage, | |
ChatMessageChatType, | |
ChatOptions, | |
ChatPushConfig, | |
} from 'react-native-chat-sdk'; | |
// 创立 app | |
const App = () => { | |
// 进行 app 设置 | |
const title = 'ChatQuickstart'; | |
var deviceToken=''; | |
var manufacturer=''; | |
NativeModules.PushModule.getDeviceToken(); | |
DeviceEventEmitter.addListener('deviceToken',(res)=>{const goosid = JSON.parse(res); | |
deviceToken = goosid.deviceToken; | |
manufacturer = goosid.deviceName; | |
console.log('React Native 界面, 收到数据:',goosid); | |
}) | |
const [appKey, setAppKey] = React.useState('1137220225110285#demo'); | |
const [username, setUsername] = React.useState('p9'); | |
const [password, setPassword] = React.useState('1'); | |
const [userId, setUserId] = React.useState(''); | |
const [content, setContent] = React.useState(''); | |
const [logText, setWarnText] = React.useState('Show log area'); | |
// 输入 console log 文件 | |
useEffect(() => {logText.split('\n').forEach((value, index, array) => {if (index === 0) {console.log(value); | |
} | |
}); | |
}, [logText]); | |
// 输入 UI log 文件 | |
const rollLog = text => { | |
setWarnText(preLogText => { | |
let newLogText = text; | |
preLogText | |
.split('\n') | |
.filter((value, index, array) => {if (index > 8) {return false;} | |
return true; | |
}) | |
.forEach((value, index, array) => {newLogText += '\n' + value;}); | |
return newLogText; | |
}); | |
}; | |
// 设置音讯监听器。const setMessageListener = () => { | |
let msgListener = {onMessagesReceived(messages) {for (let index = 0; index < messages.length; index++) {rollLog('received msgId:' + messages[index].msgId); | |
} | |
}, | |
onCmdMessagesReceived: messages => {}, | |
onMessagesRead: messages => {}, | |
onGroupMessageRead: groupMessageAcks => {}, | |
onMessagesDelivered: messages => {}, | |
onMessagesRecalled: messages => {}, | |
onConversationsUpdate: () => {}, | |
onConversationRead: (from, to) => {},}; | |
ChatClient.getInstance().chatManager.removeAllMessageListener(); | |
ChatClient.getInstance().chatManager.addMessageListener(msgListener); | |
}; | |
// SDK 初始化。// 调用任何接口之前,请先进行初始化。const init = () => { | |
let option = new ChatOptions({ | |
autoLogin: false, | |
appKey: appKey | |
}); | |
ChatClient.getInstance().removeAllConnectionListener(); | |
ChatClient.getInstance() | |
.init(option) | |
.then(() => {rollLog('init success'); | |
this.isInitialized = true; | |
let listener = {onTokenWillExpire() {rollLog('token expire.'); | |
}, | |
onTokenDidExpire() {rollLog('token did expire'); | |
}, | |
onConnected() {rollLog('login success.'); | |
setMessageListener();}, | |
onDisconnected(errorCode) {rollLog('login fail:' + errorCode); | |
}, | |
}; | |
ChatClient.getInstance().addConnectionListener(listener); | |
}) | |
.catch(error => { | |
rollLog( | |
'init fail:' + | |
(error instanceof Object ? JSON.stringify(error) : error), | |
); | |
}); | |
}; | |
// 注册账号。const registerAccount = () => {if (this.isInitialized === false || this.isInitialized === undefined) {rollLog('Perform initialization first.'); | |
return; | |
} | |
rollLog('start register account ...'); | |
ChatClient.getInstance() | |
.createAccount(username, password) | |
.then(response => {rollLog(`register success: userName = ${username}, password = ******`); | |
}) | |
.catch(error => {rollLog('register fail:' + JSON.stringify(error)); | |
}); | |
}; | |
// 用环信即时通讯 IM 账号和明码登录。const loginWithPassword = () => {if (this.isInitialized === false || this.isInitialized === undefined) {rollLog('Perform initialization first.'); | |
return; | |
} | |
rollLog('start login ...'); | |
ChatClient.getInstance() | |
.login(username, password) | |
.then(() => {rollLog('login operation success.'); | |
let push = new ChatPushConfig({ | |
deviceId:manufacturer, | |
deviceToken:deviceToken, | |
}); | |
console.log("--------------------------------------------"); | |
console.log(manufacturer); | |
console.log(deviceToken); | |
console.log("--------------------------------------------"); | |
ChatClient.getInstance().updatePushConfig(push); | |
}) | |
.catch(reason => {rollLog('login fail:' + JSON.stringify(reason)); | |
}); | |
}; | |
// 登出。const logout = () => {if (this.isInitialized === false || this.isInitialized === undefined) {rollLog('Perform initialization first.'); | |
return; | |
} | |
rollLog('start logout ...'); | |
ChatClient.getInstance() | |
.logout() | |
.then(() => {rollLog('logout success.'); | |
}) | |
.catch(reason => {rollLog('logout fail:' + JSON.stringify(reason)); | |
}); | |
}; | |
// 发送一条文本音讯。const sendmsg = () => {if (this.isInitialized === false || this.isInitialized === undefined) {rollLog('Perform initialization first.'); | |
return; | |
} | |
let msg = ChatMessage.createTextMessage( | |
userId, | |
content, | |
ChatMessageChatType.PeerChat, | |
); | |
const callback = new (class {onProgress(locaMsgId, progress) {rollLog(`send message process: ${locaMsgId}, ${progress}`); | |
} | |
onError(locaMsgId, error) {rollLog(`send message fail: ${locaMsgId}, ${JSON.stringify(error)}`); | |
} | |
onSuccess(message) {rollLog('send message success:' + message.localMsgId); | |
} | |
})(); | |
rollLog('start send message ...'); | |
ChatClient.getInstance() | |
.chatManager.sendMessage(msg, callback) | |
.then(() => {rollLog('send message:' + msg.localMsgId); | |
}) | |
.catch(reason => {rollLog('send fail:' + JSON.stringify(reason)); | |
}); | |
}; | |
// UI 组件渲染。return ( | |
<SafeAreaView> | |
<View style={styles.titleContainer}> | |
<Text style={styles.title}>{title}</Text> | |
</View> | |
<ScrollView> | |
<View style={styles.inputCon}> | |
<TextInput | |
multiline | |
style={styles.inputBox} | |
placeholder="Enter appkey" | |
onChangeText={text => setAppKey(text)} | |
value={appKey} | |
/> | |
</View> | |
<View style={styles.buttonCon}> | |
<Text style={styles.btn2} onPress={init}> | |
INIT SDK | |
</Text> | |
</View> | |
<View style={styles.inputCon}> | |
<TextInput | |
multiline | |
style={styles.inputBox} | |
placeholder="Enter username" | |
onChangeText={text => setUsername(text)} | |
value={username} | |
/> | |
</View> | |
<View style={styles.inputCon}> | |
<TextInput | |
multiline | |
style={styles.inputBox} | |
placeholder="Enter password" | |
onChangeText={text => setPassword(text)} | |
value={password} | |
/> | |
</View> | |
<View style={styles.buttonCon}> | |
<Text style={styles.eachBtn} onPress={registerAccount}> | |
SIGN UP | |
</Text> | |
<Text style={styles.eachBtn} onPress={loginWithPassword}> | |
SIGN IN | |
</Text> | |
<Text style={styles.eachBtn} onPress={logout}> | |
SIGN OUT | |
</Text> | |
</View> | |
<View style={styles.inputCon}> | |
<TextInput | |
multiline | |
style={styles.inputBox} | |
placeholder="Enter the username you want to send" | |
onChangeText={text => setUserId(text)} | |
value={userId} | |
/> | |
</View> | |
<View style={styles.inputCon}> | |
<TextInput | |
multiline | |
style={styles.inputBox} | |
placeholder="Enter content" | |
onChangeText={text => setContent(text)} | |
value={content} | |
/> | |
</View> | |
<View style={styles.buttonCon}> | |
<Text style={styles.btn2} onPress={sendmsg}> | |
SEND TEXT | |
</Text> | |
</View> | |
<View> | |
<Text style={styles.logText} multiline={true}> | |
{logText} | |
</Text> | |
</View> | |
<View> | |
<Text style={styles.logText}>{}</Text> | |
</View> | |
<View> | |
<Text style={styles.logText}>{}</Text> | |
</View> | |
</ScrollView> | |
</SafeAreaView> | |
); | |
}; | |
// 设置 UI。const styles = StyleSheet.create({ | |
titleContainer: { | |
height: 60, | |
backgroundColor: '#6200ED', | |
}, | |
title: { | |
lineHeight: 60, | |
paddingLeft: 15, | |
color: '#fff', | |
fontSize: 20, | |
fontWeight: '700', | |
}, | |
inputCon: { | |
marginLeft: '5%', | |
width: '90%', | |
height: 60, | |
paddingBottom: 6, | |
borderBottomWidth: 1, | |
borderBottomColor: '#ccc', | |
}, | |
inputBox: { | |
marginTop: 15, | |
width: '100%', | |
fontSize: 14, | |
fontWeight: 'bold', | |
}, | |
buttonCon: { | |
marginLeft: '2%', | |
width: '96%', | |
flexDirection: 'row', | |
marginTop: 20, | |
height: 26, | |
justifyContent: 'space-around', | |
alignItems: 'center', | |
}, | |
eachBtn: { | |
height: 40, | |
width: '28%', | |
lineHeight: 40, | |
textAlign: 'center', | |
color: '#fff', | |
fontSize: 16, | |
backgroundColor: '#6200ED', | |
borderRadius: 5, | |
}, | |
btn2: { | |
height: 40, | |
width: '45%', | |
lineHeight: 40, | |
textAlign: 'center', | |
color: '#fff', | |
fontSize: 16, | |
backgroundColor: '#6200ED', | |
borderRadius: 5, | |
}, | |
logText: { | |
padding: 10, | |
marginTop: 10, | |
color: '#ccc', | |
fontSize: 14, | |
lineHeight: 20, | |
}, | |
}); | |
export default App; |
注:须要再登录胜利当前进行绑定
四、推送测试
1、push 测试
如何查看绑定的证书信息:
登录环信 console—> 即时推送 —> 找到对应的用户 id—> 点击查看用户绑定推送证书(如下图)
如何测试推送
登录环信 console—> 即时推送 —> 填写相干的内容 —> 发送预览 —> 确认推送
收到推送
2、离线音讯测试
登录环信 console—> 即时通讯 —> 用户治理 —> 找到对应的用户 id—> 发送 rest 音讯
至此,ReactNative 推送集成实现。