Android接入抖音分享踩坑之旅

前言

抖音作为日活量过亿的产品,在今年年初,也终于上线了抖音开放平台,目前支持app接入登录与分享。app通过抖音授权获取用户信息;分享视频并进行处理,提高app在抖音的曝光度。

刚好项目有个新需求,需要集成抖音登录与分享。抖音开发者文档
本以为不就是接个SDK嘛,湿湿水啦!
但是bug总与我相伴!且听我慢慢道来。

导入依赖

1、在项目根目录build.gradle里添加maven:

allprojects {
    repositories {
        ……
        maven { url 'https://dl.bintray.com/aweme-open-sdk-team/public' }
    }
}

2、接着在app目录的build.gradle添加依赖:

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" />

集成抖音分享

1、在Application中,onCreate方法下初始化TikTokOpenApiFactory

String clientkey = "xxx"; // 到开发者网站申请并替换
TikTokOpenApiFactory.init(new TikTokOpenConfig(clientkey));

2、分享视频

//视频文件路径
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);

3、接收回调
两种方式接收回调信息:
(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!至此我们就可以接收分享回调了!心情别提有多愉快!!
来看看效果:
在这里插入图片描述
what!我取消分享后,虽然弹出了Toast,但是并没有回到我们的app,而是留在抖音。这就坑了!微信取消分享后都可以回到app,但是抖音就不行。估计是我哪里配置不对,去扒官方文档,在FQA里发现了这样一段话:
在这里插入图片描述
就是说,抖音在回调activity的时候,这个类是通过singleInstance启动的,如果想回到应用,也有办法,注意画红线的部分,“启动自己app的类跳回自己app的栈”,我将信将疑的照做了,在onResp方法启动MainActivity

public void onResp(BaseResp resp) {
     if (resp.getType() == TikTokConstants.ModeType.SHARE_CONTENT_TO_TT_RESP) {
         ……
         //添加这行代码
         startActivity(new Intent(this, MainActivity.class));
     }
     finish();
}

我们再来跑一遍:

在这里插入图片描述
没毛病,好像是成功了!?嗯?有点怪,页面启动分享的按钮怎么不见了!
我继续按返回键操作:
在这里插入图片描述
what!按下返回键后,又回到了抖音主界面,再接着按返回键,才回到我们的app(有启动分享的按钮)。
这就坑了,文档不是说启动自己app的类就能回到自己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)

(1)从shareSDK找线索

具体怎么做?搜索了一番,发现shareSDK是支持抖音分享的,可以扒它们抖音SDK模块的jar包看看是怎么处理的?
下载shareSDK官方demo,用Android Studio打开后,在依赖包目录下找到了关于抖音模块的代码
在这里插入图片描述
DouYinHandlerActivity,没错,就是这个类,其中有一个方法引起了我的注意:
在这里插入图片描述
很明显,shareSDK的处理是在onDestroy方法,创建Intent,并通过隐式启动来跳转到自己app的任务栈。action的值表示需要在manifest对应的activity去添加,flags被混淆成了数字,反编译后发现是FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP,对应

Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP

找到办法后我欣喜若狂,赶紧参照该方法处理。发现可以跳转到自己app,但是有时候会失效!后来还下载了shareSDK的apk测试,也发现偶尔会有失效的问题。
看来这个办法不够完美,只能继续寻找方案。
……

(2)从竞品找线索

然后,在抖音开放平台官网发现,轻颜相机是目前市面上集成了抖音SDK的app,我赶紧下载测试:
在这里插入图片描述
可以看到,轻颜相机是可以回到自己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>

我们来看看修改后的效果:
在这里插入图片描述
可以看到,分享后按返回键正常回到了自己的app,继续返回,退出app任务栈;接着回到抖音的任务栈,再返回,最后回到桌面,具体流程如下图:
在这里插入图片描述
大概分三步:
(1)app栈顶activityB唤起抖音分享,启动模式为singleTask;
(2)分享结束后,抖音启动TikTokEntryActivity,启动模式为singleInstance,回调onResp;
(3)TikTokEntryActivity调用finish,并通过Component启动栈顶的activityB,由于activityB已存在实例,系统重用该实例并调到栈顶,将任务栈拉回前台。

总结

至此,整体看下来,主要还是对activity启动模式的理解程度,以及反编译的一些相关知识,虽然平时接触不多,但是当真正遇到问题的时候,我们有了思路,才会体现出自己肚子里有多少墨水,从容应对。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值