最新版本(1.2.0) Easier 、Lighter 、 More Business-Oriented
以更簡單、更輕、更面向業務需求為設計目標,提供微博、微信、 QQ 、 Tim 、 QQ 輕聊版、釘釘的登陸分享功能支援;
專案地址: GitHub - SocialSdkLibrary
部落格網址:快速接取微信微博QQ釘原生登入分享
?微信QQ微博SDK 版本可以升級了,下個版本升級,微博變動較大;
?2020.1.21 有362顆? 啦, 發布版本1.2.0
, 插件更新,支援最新版本的Gradle
, 採用Gradle + APT + ASM
自動發現Platform
類,自動註冊初始化程式碼,內建了json
解析和http
請求,初始化配置更簡單;
? 2019.6.13 支援微信掃碼登入
?2019.5.28 專案獲得了第329顆?, 對生命週期做自動管理,統一回調參數,發布穩定版本1.0.1 ❤️,
?2019.3.28 使用gradle plugin
自動管理依賴,重新設計版本號穩定版本0.1.1 ❤️
?2018.12.27 完成gradle
插件,分割平台,自動化依賴,一個新台階?
?2018.12.21 已經225顆?,著手準備拆分成不同平台庫,方便靈活接入⛽️
?2018.9.26 專案獲得了第202顆?,感謝新同事補星2 個?
?2018.6.7 項目獲得了第100顆?,最後一顆是我問同事要的?
?2018.5.12 修復記憶體問題、功能擴充穩定版本 1.1.0 ❤️
? 2018.2.12 支援釘釘分享?
?2017.12.12 簡單重構程式碼並測試穩定版本 1.0.0 ❤️
開源:沒有彩蛋,沒有彩蛋,沒有彩蛋;
簡單:只需要專注在登入、分享管理類別和一個資料結構物件即可,不需要再關注平台之間的差異;
輕量:僅包含三方SDK
和一個簡單的非同步框架(38k),網路請求、 JSON
解析從外部注入,減少多餘的依賴,確保與宿主項目高度統一;
全面:小程式分享、複製連結、掃碼登入、推廣聯運等;
面向需求設計:
code
,服務端取得token
?wxOnlyAuthCode
參數;web
分享兼容;Intent
喚醒分享,例如支援本地視訊分享, qq
的純文字分享等等;token
避免多次授權,可選擇有效時長,儲存token 下次授權可以直接取得數據,但是用戶換了微信帳號就沒辦法切換帳號啦,這個時長要仔細斟酌;SocialSdk
吧; STEP1 : 新增插件依賴路徑
project / build.gradle
buildscript {
repositories {
maven { url "https://dl.bintray.com/zfy/maven" }
}
dependencies {
// 请查看文初最新版本,这边可能忘记更新!!!
classpath 'com.zfy.social:social-sdk-plugin:1.2.0'
}
}
allprojects {
repositories {
maven { url "https://dl.bintray.com/zfy/maven" }
}
}
STEP2 : 配置參數
app / build.gralde
為了安全起見更建議在local.properties
中配置,這樣可以避免提交到遠端;
// 在顶部引用插件
apply plugin: 'socialsdk'
// android 配置模块
android {
...
}
// socialsdk 配置模块
socialsdk {
wx {
appId = '111xxx2222'
appSecret = '111xxx2222'
// 微信授权是否只返回 code, 用于服务端授权的场景
onlyAuthCode = false
}
qq {
appId = '111xxx2222'
appSecret = '111xxx2222'
}
wb {
appId = '111xxx2222'
url = '111xxx2222'
}
dd {
appId = '111xxx2222'
}
}
以上是最簡單的配置,更多配置參數參考,通常使用預設即可:
socialsdk {
// 调试模式,默认 false, 可以在代码中开启
debug = true
// 分享:选择停留在微信时自动返回成功,默认返回失败
shareSuccessIfStay = true
// 登录:token 过期时间,单位小时,默认立即过期,有效期内可以不需要再次唤醒第三方 app,但是二次登录也没办法切换账号,这会引发问题,所以默认立即过期
tokenExpiresHours = 100
// 使用 gson 作为数据解析,默认 true,你如果不用 gson 就需要自己编写 JSONAdapter
useGson = true
// 使用 okHttp 发送请求,默认 true,你如果不用 okhttp 就需要自己编写 RequestAdapter
useOkHttp = true
// 配置 app 名称,默认使用 R.string.app_name
appName = "哈哈哈"
// 唤醒过程中的 loading 颜色
color = "#FF0000"
wx { }
qq { }
wb { }
dd { }
}
STEP3 :初始化
SocialOptions options = new SocialOptions . Builder ( this )
// 调试模式,开启 log 输出
. debug ( true )
// 加载缩略图失败时,降级使用资源图
. failImgRes ( R . drawable . share_default_img )
// 添加分享拦截器,重新处理分享的数据
. addShareInterceptor (( context , obj ) -> {
obj . setSummary ( "被重新组装" + obj . getSummary ());
return obj ;
})
// 构建
. build ();
// 初始化
SocialSdk . init ( options );
登陸功能支援三個平台,qq,微信,微博;
// 3个平台
Target . LOGIN_QQ ; // QQ 登录
Target . LOGIN_WX ; // 微信 登录
Target . LOGIN_WX_SCAN ; // 微信扫码 登录
Target . LOGIN_WB ; // 微博 登录
登入將會傳回LoginResult
, 其中主要包括登入類型,基本使用者訊息,令牌資訊3 部分;
LoginResult {
// 状态,成功,失败,取消等
public int state ;
// 目标平台
public int target ;
// 发生错误时使用
public SocialError error ;
// 针对登录类型可强转为 WbUser,WxUser,QQUser 来获取更加丰富的信息
public SocialUser socialUser ;
// 本次登陆的 token 信息,openId, unionId,token,expires_in
public AccessToken accessToken ;
// 授权码,如果 onlyAuthCode 为 true, 将会返回它
public String wxAuthCode ;
// 扫码登录二维码文件路径
public String wxCodePath ;
}
登入時需要設定登入回呼:
new OnLoginStateListener () {
@ Override
public void onState ( Activity act , LoginResult result ) {
switch ( result . state ) {
case LoginResult . STATE_START :
// 登录开始
break ;
case LoginResult . STATE_COMPLETE :
// 登录完成
break ;
case LoginResult . STATE_ACTIVE :
// 透明 Activity 开启
break ;
case LoginResult . STATE_SUCCESS :
// 登录成功
break ;
case LoginResult . STATE_FAIL :
// 登录失败
result . error
break ;
case LoginResult . STATE_CANCEL :
// 登录取消
break ;
case LoginResult . STATE_WX_CODE_RECEIVE :
// 获取到微信登录二维码
break ;
case LoginResult . STATE_WX_CODE_SCANNED :
// 微信登录二维码被扫描
break ;
}
}
};
取得更多用戶資訊:
SocialUser socialUser = loginResult . socialUser ;
// 基本信息可以从 SocialUser 在获取到
String userNickName = socialUser . getUserNickName ();
// 获取 openId
String openId = socialUser . getOpenId ();
// 微信获取 unionId,其他平台仍旧返回 openId
String unionId = socialUser . getUnionId ();
// 获取 userId,微信返回 unionId, 其他平台返回 openId
String userId = socialUser . getUserId ();
// 强转为平台用户,可以拿到更多信息
int target = result . getTarget ();
switch ( target ) {
case Target . LOGIN_QQ :
QQUser qqUser = ( QQUser ) socialUser ;
break ;
case Target . LOGIN_WB :
WbUser wbUser = ( WbUser ) socialUser ;
break ;
case Target . LOGIN_WX :
WxUser wxUser = ( WxUser ) socialUser ;
break ;
}
發起登入:
LoginManager . login ( mActivity , Target . LOGIN_QQ , listener );
帶參數登錄,如微信二維碼掃碼登錄:
LoginObj obj = new LoginObj ();
// 根据文档要求,以下数据应在服务端缓存获取
// 如果不设置,将会使用配置时设置的 secret
obj . setAppSecret ( "0a3cb00******ee3654f499171" );
obj . setNonceStr ( "3611cdc33b******a49ca45bdfab2d" );
obj . setTimestamp ( "15604******6904" );
obj . setSignature ( "b28f69426******18c8ba792caa4a0a1bcc" );
// 如果不设置,将会使用 SocialValues.WX_SCOPE
obj . setScope ( SocialValues . WX_SCOPE );
LoginManager . login ( mActivity , Target . LOGIN_WX_SCAN , obj , listener );
關於token
時效,可以在初始化時設定tokenExpiresHours
來控制,也同樣提供清除授權token
的方法。
// 清除全部平台的 token
LoginManager . clearAllToken ( context );
// 清除指定平台的 token
LoginManager . clearToken ( context , Target . LOGIN_QQ );
重要:請仔細查看平台和資料類型中間的支援能力
當微博使用openApi
形式去分享時,可能有較長的延時,建議在生命週期中增加進度條顯示,避免用戶等待很久沒有回應。
針對業務邏輯和SDK
設計,將分享資料類型分為7 種類型,他們能涵蓋大多數業務場景,分別是:
开启 App 类型,打开渠道应用;
文字类型,纯文本分享;
图片类型(jpg, png, gif(要求能动));
App 推广类型;
网页链接类型;
音频分享类型;
视频分享类型;
為了確保每個平台都有封閉且統一的外觀,如果某個平台不相容於某種類型的分享,將會使用web
分享的方式取代;例如微信不支援app
分享,分享出去之後web
分享的模式。
// 支持的分享渠道
Target . SHARE_DD ; // 钉钉好友
Target . SHARE_QQ_FRIENDS ; // qq好友
Target . SHARE_QQ_ZONE ; // qq空间
Target . SHARE_WX_FRIENDS ; // 微信好友
Target . SHARE_WX_ZONE ; // 微信朋友圈
Target . SHARE_WX_FAVORITE ; // 微信收藏
Target . SHARE_WB ; // 新浪微博
Target . SHARE_SMS ; // 短信分享
Target . SHARE_EMAIL ; // 邮件分享
Target . SHARE_CLIPBOARD ; // 粘贴板分享
分享時,我們首先要建構分享用的數據, ShareObj
物件提供了多種靜態方法用來快速建立對應分享的類型的物件;
// 测试用的路径
localImagePath = new File ( Environment . getExternalStorageDirectory (), "1.jpg" ). getAbsolutePath ();
localVideoPath = new File ( Environment . getExternalStorageDirectory (), "video.mp4" ). getAbsolutePath ();
localGifPath = new File ( Environment . getExternalStorageDirectory (), "3.gif" ). getAbsolutePath ();
netVideoPath = "http://7xtjec.com1.z0.glb.clouddn.com/export.mp4" ;
netImagePath = "http://7xtjec.com1.z0.glb.clouddn.com/token.png" ;
netMusicPath = "http://7xtjec.com1.z0.glb.clouddn.com/test_music.mp3" ;
netMusicPath = "http://mp3.haoduoge.com/test/2017-05-19/1495207225.mp3" ;
targetUrl = "http://bbs.csdn.net/topics/391545021" ;
// 打开渠道对应app
ShareObj shareMediaObj = ShareObj . buildOpenAppObj ();
// 分享文字
ShareObj textObj = ShareObj . buildTextObj ( "分享文字" , "summary" );
// 分享图片
ShareObj imageObj = ShareObj . buildImageObj ( "分享图片" , "summary" , localImagePath );
// 分享gif
ShareObj imageGifObj = ShareObj . buildImageObj ( "分享图片" , "summary" , localGifPath );
// 分享app
ShareObj appObj = ShareObj . buildAppObj ( "分享app" , "summary" , localImagePath , targetUrl );
// 分享web
ShareObj webObj = ShareObj . buildWebObj ( "分享web" , "summary" , localImagePath , targetUrl );
// 分享视频
ShareObj videoObj = ShareObj . buildVideoObj ( "分享视频" , "summary" , localImagePath , targetUrl , localVideoPath , 10 );
// 本地视频分享、部分平台支持
ShareObj videoLocalObj = ShareObj . buildVideoObj ( "分享本地视频" , "summary" , localImagePath , targetUrl , localVideoPath , 0 );
// 分享音乐
ShareObj musicObj = ShareObj . buildMusicObj ( "分享音乐" , "summary" , localImagePath , targetUrl , netMusicPath , 10 );
針對一些不能被統一的參數使用擴展的參數來支援:
// 使 ShareObj 支持短信分享
webObj . setSmsParams ( "13611301719" , "说啥呢" );
// 使 ShareObj 支持粘贴板分享
webObj . setClipboardParams ( "复制的内容" );
// 使 ShareObj 支持邮件分享
webObj . setEMailParams ( "[email protected]" , "主题" , "内容" );
// 使 ShareObj 在微信平台优先使用小程序分享
webObj . setWxMiniParams ( "51299u9**q31" , SocialValues . WX_MINI_TYPE_RELEASE , "/page/path" );
使用OnShareStateListener
作為監聽分享回呼;
new OnShareStateListener () {
@ Override
public void onState ( Activity act , ShareResult result ) {
switch ( result . state ) {
case LoginResult . STATE_START :
// 分享开始
break ;
case LoginResult . STATE_COMPLETE :
// 分享完成
break ;
case LoginResult . STATE_ACTIVE :
// 透明 Activity 开启
break ;
case ShareResult . STATE_SUCCESS :
// 分享成功
break ;
case ShareResult . STATE_FAIL :
SocialError e = result . error ;
// 分享失败
break ;
case ShareResult . STATE_CANCEL :
// 分享取消
break ;
}
}
};
// 唤醒分享
ShareManager . share ( mActivity , Target . SHARE_QQ_FRIENDS , imageObj , mOnShareListener );
關於重寫分享對象,其實提供一個能在分享之前對需要分享的ShareObj
進行統一處理的機會,類似分享功能的一個切面,比如如下場景:
app
浮水印;url
帶上公共參數shareId
等,在H5
做訪問統計;重寫分享對象,我們使用攔截器來實現,攔截器在SDK
初始化時注入,支援多個,可以將不同業務分為不同的攔截器,所有攔截器都會被順序呼叫;
UI
需要到主執行緒執行;
SocialOptions options = new SocialOptions . Builder ( this )
// ... 其他初始化代码
// 添加分享拦截器
. addShareInterceptor (( context , target , obj ) -> {
obj . setSummary ( "描述加前缀" + obj . getSummary ());
return obj ;
})
. addShareInterceptor (( context , target , obj ) -> {
obj . setTargetUrl ( obj . getTargetUrl ()+ "?id=100" );
return obj ;
})
// 构建
. build ();
// 初始化
SocialSdk . init ( options );
我們通常會在做分享時遇到需求,複製到貼上/支援簡訊分享/支援郵件分享等等, SocialSdk
內建了這些功能,需要在創建ShareObj
之後添加額外參數來實現;
shareObj . setSmsParams ( "13611301719" , "说啥呢" );
shareObj . setEMailParams ( "[email protected]" , "主题" , "内容" );
shareObj . setClipboardParams ( "复制的内容" );
支援微信小程式分享,也同樣使用額外參數的形式
shareObj . setWxMiniParams ( "51299u9**q31" , SocialValues . WX_MINI_TYPE_RELEASE , "/page/path" );
為了更好的統一分享失敗時傳回的異常,傳回的所有異常都會有一個code
,可以根據不同的code
定位問題和給出更友善的提示。
int CODE_COMMON_ERROR = 101 ; // 通用错误,未归类
int CODE_NOT_INSTALL = 102 ; // 没有安装应用
int CODE_VERSION_LOW = 103 ; // 版本过低,不支持
int CODE_SHARE_BY_INTENT_FAIL = 105 ; // 使用 Intent 分享失败
int CODE_STORAGE_READ_ERROR = 106 ; // 没有读存储的权限,获取分享缩略图将会失败
int CODE_STORAGE_WRITE_ERROR = 107 ; // 没有写存储的权限,微博分享视频copy操作将会失败
int CODE_FILE_NOT_FOUND = 108 ; // 文件不存在
int CODE_SDK_ERROR = 109 ; // sdk 返回错误
int CODE_REQUEST_ERROR = 110 ; // 网络请求发生错误
int CODE_CANNOT_OPEN_ERROR = 111 ; // 无法启动 app
int CODE_PARSE_ERROR = 112 ; // 数据解析错误
int CODE_IMAGE_COMPRESS_ERROR = 113 ; // 图片压缩失败
int CODE_PARAM_ERROR = 114 ; // 参数错误
int CODE_SDK_INIT_ERROR = 115 ; // SocialSdk 初始化错误
int CODE_PREPARE_BG_ERROR = 116 ; // 执行 prepareOnBackground 时错误
int CODE_NOT_SUPPORT = 117 ; // 不支持
例如你可以這麼做:
listener = new OnShareStateListener () {
@ Override
public void onState ( Activity act , ShareResult result ) {
switch ( result . state ) {
case ShareResult . STATE_FAIL :
SocialError e = result . error ;
showMsg ( "分享失败 " + e . toString ());
// 如下因为没有存储权限导致失败,请求权限
if ( Build . VERSION . SDK_INT >= Build . VERSION_CODES . M ) {
if ( e . getCode () == SocialError . CODE_STORAGE_READ_ERROR ) {
requestPermissions ( new String []{ Manifest . permission . READ_EXTERNAL_STORAGE }, 100 );
} else if ( e . getCode () == SocialError . CODE_STORAGE_WRITE_ERROR ) {
requestPermissions ( new String []{ Manifest . permission . WRITE_EXTERNAL_STORAGE }, 100 );
}
}
break ;
}
}
};
public class HuaweiPlatform extends AbsPlatform {
// 工厂函数
public static class Factory implements PlatformFactory {
@ Override
public IPlatform create ( Context context , int target ) {
return new HuaweiPlatform ( context , null , null , target );
}
@ Override
public int getPlatformTarget () {
return PLATFORM_HUAWEI ;
}
@ Override
public boolean checkShareTarget ( int shareTarget ) {
return false ;
}
@ Override
public boolean checkLoginTarget ( int loginTarget ) {
return loginTarget == LOGIN_HUAWEI ;
}
}
public HuaweiPlatform ( Context context , String appId , String appName , int target ) {
super ( context , appId , appName , target );
}
}
最重要的是編寫平台的工廠函數,框架會自動發現然後註冊到系統中,不需要手動註冊了;
SocialSdk
內部對生命週期有自動的管理,每次登入分享結束了都會回收掉所有的資源; 發起登入分享的Activity
建議實現LifecycleOwner
接口,可以直接使用AppCompatActivity
,內部會做生命週期的綁定,避免記憶體洩漏的發生;
QQ:
libs/open_sdk_r2973327_lite.jar
更新與2019.12微信:
com.tencent.mm.opensdk:wechat-sdk-android-without-mta:5.5.8
更新與2020.1.22微博:
com.sina.weibo.sdk:core:4.3.7:openDefaultRelease@aar
釘釘:
com.alibaba.android:ddsharesdk:1.1.0