最近公司在做一个APP项目,还是考虑到成本问题,So,技术上又一次选择了RN,考虑到项目功能上有第三方分享、第三方登陆、消息推送等高大上的功能,由于之前做过一次分享,用的是网友封装的友盟的分享,于是去官网看了下文档,惊奇的发现友盟已经专门集成了用于RN的SDK,并且分享、授权登陆、推送都有,不禁窃喜。就这样愉快的选择友盟了!
接下来就是去下载集成SDK了。
一、首先是集成分享和登陆
分享和登陆的具体集成在这篇文章里面。。
1、下载相关SDK
1.1、下载用于友盟集成的RN SDK
1.2、下载UMCommon.framework
注: 这个记得一定要下载iOS选项下面的SDK,后面集成的时候会用到,之前按教程集成的时候没有找到这个文件,就去友盟github的demo里面复制了这个文件,结果在集成的时候由于不是最新的版本,导致在Xcode10上面一直闪退,崩溃提示是
[
,后面的朋友如果碰到iOS升级之后项目编译异常的也可以考虑升级SDK试试。valueForUndefinedKey:]: this class is not key value coding-compliant for the...
2、使用Xcode进行集成iOS系统
2.1、首先进入项目的ios目录,进入对应的工程名目录,新建两个文件夹:UMReactBridge
和UMComponents
2.2、将1.2
步骤下载的文件iOS目录下的common中的framework,拷入UMComponents
中。
将1.1
步骤下载的文件iOS目录下中share目录中的最后所有文件,拷入UMComponents
中的新建文件夹UMShare
中,在将push文件里最后的所有文件拷入UMComponents
文件夹中。看下图:
集成之后在xcode中的目录结构是这样的:
2.3、进入1.1
步骤下载文件的ReactNative目录,找到common、 share、push
目录中对应的common_ios
平台中的桥接.h 和 .m
文件,全部拷贝至我们项目刚刚新建的UMReactBridge
文件夹中,看下图:
集成之后xcode中的目录结构为:
2.4、在xcode
中打开工程目录,右键黄色项目名Add Files to "xxx"
,options
中选中Create groups 、 Copy items if needed
找到我们新建的UMReactBridge
和UMComponents
,最后点击add
添加。看下图
2.5、##
Linked Frameworks and Libraries
加入系统依赖库:可参照 链接
libsqlite3.tbd
CoreGraphics.framework
SystemConfiguration.framework
CoreTelephony.framework
libc++.tbd
libz.tbd
2.6 配置SSO白名单,右键info.plist选择source code打开(plist具体设置在Build Setting -> Packaging -> Info.plist File可获取plist路径)请根据选择的平台对以下配置进行裁剪:
LSApplicationQueriesSchemes
wechat
weixin
sinaweibohd
sinaweibo
sinaweibosso
weibosdk
weibosdk2.5
mqqapi
mqq
mqqOpensdkSSoLogin
mqqconnect
mqqopensdkdataline
mqqopensdkgrouptribeshare
mqqopensdkfriend
mqqopensdkapi
mqqopensdkapiV2
mqqopensdkapiV3
mqqopensdkapiV4
mqzoneopensdk
wtloginmqq
wtloginmqq2
mqqwpa
mqzone
mqzonev2
mqzoneshare
wtloginqzone
mqzonewx
mqzoneopensdkapiV2
mqzoneopensdkapi19
mqzoneopensdkapi
mqqbrowser
mttbrowser
tim
timapi
timopensdkfriend
timwpa
timgamebindinggroup
timapiwallet
timOpensdkSSoLogin
wtlogintim
timopensdkgrouptribeshare
timopensdkapiV4
timgamebindinggroup
timopensdkdataline
wtlogintimV1
timapiV1
alipay
alipayshare
dingtalk
dingtalk-open
linkedin
linkedin-sdk2
linkedin-sdk
laiwangsso
yixin
yixinopenapi
instagram
whatsapp
line
fbapi
fb-messenger-api
fbauth2
fbshareextension
kakaofa63a0b2356e923f3edd6512d531f546
kakaokompassauth
storykompassauth
kakaolink
kakaotalk-4.5.0
kakaostory-2.9.0
pinterestsdk.v1
tumblr
evernote
en
enx
evernotecid
evernotemsg
youdaonote
ynotedictfav
com.youdao.note.todayViewNote
ynotesharesdk
gplus
pocket
readitlater
pocket-oauth-v1
fb131450656879143
en-readitlater-5776
com.ideashower.ReadItLaterPro3
com.ideashower.ReadItLaterPro
com.ideashower.ReadItLaterProAlpha
com.ideashower.ReadItLaterProEnterprise
vk
vk-share
vkauthorize
twitter
twitterauth
2.7、配置URL Scheme
URL Scheme是通过系统找到并跳转对应app的一类设置,通过向项目中的info.plist文件中加入URL types可使用第三方平台所注册的appkey信息向系统注册你的app,当跳转到第三方应用授权或分享后,可直接跳转回你的app。
2.8 初始化AppDelegate.m
设置友盟appkey
和appSecret(如果有推送功能的话需要加)
以及各个平台的appkey
和secret
.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
/* 打开调试日志 */
[[UMSocialManager defaultManager] openLog:YES];
/* 设置友盟appkey */
[RNUMConfigure initWithAppkey:@"5bd*********0db" channel:@"App Store"];
/*
* 关闭强制验证https,可允许http图片分享,但需要在info.plist设置安全域名
*/
[UMSocialGlobal shareInstance].isUsingHttpsWhenShareContent = NO;
/*
设置微信的appKey和appSecret
[微信平台从U-Share 4/5升级说明]http://dev.umeng.com/social/ios/%E8%BF%9B%E9%98%B6%E6%96%87%E6%A1%A3#1_1
*/
[[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_WechatSession appKey:@"wxd******" appSecret:@"e7b246a7bdcfe75100e77eb9e999bf37" redirectURL:nil];
/* 设置分享到QQ互联的appID
* U-Share SDK为了兼容大部分平台命名,统一用appKey和appSecret进行参数设置,而QQ平台仅需将appID作为U-Share的appKey参数传进即可。
100424468.no permission of union id
[QQ/QZone平台集成说明]http://dev.umeng.com/social/ios/%E8%BF%9B%E9%98%B6%E6%96%87%E6%A1%A3#1_3
*/
[[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_QQ appKey:@"*****"/*设置QQ平台的appID*/ appSecret:@"*******" redirectURL:@"http://mobile.umeng.com/social"];
// Push's basic setting 推送设置!!
UMessageRegisterEntity * entity = [[UMessageRegisterEntity alloc] init];
//type是对推送的几个参数的选择,可以选择一个或者多个。默认是三个全部打开,即:声音,弹窗,角标
entity.types = UMessageAuthorizationOptionBadge|UMessageAuthorizationOptionAlert|UMessageAuthorizationOptionSound;
[UNUserNotificationCenter currentNotificationCenter].delegate=self;
[UMessage registerForRemoteNotificationsWithLaunchOptions:launchOptions Entity:nil completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"deviceToken+++++++++");
} else {
}
}];
return YES;
}
//从支付、分享、第三方登陆等跳转会本APP时的回调,必须实现,否则收不到分享成功时的回调!!!!
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url];
if (!result) {
// 其他如支付等SDK的回调
}
return result;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url];
if (!result) {
// 其他如支付等SDK的回调
}
return result;
}
2.9、提供给RN调用的方法在UMShareModule.m
中查看.
2.10、进入下载目录的ReactNative
找到common
下的js
中的ShareUtil.js(包含分享和登陆的方法)
,拷贝到我们RN
目录下,即可在RN中导入使用分享的方法啦。
2.11、在RN中调用
import ShareUtil from './ShareUtil';
//分享
ShareUtile.shareboard(text,img,url,title,list,(code,message) =>{
if (code == 200){
this.setState({result:message});
}
});
text 为分享内容
img 为图片地址,可以为链接,本地地址以及res图片(如果使用res,请使用如下写法:res/icon.png)
url 为分享链接,可以为空
title 为分享链接的标题
list 为分享平台数组,如:var list = [0,1,2]
callback中code为错误码,当为0时,标记成功。message为错误信息
//第三方登陆
ShareUtile.auth(0,(code,result,message) =>{
if (code == 200){// iOS平台
//登陆成功,返回第三方账号的信息,
//比如openID、nickName、headPath等信息,这时就可以传给自己的后台小伙伴入库啦!!!
}
});
注:android与ios平台成功回调中的code值不一致,ios成功时code===200,android成功时code===0,文档写的是0,当时还被小坑啦一把。
至此iOS端端分享和登陆已经完毕,至于安卓端集成由于同事负责,在此先不记录,后面会自己集成一遍。
二、集成远程推送功能
SDK端集成已经在分享和登陆步骤中已经集成,都有截图参考,下面直接进入功能实现步骤吧:
开始前的几点说明:
- 其实对于推送功能,本质还是集成原生系统端推送功能,大部分代码逻辑还是在原生端实现,比如 注册推送权限、获取DeviceToken、设置推送提醒的类型,设置收到推送时的回调等。
-
比较烦的是对推送证书的配置,注: 如果做推送的话必须是付费的开发者账号生成证书才可以,否则在Xcode里设置开启推送权限的时候会找不到该菜单项。看下图
- 具体的集成步骤以及证书生成参考友盟官网教程:
证书配置
集成步骤 - 在推送的时候,可以通过设置不通的tag值对用户分组进行推送,也可以通过用户id进行精准推送,RN也提供来对应的方法 PushUtil.addTag(tag,(code,remain) =>{ })和PushUtil.addAlias(alias,type,(code) =>{ }),具体参考文档。
- 还有待优化的功能: 关于iOS如何在接收到推送后打开指定页面, 官方给的地址以及找不到了, 我自己的实现方法是在原生端收到推送消息后参考RN文档中原生端调用RN的方法使用通知来实现,期待朋友们有好的方法,期待赐教。
推送主要代码:
AppDelegate.h
页面
#import
#import
//!!!!一定要实现这个代理方法 :UNUserNotificationCenterDelegate
@interface AppDelegate : UIResponder
@property (nonatomic, strong) UIWindow *window;
@end
AppDelegate.m
页面
#import
#import
#import "RNUMConfigure.h"
#import
#import "YouMengNotice.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Push's basic setting
UMessageRegisterEntity * entity = [[UMessageRegisterEntity alloc] init];
//type是对推送的几个参数的选择,可以选择一个或者多个。默认是三个全部打开,即:声音,弹窗,角标
entity.types = UMessageAuthorizationOptionBadge|UMessageAuthorizationOptionAlert|UMessageAuthorizationOptionSound;
// 需要实现代理,用于下面代理方法的实现。
[UNUserNotificationCenter currentNotificationCenter].delegate=self;
[UMessage registerForRemoteNotificationsWithLaunchOptions:launchOptions Entity:nil completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"deviceToken+++++++++");
} else {
}
}];
}
#pragma mark - Push
//在这个方法打印出 deviceToken, 便于在友盟后台添加测试设备进行测试
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
[UMessage registerDeviceToken:deviceToken];
NSLog(@"deviceToken+++++++++%@",[[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""]);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
}
// 次方法在iOS10以后,已经不再支持
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
//关闭友盟自带的弹出框
[UMessage setAutoAlert:NO];
[UMessage didReceiveRemoteNotification:userInfo];
[YouMengNotice OCsendMessageToReactNative:userInfo];
}
//iOS10新增:处理前台收到通知的代理方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
//应用处于前台时的远程推送接受
//关闭友盟自带的弹出框
[UMessage setAutoAlert:NO];
//必须加这句代码
[UMessage didReceiveRemoteNotification:userInfo];
// 在这里自己实现来在接收到远程推送时,主动调用RN端的,把通知内容传给RN,这样就可以控制RN收到推送时跳转到指定页面来。
[YouMengNotice OCsendMessageToReactNative:userInfo];
}else{
//应用处于前台时的本地推送接受
}
completionHandler(UNNotificationPresentationOptionSound|UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionAlert);
}
//iOS10新增:处理后台点击通知的代理方法
//这个方法是在APP接收到通知之后,点击通知栏跳转到APP时才调用的, 注意::!!如果直接点击APP是没用的
//知识点!! iOS的通知 分APP在前台时显示和点击通知栏跳转到APP显示, 如果直接点击APP的话是不会走上面的两个回调方法的,之前理解错误
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler{
NSDictionary * userInfo = response.notification.request.content.userInfo;
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
//应用处于后台时的远程推送接受
//必须加这句代码
[UMessage didReceiveRemoteNotification:userInfo];
[YouMengNotice performSelector:@selector(OCsendMessageToReactNative:) withObject:userInfo afterDelay:15];
// [YouMengNotice OCsendMessageToReactNative:userInfo];
}else{
//应用处于后台时的本地推送接受
}
}
RN端实现:
import PushUtil from "../Tools/PushUtil.js";
import { NativeModules, NativeEventEmitter } from "react-native";
const { YouMengNotice } = NativeModules;
const myNativeEvt = new NativeEventEmitter(YouMengNotice); //创建自定义事件接口
componentDidMount() {
//收到原生端发来的推送消息,这里处理页面跳转逻辑
myNativeEvt.addListener("OCSendToRN", (e) => {
console.log("原生端的消息");
msg(JSON.stringify(e));
});
//添加tag,即分组,在推送时可以对不同分组用户进行推送
// PushUtil.addTag("ccj",(code, res) =>{
// Alert.alert("提示", ""+code+JSON.stringify(res));
// })
PushUtil.addTag("个人用户", (code, res) => {
// Alert.alert("提示", ""+code+JSON.stringify(res));
});
}
原生与RN交互参考:
https://www.jianshu.com/p/91bc0dea6821(在iOS12测试可以)
https://www.jianshu.com/p/99c32dc5cf29
https://blog.csdn.net/teagreen_red/article/details/79392477
参考:
https://www.jianshu.com/p/d54b259f7cb0
https://www.jianshu.com/p/32edded653ab
https://www.cnblogs.com/czq1989/p/5098871.html
推送注意事项:https://www.jianshu.com/p/e5a45a7e80a7