Android 友盟社會化分享的整合與封裝
分享是APP中非常高頻的操作之一,在Android的開發環境中,第三方分享框架也有很多。比較流行的包括 極光社會化分享(sharesdk)、友盟社會化分享(Ushare)、Mob社會化分享以及在githut上比較流行的 ShareSDK、ShareUtil、BiliShare、ShareLoginLib等等。 本篇文章基於友盟ShareSDK,介紹了其整合過程並對其進行模組化封裝,以便在專案中更快捷的整合和使用。
整合前準備
-
獲取友盟Appkey
在【友盟+】官網註冊並且新增新應用,獲得Appkey。友盟後臺的應用名與實際應用名和包名無關,建議命名為應用名+平臺(iOS/Android),Android和IOS兩個平臺不能進行共用,需要進行分開。 建議使用企業郵箱註冊,避免使用個人郵箱註冊。
-
三方賬號申請
因為涉及到和各個分享平臺的互動,所以在整合前需要在各個平臺建立應用並提交稽核。建立應用後,分享、登入操作時顯示的應用icon、名稱和對應開放平臺設定有關,必須要建立應用的平臺為:微信、新浪、QQ、Facebook、Kakao、LinkeIn、Twitter、釘釘。
目前整合的內容只包含微信、新浪、QQ三個平臺,申請渠道如下:
平臺 申請地址 微信開放平臺 open.weixin.qq.com/ QQ互聯平臺 connect.qq.com/ 微博開放平臺 open.weibo.com 注1:申請QQ登入一定要在QQ互聯平臺,不是在QQ開放平臺(open.qq.com)
注2:申請過程中可能需要企業相關資質,如法人身份證、營業執照、稅務登記證等,需要提前準備好。
注3:提交應用申請時,需要提交應用相關的資訊(應用名稱、介紹、圖示、截圖、授權回撥域等),微信還需要提交《微信開放平臺網站資訊登記表》。
注4: 建議大家用企業賬號申請第三方開放平臺,不要使用個人的QQ、微信、微博和郵箱進行申請,這樣可以避免申請人在職位變動或者離職後,導致賬號管理的風險和交接麻煩。
注5:開放平臺申請多數需要稽核流程,因此在專案開始時,建議首先申請開放平臺賬號和建立應用,以免申請時間長影響開發進度。
申請很複雜,所以一般直接找產品經歷要就好啦(#笑)。如果是練習用的話,可以直接用官方Demo的包名com.umeng.soexample建立一個示例專案,沿用簽名檔案、Appkey以及各個三方的Appkey就好了。
整合友盟sdk
在後期模組化後,直接引入封裝好的模組即可整合,這裡先介紹一下通過新增sdk的方式整合,以及其中我遇到過的問題。
-
下載SDK
最新SDK地址,可以看到友盟的分享包含很多平臺,這裡我們只用到了微博微信QQ的分享和登入功能,不包含支付等,所以選擇預設下載的三個精簡版即可。如有需求可以參考官方開發文件新增使用。
-
新增SDK
解壓下載的sdk壓縮包,我們需要用到其中common和share資料夾下的內容。res顧名思義都是資原始檔,複製到專案的res目錄中,其他所有jar檔案複製到專案的app/libs目錄下,並確保在app的gradle依賴中包含implementation fileTree(include: ['*.jar'], dir: 'libs') ,將這個資料夾中所有jar包匯入到專案裡。
-
新增回撥Activity
用到的三個平臺中,只有微信需要手動新增Activity。具體做法是,在包名目錄下建立wxapi資料夾,新建一個名為
WXEntryActivity
的Activity繼承WXCallbackActivity
,內容為空即可。 -
配置Android Manifest XML
在專案的Manifest中新增各個回撥Activity:
<activity android:name=".wxapi.WXEntryActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="true" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <activity android:name="com.umeng.socialize.media.WBShareCallBackActivity" android:configChanges="keyboardHidden|orientation" android:exported="false" android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity> <activity android:name="com.sina.weibo.sdk.web.WeiboSdkWebActivity" android:configChanges="keyboardHidden|orientation" android:exported="false" android:windowSoftInputMode="adjustResize"></activity> <activity android:name="com.sina.weibo.sdk.share.WbShareTransActivity" android:launchMode="singleTask" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"> <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="com.tencent.tauth.AuthActivity" android:launchMode="singleTask" android:noHistory="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="tencent100424468" /> </intent-filter> </activity> <activity android:name="com.tencent.connect.common.AssistActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> 複製程式碼
其中qq的appkey需要替換成自己申請的appkey,這裡用的是友盟官方demo的以作測試用。
-
新增許可權
在AndroidManifest中新增以下許可權:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> 複製程式碼
如果專案的目標sdk版本高於Android6.0,即 targetSdkVersion >= 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); } 複製程式碼
-
初始化設定
將前面的都整合之後,接下來就可以正式進入到程式碼層面的操作啦。在Application中呼叫友盟的初始化介面,以及設定各個平臺的appkey,這裡全部用的是官方demo測試用的appkey。
public class App extends Application { @Override public void onCreate() { super.onCreate(); //初始化元件化基礎庫, 統計SDK/推送SDK/分享SDK都必須呼叫此初始化介面 UMConfigure.init(this, "5bed13e1f1f5564655000404", "Umeng", UMConfigure.DEVICE_TYPE_PHONE, "d9352161be267fb40fb12ad5eb04edf9"); UMShareAPI.get(this); } //各個平臺的配置 { //微信 PlatformConfig.setWeixin("wxdc1e388c3822c80b", "3baf1193c85774b3fd9d18447d76cab0"); //新浪微博(第三個引數為回撥地址) PlatformConfig.setSinaWeibo("3921700954", "04b48b094faeb16683c32669824ebdad", "http://sns.whalecloud.com"); //QQ PlatformConfig.setQQZone("100424468", "c7394704798a158208a74ab60104f0ba"); PlatformConfig.setYixin("yxc0614e80c9304c11b0391514d09f13bf"); PlatformConfig.setTwitter("3aIN7fuF685MuZ7jtXkQxalyi", "MK6FEYG63eWcpDFgRYw4w9puJhzDl0tyuqWjZ3M7XJuuG7mMbO"); PlatformConfig.setAlipay("2015111700822536"); PlatformConfig.setLaiwang("laiwangd497e70d4", "d497e70d4c3e4efeab1381476bac4c5e"); PlatformConfig.setPinterest("1439206"); PlatformConfig.setKakao("e4f60e065048eb031e235c806b31c70f"); PlatformConfig.setDing("dingoalmlnohc0wggfedpk"); PlatformConfig.setVKontakte("5764965", "5My6SNliAaLxEm3Lyd9J"); PlatformConfig.setDropbox("oz8v5apet3arcdy", "h7p2pjbzkkxt02a"); } } 複製程式碼
-
新增簽名檔案
部分平臺在申請appkey的時候就需要專案的簽名檔案,如果沒有的話會影響授權。常規專案只要正常申請好籤名就可以了,這裡講一下作為測試用例如何新增簽名。
將官方demo中app目錄下的debug.keystore複製到自己的練習專案app目錄下
在專案的app.gradle依賴中android條目下新增如下程式碼:
buildTypes { release { // 是否進行混淆 minifyEnabled false // 簽名檔案 signingConfig signingConfigs.debug // 混淆檔案的位置 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false signingConfig signingConfigs.debug proguardFiles 'proguard-rules.pro' } } signingConfigs { debug { storeFile file('debug.keystore') storePassword "android" keyAlias "androiddebugkey" keyPassword "android" } } 複製程式碼
開始分享
終於到了分享的步驟,是騾子是馬要牽出來溜溜看看能不能走了,先介紹一下友盟分享的兩種形式:
-
使用分享皮膚的分享,使用者可以呼叫我們的開啟分享皮膚的方法,點選分享皮膚的對應平臺進行分享。
-
不使用分享皮膚的分享,使用者可以自己寫分享按鈕,或者觸發事件,然後呼叫我們的分享方法,進行分享。簡而言之,直接分享就是在使用者自己的介面元件中插入分享行為,分享皮膚是開啟我們寫好的一個介面元件,根據點選事件進行分享。
可分享的內容包括:
平臺 | 授權 | 可分享內容 | 使用者資訊 |
---|---|---|---|
是 | 文字 圖片 連結 視訊 音樂 | 是 | |
qq空間 | 同qq | 文字(說說) 圖片(說說) 連結 視訊 音樂 | 同qq |
微信 | 是 | 文字 圖片 連結 視訊 音樂 | 是 |
微信朋友圈 | 同微信 | 文字 圖片 連結 視訊 音樂 (分享連結不顯示描述) | 同微信 |
微信收藏 | 同微信 | 文字 圖片 連結 視訊 音樂 檔案 | 同微信 |
新浪微博 | 是 | 文字 圖片 連結 視訊 音樂 檔案 | 是 |
下面以直接分享一個網站到微信平臺為例,看一下具體的程式碼實現:
UMWeb web = new UMWeb("https://gank.io/");//建立要分享的Web物件,傳入分享的url地址
web.setTitle("測試分享標題");//設定標題
web.setThumb(new UMImage(this, R.drawable.thumb));//設定傳入顯示的縮圖
web.setDescription("測試分享內容測試分享內容測試分享內容測試分享內容測試分享內容");//設定描述
new ShareAction(ShareDetailActivity.this)//開啟分享
.withMedia(web) //填入建立好的分享內容
.setPlatform(SHARE_MEDIA.WEIXIN)//選擇分享平臺
.setCallback(shareListener)//設定對分享返回結果的監聽
.share();//啟動分享操作
複製程式碼
實現效果如下:
以皮膚的形式分享這個網站:
ShareBoardlistener boardListener = new ShareBoardlistener() { //建立皮膚的監聽器
@Override
public void onclick(SnsPlatform snsPlatform, SHARE_MEDIA platform) {
new ShareAction(mActivity)//開啟分享
.withMedia(web) //填入建立好的分享內容
.setPlatform(platform)//填入選擇的平臺
.setCallback(shareListener)//設定對分享返回結果的監聽
.share();//啟動分享操作
}
};
new ShareAction(mActivity)
.setDisplayList(SHARE_MEDIA.WEIXIN, SHARE_MEDIA.WEIXIN_CIRCLE, SHARE_MEDIA.WEIXIN_FAVORITE,
SHARE_MEDIA.SINA, SHARE_MEDIA.QQ, SHARE_MEDIA.QZONE)//設定分享皮膚顯示的平臺
.setShareboardclickCallback(boardListener)//新增之前建立的皮膚監聽器
.open(config);//開啟分享皮膚 其中可傳入能對皮膚樣式進行自定義操作的config物件
//比如設定皮膚在底部還是中部顯示、是否有取消按鈕、圖示形狀、字型大小和背景顏色等等
複製程式碼
預設居中的皮膚效果如下:
最後不要忘記在呼叫分享的Activity中,新增如下程式碼,關閉監聽,防止記憶體洩露等問題。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onDestroy() {
super.onDestroy();
UMShareAPI.get(this).release();
}
複製程式碼
對友盟分享的模組化和程式碼封裝
在前面的內容裡,我們完整的體驗了友盟社會化分享的準備、整合和使用,雖然看起來比較簡單明瞭,但對於初次接觸的人還是比較容易碰到問題的,在專案中多次整合也比較繁瑣。所以接下來到了本文的重點內容,對友盟的分享進行模組化,在需要時直接匯入模組即可使用,並將主要方法進行封裝處理,在開發時提高效率,減少程式碼量。
下面記錄一下封裝過程中的思路和過程,以及封裝後的使用方法。
-
封裝過程
在前面的使用介紹中,可以看到每一次分享,都需要提前建立好待分享的內容,需要傳入的資料越多,程式碼行數越多,所以首先對待建立的物件進行封裝。
根據分享的型別,分了8個類:
分享型別 列舉引數 僅文字 SHARE_TYPE_TEXT 僅圖片 SHARE_TYPE_IMAGE 圖文 SHARE_TYPE_TEXTANDIMG 網址 SHARE_TYPE_WEB 網路視訊 SHARE_TYPE_VIDEO 網路音樂 SHARE_TYPE_MUSIC GIF表情 SHARE_TYPE_EMOJI 微信小程式 SHARE_TYPE_MINAPP 其中圖片可以通過資原始檔id、File檔案、網路地址、Bitmap物件、還有byte[]這些方式來建立,其他很多型別雖然不需要圖片,但很多需要縮圖,而縮圖的本質也是圖片,所以可以將縮圖獨立出來:
private static UMImage mThumb; //建立待分享所用的縮圖 public static void createThumbImage(int thumbResId) { mThumb = new UMImage(mActivity, thumbResId); } public static void createThumbImage(File thumbFile) { mThumb = new UMImage(mActivity, thumbFile); } public static void createThumbImage(String thumbImageUrl) { mThumb = new UMImage(mActivity, thumbImageUrl); } public static void createThumbImage(Bitmap thumbBitmap) { mThumb = new UMImage(mActivity, thumbBitmap); } public static void createThumbImage(byte[] thumbBytes) { mThumb = new UMImage(mActivity, thumbBytes); } 複製程式碼
接下來以建立待分享的網址為例,需要傳入的資料包括視訊地址、標題、描述、縮圖最少4個內容,前三個都是String物件,最複雜的縮圖已經通過上面的方法建立好了,所以只需要新增前三個內容就夠了:
private static UMWeb mWeb; //建立待分享的連結 需要縮圖 public static void createUrl(String url, String title, String description) { mWeb = new UMWeb(url); mWeb.setTitle(title); mWeb.setDescription(description); mWeb.setThumb(mThumb);//傳入建立好的縮圖 } 複製程式碼
到此我們已經建立好了需要分享的網址物件,接下來自然而然就是分享了。實現非常簡單粗暴,直接傳入需要分享的平臺和型別對應的列舉名即可:
public static void share(SHARE_MEDIA platform, SHARE_TYPE shareType) { ShareAction action = new ShareAction(mActivity) .setPlatform(platform).setCallback(mListener); switch (shareType) { case SHARE_TYPE_TEXT: action.withText(mText).share(); break; case SHARE_TYPE_IMAGE: action.withMedia(mImage).share(); break; case SHARE_TYPE_TEXTANDIMG: action.withText(mText).withMedia(mImage).share(); break; case SHARE_TYPE_WEB: action.withMedia(mWeb).share(); break; case SHARE_TYPE_VIDEO: action.withMedia(mVideo).share(); break; case SHARE_TYPE_MUSIC: action.withMedia(mMusic).share(); break; case SHARE_TYPE_EMOJI: action.withMedia(mEmoji).share(); break; case SHARE_TYPE_MINAPP: action.withMedia(mMinAPP).share(); break; } } 複製程式碼
到這裡基本將直接分享的內容進行了封裝,那麼如果使用者不需要我們已經設好的分享callback,想要自定義呢?所以需要構建一個方法讓使用者傳入自定義的監聽器:
//設定分享監聽 傳入自定義的監聽方式 public static void setShareListener(UMShareListener listener) { mListener = listener; } 複製程式碼
除了直接分享,還有皮膚形式的分享,在這裡提供了三種形式的封裝:
-
直接在中間顯示分享皮膚
public static void shareBoardAtCenter(SHARE_TYPE shareType) { ShareBoardConfig config = new ShareBoardConfig(); config.setShareboardPostion(ShareBoardConfig.SHAREBOARD_POSITION_CENTER); config.setCancelButtonVisibility(true); shareBoard(config, shareType); } 複製程式碼
-
在底部顯示分享皮膚
public static void shareBoardAtBottom(SHARE_TYPE shareType) { ShareBoardConfig config = new ShareBoardConfig(); config.setShareboardPostion(ShareBoardConfig.SHAREBOARD_POSITION_BOTTOM); config.setCancelButtonVisibility(true); shareBoard(config, shareType); } 複製程式碼
-
使用者自定義分享皮膚
public static void setBoardWithConfig(ShareBoardConfig config, SHARE_TYPE shareType) { shareBoard(config, shareType); } 複製程式碼
三種方式,最終都是將皮膚定義 config 以及要分享的型別 shareType 傳入 shareBoard() 方法中,config的具體自定義方法見官方文件,下面貼出 shareBoard() 方法:
private static void shareBoard(ShareBoardConfig config, final SHARE_TYPE shareType) { ShareBoardlistener boardListener = new ShareBoardlistener() { @Override public void onclick(SnsPlatform snsPlatform, SHARE_MEDIA platform) { share(platform, shareType); } }; new ShareAction(mActivity) .setDisplayList(SHARE_MEDIA.WEIXIN, SHARE_MEDIA.WEIXIN_CIRCLE, SHARE_MEDIA.WEIXIN_FAVORITE, SHARE_MEDIA.SINA, SHARE_MEDIA.QQ, SHARE_MEDIA.QZONE) .setShareboardclickCallback(boardListener) .open(config); } 複製程式碼
可以看出在選擇平臺後,具體分享的實現方法又跳轉到了share()中,實現了程式碼的複用,對於使用者需要自定義皮膚分享哪些平臺,同樣可以通過setPlatforms()方法實現:
//設定分享皮膚要分享的內容 public static void setBoardPlatforms(SHARE_MEDIA[] platforms) { mPlatforms = platforms; } 複製程式碼
-
-
使用方法
整體的使用比較簡單明瞭,不過需要注意的是,除了分享文字圖片,其他型別都要記得先建立縮圖。
下面以分享一個網址或者視訊為例:
//首先需要初始化 UShareUtils.init(this); //建立縮圖 UShareUtils.createThumbImage(R.drawable.cat80); //建立待分享的網址,傳入網址、標題和描述 UShareUtils.createUrl("https://gank.io/", "分享標題", "分享描述"); //建立待分享的視訊,傳入視訊地址、標題和描述 UShareUtils.createVideo("http://vfx.mtime.cn/Video/2018/10/26/mp4/181026140242572417.mp4", "《馴龍高手3》中文預告", "《馴龍高手3 》由夢工場動畫出品,馴龍高手是影史上最受歡迎的動畫系列之一,而這部備受期待的新片是該系列的第三部。 "); //點選分享 @OnClick({R.id.tv_share_web, R.id.tv_share_video, R.id.tv_share_board, R.id.tv_share_center}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.tv_share_web: //分享WEB到QQ UShareUtils.share(SHARE_MEDIA.QQ, SHARE_TYPE.SHARE_TYPE_WEB); break; case R.id.tv_share_video: //分享視訊到微信 UShareUtils.share(SHARE_MEDIA.WEIXIN, SHARE_TYPE.SHARE_TYPE_VIDEO); break; case R.id.tv_board_board: //開啟底部分享皮膚 分享WEB UShareUtils.shareBoardAtBottom(SHARE_TYPE.SHARE_TYPE_WEB); break; case R.id.tv_board_center: //開啟中部分享皮膚 分享視訊 UShareUtils.shareBoardAtBottom(SHARE_TYPE.SHARE_TYPE_VIDEO); break; } } 複製程式碼