React Native 结合友盟实现分享
前言
如今,分享已经是app必不可少的一项功能,前段时间在react native中实现了社会化分享的功能,在这里记录一下实现过程,希望可以帮到有需要的人。
此文章会记录安卓和IOS 两个平台分别实现分享的步骤,
内容可能会有点长,可根据需要查看。
技术调研
在搜罗了网上大部分 react native实现分享的技术文章中,大部分文章较为老旧,实现方式也跟原生app相仿,需要自己编写大量的Object-C 以及java代码,对于纯前端开发的人来说时间成本和难度有点高,有幸,在友盟官网上发现了有针对于react native的社会化分享sdk,研究了一番,可行,开始。
准备
这里默认你已经搭建好react native的开发环境。
注册友盟账号
去友盟官网注册账号,建议使用公司邮箱。
关于开发者认证,暂时不需要企业认证可以免费试用大部分功能。
点击立即使用即可前往控制台,首先要新建你的应用。
不同平台的应用禁止使用相同的Appkey,需要分开注册,
应用名与实际应用名和包名无关,建议命名为应用名+平台(iOS/Android)
目的是拿到AppKey。
下载SDK
在弹框选择对应的分享平台,本文只针对 微信、QQ、新浪微博的精简版说明。
在各大平台注册应用
关于申请的流程官网文档有介绍,有几点需要注意:
- 各大平台申请服务所需要等待的时间不等,通常是1-5天即可通过,申请的同时可以集成sdk。
- 新浪的开发者账号申请比较麻烦,但也是最快可以拿到appkey的。
React native的集成
关于集成文档,友盟已经给出,按照官方文档的步骤集成即可,只不过集成完react native 的部分才算一小部分,大部分集成都需要按照ios和安卓平台的文档分别集成,鉴于官方文档写的云里雾里,新手可直接参考我这里的步骤。
友盟集成文档
React Native Android 集成
安卓集成比较麻烦,建议clone 官方示例demo对照设置。
- 初始化
用android studio 打开你的Android目录,
app目录中新建libs文件夹,将下载的jar放入libs中。
首先需要新建一个文件夹来存放这些.java
文件,
在你的项目如下目录中新建 umeng
文件夹:
拷贝common_android文件夹中的文件拷贝到umeng
文件夹:
然后再将对应平台的桥接文件拷入umeng
文件夹:
注意:官方示例中桥接文件的路径默认是 com.umeng.soexample.invokenative
,要修改成自己的路径。
改为自己的路径:
打开MainApplication.java文件,在new MainReactPackage()
后添加一行 new DplusReactPackage()
;
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new DplusReactPackage() ); } };
并在onCreate()中进行初始化:
@Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); RNUMConfigure.init(this, "59892f08310c9307b60023d0", "Umeng", UMConfigure.DEVICE_TYPE_PHONE, "669c30a9584623e70e8cd01b0381dcb4"); }
RNUMConfture.init接口一共五个参数,其中第一个参数为Context,第二个参数为友盟Appkey,第三个参数为channel,第四个参数为应用类型(手机或平板),第五个参数为push的secret(如果没有使用push,可以为空)。
在友盟后台注册完app后即可把 android 的appkey填入。
至此,react native 的安卓工程配置已经完成,接下来要按照Android的 U-share文档集成。
Android 部分集成
官方文档说Android集成包含快速集成和手动集成,但是关于快速集成毛都没讲,我们使用手动集成。
- 导入res
将 main 和platfroms文件夹下的res资源全部导入工程中。
res下没有相关目录的话直接拷贝文件夹过去。
添加完毕:
微信
的回调需要新建文件夹
在包名目录下创建wxapi文件夹,新建文件WXEntryActivity的activity.java
写入以下内容(com.share.umeng
要改成你的包路径):
package com.share.umeng; import com.umeng.socialize.weixin.view.WXCallbackActivity; public class WXEntryActivity extends WXCallbackActivity { }
QQ与新浪
QQ与新浪不需要添加Activity,但需要在MainActivity.java
文件中修改如下:
public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */ @Override protected String getMainComponentName() { return "share"; } // 添加以下代码 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data); } }
注意onActivityResult不可在fragment中实现,如果在fragment中调用登录或分享,需要在fragment依赖的Activity中实现。
配置Android Manifest XML
sdk中需要的Activity
- 新浪:
<activity android:name="com.umeng.socialize.media.WBShareCallBackActivity" android:configChanges="keyboardHidden|orientation" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:exported="false" > </activity> <activity android:name="com.sina.weibo.sdk.web.WeiboSdkWebActivity" android:configChanges="keyboardHidden|orientation" android:exported="false" android:windowSoftInputMode="adjustResize" > </activity> <activity android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" android:launchMode="singleTask" android:name="com.sina.weibo.sdk.share.WbShareTransActivity"> <intent-filter> <action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
- 微信:
<activity android:name=".wxapi.WXEntryActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="true" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
权限添加
在AndroidManifest.xml
中添加如下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
如果需要使用QQ纯图分享或避免其它平台纯图分享的时候图片不被压缩,可以增加以下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Android6.0权限适配
查看你的build.gradle文件,如果 targetSdkVersion小于或等于22,可以忽略这一步,如果大于或等于23,需要做权限的动态申请:
if(Build.VERSION.SDK_INT>=23){ String[] mPermissionList = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.CALL_PHONE,Manifest.permission.READ_LOGS,Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.SET_DEBUG_APP,Manifest.permission.SYSTEM_ALERT_WINDOW,Manifest.permission.GET_ACCOUNTS,Manifest.permission.WRITE_APN_SETTINGS}; ActivityCompat.requestPermissions(this,mPermissionList,123); }
其中123是requestcode,可以根据这个code判断,用户是否同意了授权。如果没有同意,可以根据回调进行相应处理:
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { }
初始化设置
由于之前已经在在onCreate()方法中替换友盟的appkey,还需要替换各大平台的Appkey
和 App Secret
打开MainApplication.java
文件,在onCreate()
方法后添加各平台的Appkey
:
{ //豆瓣RENREN平台目前只能在服务器端配置 PlatformConfig.setWeixin("wxdc1e388c3822c80b", "3baf1193c85774b3fd9d18447d76cab0"); PlatformConfig.setSinaWeibo("3921700954", "04b48b094faeb16683c32669824ebdad", "http://sns.whalecloud.com"); PlatformConfig.setQQZone("100424468", "c7394704798a158208a74ab60104f0ba"); }
签名配置
将文件夹中的签名文件放入到工程中,一般是debug.keystore
打开build.gradle
然后增加签名文件的密码:
signingConfigs { debug { storeFile file('debug.keystore') storePassword "android" keyAlias "androiddebugkey" keyPassword "android" } }
然后在buildTypes中将这个signingConfigs配置进去,如下图所示:
至此,android 部分的 集成结束,更多高级功能请去参考官方文档。
React Native IOS 集成
ios集成文档
ios的集成也非分为手动集成和自动集成,自动集成使用Cocoapods
。
通过 Cocoapods
方式集成请参考文档 Cocoapods集成分享SDK。
由于我之前是通过手动集成的,所以本文讲解手动集成步骤,
但是对于ios来说更推荐使用 Cocoapods。
- 进入ios > 项目目录,新建两个文件夹
UMReactBridge
和UMComponent
。 - 打开之前下载的文件,把
share
目录中的最后所有文件,拷入UMComponent
中的新建文件夹UMShare
中。
这里有一个问题。通过选择react native 下载的sdk包中ios目录中缺少common部分的文件,所以还需要去sdk下载中心去下载ios的sdk。
下载之后,将ios目录下的common
中的framework
,拷入UMComponent
中。
同时有两个log相关的文件,一并导入,便于开发时可以在xcode中查看详细的日志。
- 进入下载文件的
ReactNative
目录,找到common
`share目录中对应的ios平台中的桥接
.h`.m
文件,全部拷贝至我们项目刚刚新建的UMReactBridge
文件夹。
- xcode中打开工程目录,右键黄色项目名
Add Files to "xxx"
,options
中选中Create groups Copy items if needed
找到我们新建的UMReactBridge
和UMComponent
,add添加。
- 在
Other Linker Flags
加入-ObjC
,注意不要写为-ObjC
,注:-ObjC
属于链接库必备参数,如果不加此项,会导致库文件无法被正确链接,SDK无法正常运行。
加入依赖系统库
加入以下系统库:
libsqlite3.tbd CoreGraphics.framework
日志依赖库:
Foundation.framework
[日志详细配置
](https://developer.umeng.com/d...
第三方平台库添加(精简版):
新浪微博(精简版)
Photos.framework
第三方平台配置
配置SSO白名单
如果你的应用使用了如SSO授权登录或跳转到第三方分享功能,在iOS9/10下就需要增加一个可跳转的白名单,即LSApplicationQueriesSchemes
,否则将在SDK判断是否跳转时用到的canOpenURL
时返回NO,进而只进行webview授权或授权/分享失败。在项目中的info.plist
中加入应用白名单,右键info.plist
选择source code
打开,请根据选择的平台对以下配置进行裁剪:
<key>LSApplicationQueriesSchemes</key> <array> <!-- 微信 URL Scheme 白名单--> <string>wechat</string> <string>weixin</string> <!-- 新浪微博 URL Scheme 白名单--> <string>sinaweibohd</string> <string>sinaweibo</string> <string>sinaweibosso</string> <string>weibosdk</string> <string>weibosdk2.5</string> <!-- QQ、Qzone URL Scheme 白名单--> <string>mqqapi</string> <string>mqq</string> <string>mqqOpensdkSSoLogin</string> <string>mqqconnect</string> <string>mqqopensdkdataline</string> <string>mqqopensdkgrouptribeshare</string> <string>mqqopensdkfriend</string> <string>mqqopensdkapi</string> <string>mqqopensdkapiV2</string> <string>mqqopensdkapiV3</string> <string>mqqopensdkapiV4</string> <string>mqzoneopensdk</string> <string>wtloginmqq</string> <string>wtloginmqq2</string> <string>mqqwpa</string> <string>mqzone</string> <string>mqzonev2</string> <string>mqzoneshare</string> <string>wtloginqzone</string> <string>mqzonewx</string> <string>mqzoneopensdkapiV2</string> <string>mqzoneopensdkapi19</string> <string>mqzoneopensdkapi</string> <string>mqqbrowser</string> <string>mttbrowser</string> <string>tim</string> <string>timapi</string> <string>timopensdkfriend</string> <string>timwpa</string> <string>timgamebindinggroup</string> <string>timapiwallet</string> <string>timOpensdkSSoLogin</string> <string>wtlogintim</string> <string>timopensdkgrouptribeshare</string> <string>timopensdkapiV4</string> <string>timgamebindinggroup</string> <string>timopensdkdataline</string> <string>wtlogintimV1</string> <string>timapiV1</string> <!-- 支付宝 URL Scheme 白名单--> <string>alipay</string> <string>alipayshare</string> <!-- 钉钉 URL Scheme 白名单--> <string>dingtalk</string> <string>dingtalk-open</string> <!--Linkedin URL Scheme 白名单--> <string>linkedin</string> <string>linkedin-sdk2</string> <string>linkedin-sdk</string> <!-- 点点虫 URL Scheme 白名单--> <string>laiwangsso</string> <!-- 易信 URL Scheme 白名单--> <string>yixin</string> <string>yixinopenapi</string> <!-- instagram URL Scheme 白名单--> <string>instagram</string> <!-- whatsapp URL Scheme 白名单--> <string>whatsapp</string> <!-- line URL Scheme 白名单--> <string>line</string> <!-- Facebook URL Scheme 白名单--> <string>fbapi</string> <string>fb-messenger-api</string> <string>fb-messenger-share-api</string> <string>fbauth2</string> <string>fbshareextension</string> <!-- Kakao URL Scheme 白名单--> <!-- 注:以下第一个参数需替换为自己的kakao appkey--> <!-- 格式为 kakao + "kakao appkey"--> <string>kakaofa63a0b2356e923f3edd6512d531f546</string> <string>kakaokompassauth</string> <string>storykompassauth</string> <string>kakaolink</string> <string>kakaotalk-4.5.0</string> <string>kakaostory-2.9.0</string> <!-- pinterest URL Scheme 白名单--> <string>pinterestsdk.v1</string> <!-- Tumblr URL Scheme 白名单--> <string>tumblr</string> <!-- 印象笔记 --> <string>evernote</string> <string>en</string> <string>enx</string> <string>evernotecid</string> <string>evernotemsg</string> <!-- 有道云笔记--> <string>youdaonote</string> <string>ynotedictfav</string> <string>com.youdao.note.todayViewNote</string> <string>ynotesharesdk</string> <!-- Google+--> <string>gplus</string> <!-- Pocket--> <string>pocket</string> <string>readitlater</string> <string>pocket-oauth-v1</string> <string>fb131450656879143</string> <string>en-readitlater-5776</string> <string>com.ideashower.ReadItLaterPro3</string> <string>com.ideashower.ReadItLaterPro</string> <string>com.ideashower.ReadItLaterProAlpha</string> <string>com.ideashower.ReadItLaterProEnterprise</string> <!-- VKontakte--> <string>vk</string> <string>vk-share</string> <string>vkauthorize</string> <!-- Twitter--> <string>twitter</string> <string>twitterauth</string> </array>
配置URL Scheme
URL Scheme是通过系统找到并跳转对应app的一类设置,通过向项目中的info.plist文件中加入URL types可使用第三方平台所注册的appkey信息向系统注册你的app,当跳转到第三方应用授权或分享后,可直接跳转回你的app。
部分规则:
- 微信:微信appKey wxdc1e388c3822c80b
- QQ/Qzone: 需要添加两项URL Scheme:
1、"tencent"+腾讯QQ互联应用appID
2、“QQ”+腾讯QQ互联应用appID转换成十六进制(不足8位前面补0)
如appID:100424468 1、tencent100424468
2、QQ05fc5b14
- 新浪微博: “wb”+新浪appKey wb3921700954
权限配置
在 info.plist 文件中配置相册权限:
<key>NSPhotoLibraryUsageDescription</key> <string>App需要您的同意,才能访问相册</string>
初始化设置
AppDelegate.m
设置友盟Appkey
以及各个平台的Appkey
和secret
。
#import <UMShare/UMShare.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // UMConfigure 通用设置,请参考SDKs集成做统一初始化。 // 以下仅列出U-Share初始化部分 // U-Share 平台设置 [self configUSharePlatforms]; [self confitUShareSettings]; // Custom code return YES; } - (void)confitUShareSettings { /* * 打开图片水印 */ //[UMSocialGlobal shareInstance].isUsingWaterMark = YES; /* * 关闭强制验证https,可允许http图片分享,但需要在info.plist设置安全域名 <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> */ //[UMSocialGlobal shareInstance].isUsingHttpsWhenShareContent = NO; } - (void)configUSharePlatforms { /* 设置微信的appKey和appSecret */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_WechatSession appKey:@"wxdc1e388c3822c80b" appSecret:@"3baf1193c85774b3fd9d18447d76cab0" redirectURL:@"http://mobile.umeng.com/social"]; /* * 移除相应平台的分享,如微信收藏 */ //[[UMSocialManager defaultManager] removePlatformProviderWithPlatformTypes:@[@(UMSocialPlatformType_WechatFavorite)]]; /* 设置分享到QQ互联的appID * U-Share SDK为了兼容大部分平台命名,统一用appKey和appSecret进行参数设置,而QQ平台仅需将appID作为U-Share的appKey参数传进即可。 */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_QQ appKey:@"1105821097"/*设置QQ平台的appID*/ appSecret:nil redirectURL:@"http://mobile.umeng.com/social"]; /* 设置新浪的appKey和appSecret */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Sina appKey:@"3921700954" appSecret:@"04b48b094faeb16683c32669824ebdad" redirectURL:@"https://sns.whalecloud.com/sina2/callback"]; /* 钉钉的appKey */ [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_DingDing appKey:@"dingoalmlnohc0wggfedpk" appSecret:nil redirectURL:nil]; /* 支付宝的appKey */ [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_AlipaySession appKey:@"2015111700822536" appSecret:nil redirectURL:@"http://mobile.umeng.com/social"]; /* 设置易信的appKey */ [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_YixinSession appKey:@"yx35664bdff4db42c2b7be1e29390c1a06" appSecret:nil redirectURL:@"http://mobile.umeng.com/social"]; /* 设置点点虫(原来往)的appKey和appSecret */ [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_LaiWangSession appKey:@"8112117817424282305" appSecret:@"9996ed5039e641658de7b83345fee6c9" redirectURL:@"http://mobile.umeng.com/social"]; /* 设置领英的appKey和appSecret */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Linkedin appKey:@"81t5eiem37d2sc" appSecret:@"7dgUXPLH8kA8WHMV" redirectURL:@"https://api.linkedin.com/v1/people"]; /* 设置Twitter的appKey和appSecret */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Twitter appKey:@"fB5tvRpna1CKK97xZUslbxiet" appSecret:@"YcbSvseLIwZ4hZg9YmgJPP5uWzd4zr6BpBKGZhf07zzh3oj62K" redirectURL:nil]; /* 设置Facebook的appKey和UrlString */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Facebook appKey:@"506027402887373" appSecret:nil redirectURL:@"http://www.umeng.com/social"]; /* 设置Pinterest的appKey */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Pinterest appKey:@"4864546872699668063" appSecret:nil redirectURL:nil]; /* dropbox的appKey */ [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_DropBox appKey:@"k4pn9gdwygpy4av" appSecret:@"td28zkbyb9p49xu" redirectURL:@"https://mobile.umeng.com/social"]; /* vk的appkey */ [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_VKontakte appKey:@"5786123" appSecret:nil redirectURL:nil]; } - (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; }
对应的方法在UMShareModule.m
中查看。
调试模式与日志
之前已经加过日志库的资源文件了。
开启日志:
[UMConfigure setLogEnabled:YES];
使用分享
至此,ios和adnroid平台的集成和工程配置基本完成,最后一步就是使用原生代码导出的分享模块供js调用。
进入下载目录的ReactNative
找到common下的js中的ShareUtil.js
,拷贝到我们RN目录下,放入libs
文件夹。
android与ios平台回调中的code值不一致,ios成功时code:200,android成功时code:0。
首先需要引入ShareUtil文件:
import ShareUtile from './ShareUtil'
授权
授权代码可以直接使用ShareUtile.auth(platform,callback)
,其中platform
为平台id,callback
为回调内容。
[详细对应关系
](https://developer.umeng.com/d...
官方文档给出了三种分享回调,在这里使用 ShareUtile.shareboard
调起分享面板实现分享。
ShareUtile.shareboard(text,img,url,title,list,(code,message) =>{ this.setState({result:message}); });
- text 为分享内容
- img 为图片地址,可以为链接,本地地址以及res图片(如果使用res,请使用如下写法:res/icon.png)
- url 为分享链接,可以为空
- title 为分享链接的标题
- list 为分享平台数组,如:var list = [0,1,2]
- callback中code为错误码,当为0时,标记成功。-
- message为错误信息