文章涉及的demo在Github LQThirdParty, 欢迎Star | Fork
一. 注册账号
首先到Mob的开放平台注册成为开发者, 并新建应用, 获得相应的 APPID 和 APPSecret .然后到相应的第三方平台注册成为开发者, 新建应用, 获取对应的AppKey.
二. 集成及配置
2.1 集成
2.1.1 CocoaPods集成
CocoaPods集成好处不多说, 根据官方文档在项目 Podfile 文件 添加相应的引入即可:
# UI模块(非必须,需要用到ShareSDK提供的分享菜单栏和分享编辑页面需要以下1行)
pod 'mob_sharesdk/ShareSDKUI'
# 平台SDK模块(对照一下平台,需要的加上。如果只需要QQ、微信、新浪微博,只需要以下3行)
pod 'mob_sharesdk/ShareSDKPlatforms/QQ'
pod 'mob_sharesdk/ShareSDKPlatforms/SinaWeibo'
pod 'mob_sharesdk/ShareSDKPlatforms/WeChat' //(微信sdk不带支付的命令)
# pod 'mob_sharesdk/ShareSDKPlatforms/WeChatFull’ //(微信sdk带支付的命令,和上面不带支付的不能共存,只能选择一个)
然后执行 pod install ,等待下载完成即可;
2.1.2 手动集成
官方文档
首先下载iOS SDK, 在下载页选择需要的第三方平台SDK, 点击下载即可;
将下载的文件解压出的两个文件夹, 直接拖进项目目录, 具体各个文件夹的内容可参考官方文档内的说明进行删减.
注意: 如果是使用Xcode 9+ 新建的项目, 在将文件拖入项目的时候, 不会自动把库文件加载到库资源里,以及不会自动添加路径. 可以先将添加的文件删除引用, 不是删除文件移到废纸篓, Delegate -> Remove References, 然后, 重新右键 -> Add Files To..., 找到添加的文件, 重新添加即可.
2.2 配置项目
2.2.1 添加info字段
在项目info.plist文件内添加以下字段:
MOBAppKey
MOBAppSecret
其值分别是Mob平台新建APP后获取的AppKey及Secret;
2.2.2 添加系统依赖库
在Target -> General -> Linked Frameworks and Libraries 添加
必加依赖库:
libicucore.tbd
libz.tbd
libstdc++.tbd
JavaScriptCore.framework
以下依赖库根据社交平台添加:
新浪微博SDK依赖库
ImageIO.framework
libsqlite3.tbd
QQ好友和QQ空间SDK依赖库
libsqlite3.tbd
微信SDK依赖库
libsqlite3.tbd
2.2.3 在Other Linker Flags加入-ObjC
如果使用了新浪微博SDK, 需要添加
在Target -> Build Setting -> Linking ->Other Linker Flags添加 -ObjC , 注意大小写.
2.3 设置 URL Scheme
URL Scheme是通过系统找到并跳转对应app的设置,通过向项目中的info.plist文件中加入URL types可使用第三方平台所注册的appkey信息向系统注册你的app,当跳转到第三方应用授权或分享后,可直接跳转回你的app。
在 Info -> URL Types 中添加:
具体的设置, 可参考官方文档中间部分内容.
平台 | 配置URL Scheme 格式举例 | 备注 |
新浪微博 | wb+微博appKey | 如AppKey:568898243 则为: wb568898243 |
QQ/Qzone(登录) | “tencent”+腾讯QQ互联应用appID | 如appID:100371282 则为: tencent100371282 |
QQ/Qzone(分享) | “QQ”+腾讯QQ互联应用appID的十六进制, 必须是8位, 不足8位的前面补0 | 如appID:100371282, 其十六进制为: 5fb8b52 , 因为不足8位,所以应写为: QQ05fb8b52 |
微信 | 微信的appid | wx4868b35061f87885 |
如果是
2.4 适配 iOS 9 +
在iOS 9以上系统, 需要添加一些设置:
2.4.1 配置SSO白名单
在iOS9以上系统需要增加一个可跳转App的白名单,即LSApplicationQueriesSchemes, 否则将在SDK判断是否跳转时用到的canOpenURL时返回NO,进而只进行webview授权或授权/分享失败.
在项目中的info.plist中加入应用白名单,右键info.plist选择source code打开, 根据选择的平台对以下配置进行缩减:
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
其他平台, 可参考官方文档
2.4.2 网络请求
- 方式一: 暂时回退到HTTP请求
在Info.plist文件中添加字段: NSAppTransportSecurity, 类型为字典;
然后添加一个Key:NSAllowsArbitraryLoads, 类型为Boolean, 值为 YES
或者以Source Code 打开Info.plist文件, 空白处添加以下代码:
NSAppTransportSecurity
NSAllowsArbitraryLoads
- 方式二: 设置域
在项目的info.plist中添加一个Key:NSAppTransportSecurity,类型为字典类型。
然后给它添加一个值: NSExceptionDomains,类型为字典类型;
把需要的支持的域添加給NSExceptionDomains
其中域作为Key,类型为字典类型。
每个域下面需要设置3个属性:
NSIncludesSubdomains、
NSExceptionRequiresForwardSecrecy、NSExceptionAllowsInsecureHTTPLoads。
均为Boolean类型,值分别为YES、NO、YES
微信需要设置的域为:
- qq.com
或者以Source Code 打开Info.plist文件, 空白处添加以下代码:
NSAppTransportSecurity
NSExceptionDomains
qq.com
NSExceptionAllowsInsecureHTTPLoads
NSExceptionRequiresForwardSecrecy
NSIncludesSubdomains
PS: 这种方式需要对每个要以HTTP方式访问的域名进行设置, 比较麻烦, 建议使用第一种方式.
到此, 相关的配置就完成了, 下面就是使用相关的API实现相应的功能.
PS: 如果是Swift项目, 在使用相关API的时候, 需要新建桥接头文件, 或者在已有桥接头文件内引用其头文件:
#import
#import
//腾讯开放平台(对应QQ和QQ空间)SDK头文件
#import
#import
//微信SDK头文件
#import "WXApi.h"
//新浪微博SDK头文件
#import "WeiboSDK.h"
三. 登录
以上配置完成, 接下来的就很简单了, 登录授权的API相对比较简单.所有平台的登录请参考官方文档
3.1 注册APP
在相应的第三方开放平台新建APP之后, 获取到相应的APPkey和appSecret; 调用以下方法进行注册:
class func registApp() {
ShareSDK.registerActivePlatforms([SSDKPlatformType.typeQQ.rawValue, SSDKPlatformType.typeWechat.rawValue, SSDKPlatformType.typeSinaWeibo.rawValue], onImport: { (platform) in
switch platform {
case SSDKPlatformType.typeQQ:
ShareSDKConnector.connectQQ(QQApiInterface.self, tencentOAuthClass: TencentOAuth.self)
case SSDKPlatformType.typeWechat:
ShareSDKConnector.connectWeChat(WXApi.self)
case SSDKPlatformType.typeSinaWeibo:
ShareSDKConnector.connectWeibo(WeiboSDK.self)
default:
break
}
}) { (platform, appInfo) in
switch platform {
case SSDKPlatformType.typeQQ:
appInfo?.ssdkSetupQQ(byAppId: kShareSDK_QQAppID, appKey: kShareSDK_QQAppKey, authType: SSDKAuthTypeBoth)
case SSDKPlatformType.typeWechat:
appInfo?.ssdkSetupWeChat(byAppId: kShareSDK_WechatAppID, appSecret: kShareSDK_WechatAppSecret)
case SSDKPlatformType.typeSinaWeibo:
appInfo?.ssdkSetupSinaWeibo(byAppKey: kShareSDK_SinaWeiboAppKey, appSecret: kShareSDK_SinaWeiboAppSecret, redirectUri: kShareSDK_SinaWeibOredirectUri, authType: SSDKAuthTypeBoth)
default:
break
}
}
}
此方法要在AppDelegate中的 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 方法中调用;
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
LQShareSDK.registApp()
return true
}
3.2 获取授权及用户信息
以上设置完毕, 只需要在登登录的事件内添加以下获取授权的方法即可, 这里我封装进了一个方法里:
class func login(_ type: LQShareType, success handle: @escaping ((_ uid: String, _ name: String, _ url: String, _ sex: String) -> Void), failed: ((_ error: Error) -> Void)?) {
var shareType: SSDKPlatformType?
switch type {
case .qq:
shareType = SSDKPlatformType.typeQQ
case .wechat:
shareType = SSDKPlatformType.typeWechat
case .sinaWeibo:
shareType = SSDKPlatformType.typeSinaWeibo
}
if let login = shareType {
ShareSDK.cancelAuthorize(login)
ShareSDK.getUserInfo(login) { (state, user, error) in
if state == SSDKResponseState.success {
var uid = ""
if let ui = user?.uid {
uid = ui
}
var nickName = ""
if let name = user?.nickname {
nickName = name
}
var icon = ""
if let ic = user?.icon {
icon = ic
}
var gender = ""
if let gen = user?.gender {
if gen == 0 {
gender = "男"
} else if gen == 1 {
gender = "女"
}else{
gender = "未知"
}
}
handle(uid, nickName, icon, gender)
} else {
if let handle = failed {
handle(error!)
}
}
}
}
}
其中 LQShareType 为登录的类型:
enum LQShareType {
case qq, wechat, sinaWeibo
}
这里只使用了微信/QQ/新浪微博登录, 一般常用的也是这三种, 结果回调里返回了uid, name, 头像, 性别. 其他的内容可参考文档获取.对象的 rawData 属性可获取原始的第三方数据.
四. 简单分享
在创建分享内容时, 可使用下面的API进行简单的分享:
/**
* 设置分享参数
*
* @param text 文本
* @param images 图片集合,传入参数可以为单张图片信息,也可以为一个NSArray,数组元素可以为UIImage、NSString(图片路径)、NSURL(图片路径)、SSDKImage。如: @"http://www.mob.com/images/logo_black.png" 或 @[@"http://www.mob.com/images/logo_black.png"]
* @param url 网页路径/应用路径
* @param title 标题
* @param type 分享类型
*/
- (void)SSDKSetupShareParamsByText:(NSString *)text
images:(id)images
url:(NSURL *)url
title:(NSString *)title
type:(SSDKContentType)type;
另外, ShareSDK 也有针对各个平台的分享参数设API, 可直接查看其接口文档.
4.1 使用Mob的分享面板
引入ShareSDK的UI模块后, 即可使用ShareSDK的分享面板, 在创建分享到各个平台的消息后, 可直接调用此方法来弹出分享面板进行分享.
#import
class func shareUI() {
let shareParams: NSMutableDictionary = NSMutableDictionary()
shareParams.ssdkSetupShareParams(byText: "分享内容", images: "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1510826207776&di=5308bfb4c02cefc1210cad3eb963993b&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2Fd788d43f8794a4c273cb6b0804f41bd5ad6e392c.jpg", url: URL.init(string: "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1510826207776&di=5308bfb4c02cefc1210cad3eb963993b&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2Fd788d43f8794a4c273cb6b0804f41bd5ad6e392c.jpg"), title: "分享标题", type: SSDKContentType.audio)
//1.要显示菜单的视图, iPad版中此参数作为弹出菜单的参照视图,只有传这个才可以弹出我们的分享菜单,可以传分享的按钮对象或者自己创建小的view 对象,iPhone可以传nil不会影响
// 2. 菜单项, 需要分享到的平台, 如果传nil, 则会显示所有已集成的平台 SSDKPlatformType
// 3. 分享的内容
ShareSDK.showShareActionSheet(nil, items: nil, shareParams: shareParams) { (state, type, info, entity, error, end) in
if state == SSDKResponseState.success {
print("分享成功")
} else {
print("分享失败")
}
}
}
以下用到的shareSession函数定义如下:
private class func shareSession(_ type: LQShareSession) -> SSDKPlatformType {
switch type {
case .qq:
return SSDKPlatformType.subTypeQQFriend
case .qzone:
return SSDKPlatformType.subTypeQZone
case .wechatSession:
return SSDKPlatformType.subTypeWechatSession
case .wechatTimeline:
return SSDKPlatformType.subTypeWechatTimeline
case .wechatFavorite:
return SSDKPlatformType.subTypeWechatFav
case .sina:
return SSDKPlatformType.typeSinaWeibo
}
}
4.2 分享网页
/// 分享网页
///
/// - Parameters:
/// - url: 网页地址
/// - thumbImage: 网页缩略图
/// - title: 网页标题
/// - descr: 网页描述
/// - session: 分享到的平台
/// - success: 成功回调
/// - failed: 失败回调
class func shareWeb(_ url: String, thumbImage: String? = nil, title: String? = nil, descr: String? = nil, to session: LQShareSession, success: (() -> Void)? = nil, failed: (() -> Void)? = nil) {
let shareParams = NSMutableDictionary()
shareParams.ssdkSetupShareParams(byText: descr, images: thumbImage, url: URL.init(string: url), title: title, type: SSDKContentType.webPage)
ShareSDK.share(shareSession(session), parameters: shareParams) { (state, info, entity, error) in
if state == SSDKResponseState.success {
if let handle = success {
handle()
}
} else {
if let handle = failed {
handle()
}
}
}
}
4.3 分享图片
/// 分享图片
///
/// - Parameters:
/// - image: 图片内容, 可以为Data, UIImage, String, 或一组图片, 当为一组图片时, 只分享第一张
/// - session: 分享到的平台
/// - success: 成功的回调
/// - failed: 失败的回调
class func shareImage(_ image: Any, to session: LQShareSession, success: (() -> Void)? = nil, failed: (() -> Void)? = nil) {
let shareParams = NSMutableDictionary()
shareParams.ssdkSetupShareParams(byText: nil, images: image, url: nil, title: nil, type: SSDKContentType.image)
ShareSDK.share(shareSession(session), parameters: shareParams) { (state, info, entity, error) in
if state == SSDKResponseState.success {
if let handle = success {
handle()
}
} else {
if let handle = failed {
handle()
}
}
}
}
4.4 分享文本
分享纯文本的时候, 找了半天没有找到纯文本的媒体对象, 后来发现, 直接设置发送消息即可, 文档中也没用说明, 着实有点坑:
/// 分享文本
///
/// - Parameters:
/// - text: 文本
/// - session: 分享到的平台
/// - success: 成功的回调
/// - failed: 失败的回调
class func shareText(_ text: String, to session: LQShareSession, success: (() -> Void)? = nil, failed: (() -> Void)? = nil) {
let shareParams = NSMutableDictionary()
shareParams.ssdkSetupShareParams(byText: text, images: nil, url: nil, title: nil, type: SSDKContentType.text)
ShareSDK.share(shareSession(session), parameters: shareParams) { (state, info, entity, error) in
if state == SSDKResponseState.success {
if let handle = success {
handle()
}
} else {
if let handle = failed {
handle()
}
}
}
}
4.5 分享视频
/// 分享视频
///
/// - Parameters:
/// - url: 视频url地址
/// - thumbImage: 视频缩略图
/// - title: 视频标题
/// - descr: 视频描述
/// - session: 分享到的平台
/// - success: 分享成功回调
/// - failed: 分享失败回调
class func shareVideo(_ url: String, thumbImage: String? = nil, title: String? = nil, descr: String? = nil, to session: LQShareSession, success: (() -> Void)? = nil, failed: (() -> Void)? = nil) {
let shareParams = NSMutableDictionary()
shareParams.ssdkSetupShareParams(byText: descr, images: thumbImage, url: URL.init(string: url), title: title, type: SSDKContentType.video)
ShareSDK.share(shareSession(session), parameters: shareParams) { (state, info, entity, error) in
if state == SSDKResponseState.success {
if let handle = success {
handle()
}
} else {
if let handle = failed {
handle()
}
}
}
}
其他类型的分享, 可直接参考官方文档或者其API.
文章涉及的demo在Github LQThirdParty, 欢迎Star | Fork