抖音做爲日活量過億的產品,在今年年初,也終於上線了抖音開放平臺,目前支持app接入登陸與分享。app經過抖音受權獲取用戶信息;分享視頻並進行處理,提升app在抖音的曝光度。java
恰好項目有個新需求,須要集成抖音登陸與分享。抖音開發者文檔android
本覺得不就是接個SDK嘛,溼溼水啦!可是bug總與我相伴!且聽我慢慢道來。c#
一、在項目根目錄build.gradle裏添加maven:api
allprojects {
repositories {
……
maven { url 'https://dl.bintray.com/aweme-open-sdk-team/public' }
}
}
複製代碼
二、接着在app目錄的build.gradle添加依賴:bash
dependencies {
implementation 'com.bytedance.ies.ugc.aweme:open-sdk:0.0.1.3'
}
複製代碼
別忘了在manifest添加權限並處理,最後同步項目微信
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
複製代碼
一、在Application中,onCreate方法下初始化TikTokOpenApiFactoryapp
String clientkey = "xxx"; // 到開發者網站申請並替換
TikTokOpenApiFactory.init(new TikTokOpenConfig(clientkey));
複製代碼
二、分享視頻maven
//視頻文件路徑
private ArrayList<String> mUri = new ArrayList<>();
mUri.add("xxx.video-path");
// 初始化api,須要傳入targetApp
TiktokOpenApi tiktokOpenApi =
TikTokOpenApiFactory.create(this, TikTokConstants.TARGET_APP.AWEME);
// 初始化Share
Share.Request request = new Share.Request();
TikTokVideoObject videoObject = new TikTokVideoObject();
videoObject.mVideoPaths = mUri;
TikTokMediaContent content = new TikTokMediaContent();
content.mMediaObject = videoObject;
request.mMediaContent = content;
//配置完成後,調用share方法喚起抖音app
tiktokOpenApi.share(request);
複製代碼
三、接收回調ide
兩種方式接收回調信息:測試
(1)在包名下建立.tiktokapi.TikTokEntryActivity,初始化TTOpenApi,實現 TikTokApiEventHandler接口,在onResp方法中回調結果。(和微信回調相似)
(2)自定義接收回調全路徑,好比須要回調的activity路徑爲:
com.douyin.share.TikTokEntryActivity
複製代碼
則在前面傳分享參數時指定回調全路徑:
request.callerLocalEntry = com.douyin.share.TikTokEntryActivity
複製代碼
回調activity實現TikTokApiEventHandler接口,並在manifest中註冊activity,添加android:exported="true",而後在onResp方法接收回調:
public void onResp(BaseResp resp) {
if (resp.getType() == TikTokConstants.ModeType.SHARE_CONTENT_TO_TT_RESP) {
switch (resp.errorCode){
case TikTokConstants.BaseErrorCode.OK:
Toast.makeText(this, "分享成功",Toast.LENGTH_SHORT).show();
break;
case TikTokConstants.BaseErrorCode.ERROR_UNKNOW:
Toast.makeText(this, "未知錯誤",Toast.LENGTH_SHORT).show();
break;
case TikTokConstants.BaseErrorCode.ERROR_CANCEL:
Toast.makeText(this, "取消分享",Toast.LENGTH_SHORT).show();
break;
}
}
finish();
}
複製代碼
OK!至此咱們就能夠接收分享回調了!心情別提有多愉快!! 來看看效果:
public void onResp(BaseResp resp) {
if (resp.getType() == TikTokConstants.ModeType.SHARE_CONTENT_TO_TT_RESP) {
……
//添加這行代碼
startActivity(new Intent(this, MainActivity.class));
}
finish();
}
複製代碼
改完後咱們再來跑一遍:
我繼續按返回鍵操做:
這就坑了,文檔不是說啓動本身app的類就能回到本身app的棧嗎?我好奇的打開了手機任務棧,發現:
咱們來捋一捋這些場景,並結合官方文檔來分析。文檔描述,tiktok回調這個類是經過singleInstance的,即抖音回調activity的時候,是經過singleInstance啓動TikTokEntryActivity的,這個時候的TikTokEntryActivity運行在獨立的任務棧裏,屬於前臺任務;當調用到TikTokEntryActivity的onResp方法,執行到startActivity(new Intent(this,MainActivity.class)),啓動MainActivity並finish本身,這個時候抖音的任務棧屬於前臺任務棧,那麼天然而然的,新啓動的MainActivity就依附在抖音的任務棧上。接着再按返回鍵,退出了抖音的任務棧,最後纔回到本身app的任務棧。
OK!知道了緣由,對應的解決方案也就有了。在TikTokEntryActivity調用finish後,咱們只須要將MainActivity拉回本身app的任務棧,那麼不就能夠搞定了嗎?
想法是好,可是還會有兩個問題:
(1)如何將MainActivity拉回本身app的任務棧?
(2)接收回調後,不必定是跳轉到MainActivity,而是怎麼回到啓動分享的那個activity?
第一個問題好解決,把MainActivity的啓動模式設置爲singleTask就好了; 第二個問題,怎麼回到啓動分享的那個activity?好比一個實際的場景,A是根activity,A能夠啓動B或者啓動C,而後B和C均可以喚起抖音分享,那麼分享後回到哪一個activity得知道,也就是須要知道棧頂activity。就跟喚起微信,取消分享的場景同樣(不知道抖音爲何不作成和微信同樣的處理方式,還須要開發者額外處理)。
把問題1和2結合起來就是: 接收回調後,如何跳轉到啓動分享的那個activity?(即本身app棧的棧頂activity)。
具體怎麼作?搜索了一番,發現shareSDK是支持抖音分享的,能夠扒它們抖音SDK模塊的jar包看看是怎麼處理的? 下載shareSDK官方demo,用Android Studio打開後,在依賴包目錄下找到了關於抖音模塊的代碼:
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP
複製代碼
找到辦法後我欣喜若狂,趕忙參照該方法處理。發現能夠跳轉到本身app,可是有時候會失效!後來還下載了shareSDK的apk測試,也發現偶爾會有失效的問題。看來這個辦法不夠完美,只能繼續尋找方案。
……
而後,在抖音開放平臺官網發現,輕顏相機是目前市面上集成了抖音SDK的app,我趕忙下載測試:
public int c(d paramd) {
……
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(this.mActivity.getPackageName());
stringBuilder.append(".wttsharesdk.WttShareActivity");
String str = stringBuilder.toString();
ComponentName componentName =
new ComponentName(this.mActivity.getPackageName(), str);
Intent intent = new Intent();
intent.setComponent(componentName);
this.mActivity.startActivity(intent);
……
}
複製代碼
邏輯是使用StringBuilder拼接activity路徑,而後經過ComponentName隱式啓動startActivity,回到本身的app。
至此,咱們來整理下思路,首先咱們能夠獲取到本身app棧頂activity(這個activity必須是singleTask模式),拿到ComponentName,再經過隱式Intent跳轉,不就能回到本身app任務棧了嗎?
開搞,代碼實現:
……
private String getTopClassName(){
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfos = manager.getRunningTasks(1);
if (taskInfos != null && taskInfos.size() != 0){
ComponentName componentName = taskInfos.get(0).topActivity;
//拿到棧頂的activity className
return componentName.getClassName();
}
return "";
}
private void openComponent(){
String className = getTopClassName();
if (!className.isEmpty()){
ComponentName componentName =
new ComponentName(getPackageName(),className);
Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
}
}
……
複製代碼
在onResp()裏調用openComponent()
public void onResp(BaseResp resp) {
if (resp.getType() == TikTokConstants.ModeType.SHARE_CONTENT_TO_TT_RESP) {
……
openComponent();
}
finish();
}
複製代碼
注意棧頂activity須要設置launchMode="singleTask",至於爲何,稍後解釋
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
</activity>
複製代碼
咱們來看看修改後的效果:
(1)app棧頂activityB喚起抖音分享,啓動模式爲singleTask;
(2)分享結束後,抖音啓動TikTokEntryActivity,啓動模式爲singleInstance,回調onResp;
(3)TikTokEntryActivity調用finish,並經過Component啓動棧頂的activityB,因爲activityB已存在實例,系統重用該實例並調到棧頂,將任務棧拉回前臺。
至此,總體看下來,主要仍是考察對activity啓動模式的理解程度,以及反編譯的一些相關知識,雖然平時接觸很少,可是當真正遇到問題的時候,咱們有了思路,纔會體現出本身肚子裏有多少墨水,從容應對。