最近在写阿里云推送相关的东西,看了阿里云移动推送+ReactNative最佳实践之后,跟着写越写越不对劲,明显省略了亿点点细节。我发现大多数文档就算跟着一步步去做,还是会有报错,都是省略了细节,于是重复的坑越踩越多,特此记录一下此次踩坑记录。
在demo中copy一下,啊,不是,借鉴一下,是每个程序员都具备的良好品质👍。查看使用Demo快速体验移动推送,将demo下载下来, 打开react-native的demo选择文件目录:mpush_reactnative_android_demo/AwesomeProject.
安装依赖,执行yarn android命令,于是你就会得到这样的错误提示:
将文件android/app/build.gradle里的debug内容换一下
signingConfigs {
debug {
storeFile file('D:\桌面\key\Test.jks')
storePassword "test1234"
keyAlias "test"
keyPassword "test1234"
}
}
// 替换成
signingConfigs {
debug {
storeFile file('debug.keystore') // 主要是这句
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
重新yarn android一下,怀着期待的心情发现它又报错啦:
看提示就知道local.properties未设置,将local.properties放到android文件夹下,里面是本地sdk的位置
再次运行yarn android
程序终于运行成功啦🎉,然后按照链接文档的那样,找到android/app/src/main/AndroidManifest.xml,将appkey和appsecret设置成自己创建好的emas项目
<!-- 请填写你自己的- appKey -->
<meta-data
android:name="com.alibaba.app.appkey"
android:value="********" />
<!-- 请填写你自己的appSecret -->
<meta-data
android:name="com.alibaba.app.appsecret"
android:value="********" />
重新yarn android一下,在emas控制台上新建消息通知,满心期待的看着app的界面........................................................................................好吧,等了很久没什么反应,应该是哪儿出问题了。 控制台输入adb shell input keyevent 82, 选择debug,看到react-native-debugger控制台有个这样的错误:
研究了半天,看了github提交的issue也没有这个问题,心里感觉这个方向应该没必要研究下去了。于是开始读源码。找到android/app/src/main/java/com/MainApplication.java里的这一段方法。
/**
* 注册通知
*/
public void initCloudChannel() {
File is_privacy = new File(ContextCompat.getDataDir(this).getAbsolutePath(), ContVar.P_FILE);
if (!is_privacy.exists()) return;
if (pushInit) return;
pushInit = true;
if (BuildConfig.DEBUG) {
//仅适用于Debug包,正式包不需要此行
PushServiceFactory.getCloudPushService().setLogLevel(CloudPushService.LOG_DEBUG);
}
PushServiceFactory.getCloudPushService().register(this.getApplicationContext(), new CommonCallback() {
@Override
public void onSuccess(String s) {
pushInit = true;
WritableMap params = Arguments.createMap();
params.putBoolean("success", true);
PushModule.sendEvent("onInit", params);
initCS();
}
@Override
public void onFailed(String s, String s1) {
pushInit = false;
WritableMap params = Arguments.createMap();
params.putBoolean("success", false);
params.putString("errorMsg", "errorCode:" + s + ". errorMsg:" + s1);
PushModule.sendEvent("onInit", params);
}
});
}
反复🤔了一下,在主目录的index.android.js文件找到这段
componentDidMount() {
DeviceEventEmitter.addListener('onMessage', this.onMessage);
DeviceEventEmitter.addListener('onNotification', this.onNotification);
DeviceEventEmitter.addListener('onNotificationOpened', this.onNotificationOpened);
DeviceEventEmitter.addListener('onNotificationRemoved', this.onNotificationRemoved);
DeviceEventEmitter.addListener('onSysNoticeOpened', this.onSysNoticeOpened);
}
因为项目是react-native,链接文档下面这个是原生java输出,react里是看不到是否是集成成功的。
动动脑筋学委想了一下,我把第二段代码改成了这样:
componentDidMount() {
DeviceEventEmitter.addListener('onInit', (params)=> {
console.log('----------init', params);
});
DeviceEventEmitter.addListener('onMessage', this.onMessage);
DeviceEventEmitter.addListener('onNotification', this.onNotification);
DeviceEventEmitter.addListener('onNotificationOpened', this.onNotificationOpened);
DeviceEventEmitter.addListener('onNotificationRemoved', this.onNotificationRemoved);
DeviceEventEmitter.addListener('onSysNoticeOpened', this.onSysNoticeOpened);
}
思路是先判断是否初始化成功再考虑是不是接收方法的问题,因为第一段java有PushModule.sendEvent("onInit", params), 这个方法可以在第二段react里用我加的这段代码监听到,这里不懂可以去看react和原生通信相关知识, 然后重新yarn android一下,结果不出所料,没有任何打印信息。继续修改第一段java代码
/**
* 注册通知
*/
public void initCloudChannel() {
File is_privacy = new File(ContextCompat.getDataDir(this).getAbsolutePath(), ContVar.P_FILE);
// if (!is_privacy.exists()) return;
if (pushInit) return;
pushInit = true;
if (BuildConfig.DEBUG) {
//仅适用于Debug包,正式包不需要此行
PushServiceFactory.getCloudPushService().setLogLevel(CloudPushService.LOG_DEBUG);
}
PushServiceFactory.getCloudPushService().register(this.getApplicationContext(), new CommonCallback() {
@Override
public void onSuccess(String s) {
pushInit = true;
WritableMap params = Arguments.createMap();
params.putBoolean("success", true);
PushModule.sendEvent("onInit", params);
initCS();
}
@Override
public void onFailed(String s, String s1) {
pushInit = false;
WritableMap params = Arguments.createMap();
params.putBoolean("success", false);
params.putString("errorMsg", "errorCode:" + s + ". errorMsg:" + s1);
PushModule.sendEvent("onInit", params);
}
});
}
将第一个return注释掉,可能是没有执行到sendEvent这一步。继续yarn android. 出乎意料的没有任何输出,🤯,这么看来,控制台报错有可能就是onInit监听有问题了。再再思考了一下,将第一段代码改成了这样:
/**
* 注册通知
*/
public void initCloudChannel() {
File is_privacy = new File(ContextCompat.getDataDir(this).getAbsolutePath(), ContVar.P_FILE);
// if (!is_privacy.exists()) return;
if (pushInit) return;
pushInit = true;
if (BuildConfig.DEBUG) {
//仅适用于Debug包,正式包不需要此行
PushServiceFactory.getCloudPushService().setLogLevel(CloudPushService.LOG_DEBUG);
}
PushServiceFactory.getCloudPushService().register(this.getApplicationContext(), new CommonCallback() {
@Override
public void onSuccess(String s) {
pushInit = true;
WritableMap params = Arguments.createMap();
params.putBoolean("success", true);
Toast.makeText(MainApplication.this, "success", Toast.LENGTH_SHORT).show();
PushModule.sendEvent("onInit", params);
initCS();
}
@Override
public void onFailed(String s, String s1) {
pushInit = false;
WritableMap params = Arguments.createMap();
params.putBoolean("success", false);
params.putString("errorMsg", "errorCode:" + s + ". errorMsg:" + s1);
Toast.makeText(MainApplication.this, "fail", Toast.LENGTH_SHORT).show();
PushModule.sendEvent("onInit", params);
}
});
}
Toast是原生android的弹窗,自创的react-native原生java的"debug",记得要在上方导入,再次yarn android
import android.widget.Toast
终于输出了。。。根据使用Demo快速体验移动推送,在控制台新建通知信息,然后静静等待片刻,即可收到控制台设置好的消息,这里需要注意的是demo的GET DEVICE_ID点击后有deviceID的大概率能正常收到消息,但是Mac的虚拟器有时候deviceId为null.是收不到消息的,这又是另一个大坑,emm,其次控制台设置的PackageName需要和项目android/app目录下的build.gradle里的applicationId设置的一致。
费尽心思终于,这个demo跑起来了。。。emm...具体项目里如何重写,虽然我已经集成进项目,但是文章只能有时间再写了。
最后的最后,老实说,实现这些功能是一件很有趣的事儿,但是有时候因为工作,或者生活中各种压力,会对自己热爱的事情有厌倦,这时候最好的做法就是停下脚步想一想自己想要的究竟是什么,放慢之后会发现,喜欢的还是会喜欢,热爱的还是会热爱,有遗憾就去争取,尽力之后就不要后悔,做自己很重要。实话实说代码很有趣,工作很无趣,两者并不是互斥的,希望我们都能因为热爱去做一些事。
2023-06-15 更新 家人们,谁懂啊,6月12号还有react-native阿里云推送最佳实践的官方文档,现在官网已经删除了,只能移步至客户端插件,使用官方推荐的aliyun-react-native-push,好像是这个,但是文档...还是不全,建议有需求的直接用插件好了。。。。踩坑文档等我最近有时间再更吧,大概吧,哈哈哈哈...