抖音接入避雷指南,你值得拥有!

640?wx_fmt=jpeg


/   今日科技快讯   /


昨日,美国太空探索技术公司SpaceX首席执行官埃隆·马斯克开始介绍其星际飞船项目取得的最新进展以及未来计划。星际飞船是一种大型航天器,旨在将人们送往月球、火星等太空目的地。星际飞船的概念在过去几年中已经多次改变,现在马斯克计划揭示其最新蓝图。


/   作者简介   /


大家早上好,明天就是国庆长假了,本着非工作日不发文的原则,明天起本公众号也会进行一段时间的休息。这里祝大家国庆节快乐,同时也祝祖国繁荣昌盛,我们节后再见!


本篇文章来自海王星0908的投稿,分享了他对接入抖音过程遇到的一些问题的总结,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。


海王星0908的博客地址:

https://blog.csdn.net/magic0908


/   前言   /


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


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


/   正文   /


导入依赖


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


 
  

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


接着在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" />


集成抖音分享


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


 
  

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


分享视频


 
  

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


接收回调


两种方式接收回调信息:


  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!至此我们就可以接收分享回调了!心情别提有多愉快!!来看看效果:


640?wx_fmt=gif


what!我取消分享后,虽然弹出了Toast,但是并没有回到我们的app,而是留在抖音。这就坑了!微信取消分享后都可以回到app,但是抖音就不行。估计是我哪里配置不对,去扒官方文档,在FQA里发现了这样一段话:


640?wx_fmt=png


就是说,抖音在回调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();
}


我们再来跑一遍:


640?wx_fmt=gif


没毛病,好像是成功了!?嗯?有点怪,页面启动分享的按钮怎么不见了!我继续按返回键操作:


640?wx_fmt=gif


what!按下返回键后,又回到了抖音主界面,再接着按返回键,才回到我们的app(有启动分享的按钮)。这就坑了,文档不是说启动自己app的类就能回到自己app的栈吗?我好奇的打开了手机任务栈,发现:


640?wx_fmt=png


坑!怎么我自己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找线索


具体怎么做?搜索了一番,发现shareSDK是支持抖音分享的,可以扒它们抖音SDK模块的jar包看看是怎么处理的?下载shareSDK官方demo,用Android Studio打开后,在依赖包目录下找到了关于抖音模块的代码。


640?wx_fmt=png


DouYinHandlerActivity,没错,就是这个类,其中有一个方法引起了我的注意:


640?wx_fmt=png


很明显,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测试,也发现偶尔会有失效的问题。看来这个办法不够完美,只能继续寻找方案。


从竞品找线索


然后,在抖音开放平台官网发现,轻颜相机是目前市面上集成了抖音SDK的app,我赶紧下载测试:


640?wx_fmt=gif


可以看到,轻颜相机是可以回到自己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>


我们来看看修改后的效果:


640?wx_fmt=gif


可以看到,分享后按返回键正常回到了自己的app,继续返回,退出app任务栈;接着回到抖音的任务栈,再返回,最后回到桌面,具体流程如下图:


640?wx_fmt=png


大概分三步:


  1. app栈顶activityB唤起抖音分享,启动模式为singleTask;

  2. 分享结束后,抖音启动TikTokEntryActivity,启动模式为singleInstance,回调onResp;

  3. TikTokEntryActivity调用finish,并通过Component启动栈顶的activityB,由于activityB已存在实例,系统重用该实例并调到栈顶,将任务栈拉回前台。


/   总结   /


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


推荐阅读:





欢迎关注我的公众号

学习技术或投稿


640.png?


640?wx_fmt=jpeg

长按上图,识别图中二维码即可关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值