Android 解决新浪分享之后回调出现两个icon进行选择

目录

问题起源

第一次尝试

源码分析

1.实例化WbShareHandler

2.发送消息

3.处理发送到微博SDK上的消息

4.另外一个icon

第二次尝试

总结


问题起源

这几天翻看了项目中以前添加的新浪分享功能,发现有个问题是虽然添加了WbShareCallback,但是并没有真正的实现回调,而只是放了代码而已,所以就想着把新浪分享之后的回调给加进去。结果就开始各种踩坑。

第一次尝试

由于项目中并不是一个页面在调用新浪分享的功能,所以在每个Activity中添加

<intent-filter>
    <action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY"/>
    <category android:name="android.intent.category.DEFAULT"/>
 </intent-filter>

必然无法解决问题。首先多个Activity注册该action,肯定在进行新浪分享结果处理完回调之后,会出现多个icon供选择,所以就想到了是不是可以将回调的逻辑写到一个空的Activity中,这样子就可以回调到该Activity,所以就有了如下代码:

public class SinaEntryActivity extends Activity implements WbShareCallback {
//......省略代码
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (wbShareHandler == null) {
            finish();
            return;
        }
        wbShareHandler.doResultIntent(intent, this);
    }

    @Override
    public void onWbShareSuccess() {     
    }

    @Override
    public void onWbShareCancel() {
    }

    @Override
    public void onWbShareFail() {     
    }
}

这样子的确是可以回调成功,但是就是遇到了分享成功、取消或者失败之后,回调到该SinaEntryActivity的时候,就会从底部弹出一个对话框,有两个icon的入口,提示点击进入?

为什么会出现这种问题呢?我搜索了全局也只有这一个Activity注册了该Action,理论上应该只有这一个Activity,是时候去查看下源码了。

源码分析

1.实例化WbShareHandler

        WbSdk.install(getApplicationContext(), new AuthInfo(getApplicationContext(), appkey, redirectUrl, ""));
        wbShareHandler = new WbShareHandler(activity);
        wbShareHandler.registerApp();

不做过多解释

2.发送消息

   wbShareHandler.shareMessage(weiboMultiMessage, false);

主要就是将要分享的信息发送给微博的API。主要进入源码看下


    public void shareMessage(WeiboMultiMessage message, boolean clientOnly) {
        if (!this.hasRegister) {
            throw new RuntimeException("please call WbShareHandler.registerApp(),before use share function");
        } else if (WbSdk.isWbInstall(this.context) || !clientOnly) {
            if (!clientOnly && !WbSdk.isWbInstall(this.context)) {
                this.startWebShare(message);
            } else {
                this.startClientShare(message);
            }

        }
    }

进入到startClientShare()

 private void startClientShare(WeiboMultiMessage message) {
//...省略代码
        Intent intent = new Intent();
        intent.setClass(this.context, WbShareTransActivity.class);
        intent.putExtra("startPackage", WeiboAppManager.getInstance(this.context).getWbAppInfo().getPackageName());
        intent.putExtra("startAction", "com.sina.weibo.sdk.action.ACTION_WEIBO_ACTIVITY");
        intent.putExtra("startFlag", 0);
        intent.putExtra("startActivity", this.context.getClass().getName());
        intent.putExtra("progressColor", this.progressColor);
        intent.putExtra("progressId", this.progressId);
        if (data != null) {
            intent.putExtras(data);
        }
        try {
            this.context.startActivity(intent);
        } catch (Exception var5) {
            LogUtil.v("weibo sdk error ", var5.toString());
        }

    }

从源码中可以看出主要就是封装了Bundle,去启动了WbShareTransActivity这个Activity。主要看下里面几个主要的关键字

"startPackage"将内置SDK的包名传入到WbShareTransActivity
"startAction""com.sina.weibo.sdk.action.ACTION_WEIBO_ACTIVITY"传入到WbShareTransActivity
"startActivity"就是将调用该发送分享消息的Activity也传入了WbShareTransActivity

 

主要看下上述几个关键字怎么在WbShareTransActivity中发挥作用的。

3.处理发送到微博SDK上的消息

主要进入到WbShareTransActivity查看下源码:

  • 1)onCreate()
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.initView();
        this.startActivityName = this.getIntent().getStringExtra("startActivity");
        if (savedInstanceState != null) {
            this.startActivityName = savedInstanceState.getString("startActivity");
            this.flag = savedInstanceState.getBoolean("resultDataFlag", false);
        } else {
            this.checkSource();
        }
    }

主要就是从Bundle里面获取"startActivity"对应的类名,在本实例中就是定义的SinaEntryActivity。

  • 2)initView()

主要根据Bundle中设置的进度条的颜色和id,即开发者即可以设置SDK中的进度条的样式,也可以调用自己定义的进度条。

 private void initView() {
        this.progressColor = this.getIntent().getIntExtra("progressColor", -1);
        this.progressId = this.getIntent().getIntExtra("progressId", -1);
        this.rootLayout = new FrameLayout(this);
        if (this.progressId != -1) {
            LayoutInflater inflater = (LayoutInflater)this.getSystemService("layout_inflater");

            try {
                this.progressBar = inflater.inflate(this.progressId, (ViewGroup)null);
            } catch (Exception var3) {
                this.progressBar = new WbSdkProgressBar(this);
            }
        } else {
            this.progressBar = new WbSdkProgressBar(this);
            if (this.progressColor != -1) {
                ((WbSdkProgressBar)this.progressBar).setProgressColor(this.progressColor);
            }
        }

        LayoutParams params = new LayoutParams(-2, -2);
        params.gravity = 17;
        this.rootLayout.addView(this.progressBar, params);
        this.rootLayout.setBackgroundColor(855638016);
    }

返回到WbShareHandler中可以看到,提供下面两个方法来设置对应的参数

    public void setProgressColor(int color) {
        this.progressColor = color;
    }

    public void setProgressId(int id) {
        this.progressId = id;
    }
  • 3)进行SDK调用分享

刚进来的时候savedInstanceState的时候为null,所以进入到else的流程中,即调用到checkSource()

    private void checkSource() {
        Bundle bundle = this.getIntent().getExtras();
        WeiboMultiMessage multiMessage = new WeiboMultiMessage();
        multiMessage.toObject(bundle);
        this.transPicAndVideoResource(multiMessage);
    }

跟进到transPicAndVideoResource()中可以看到,跟进分享的信息是如果是多张图片或者video的话,就走else,如果不是这两者的就直接调用到this.gotoWeiboComposer(multiMessage)。

    private void transPicAndVideoResource(WeiboMultiMessage multiMessage) {
        this.setContentView(this.rootLayout);
        if (multiMessage.multiImageObject == null && multiMessage.videoSourceObject == null) {
            this.gotoWeiboComposer(multiMessage);
        } else {
            this.setContentView(this.rootLayout);
            if (this.copyResourceTask != null) {
                this.copyResourceTask.cancel(true);
            }

            this.copyResourceTask = new WbShareTransActivity.CopyResourceTask(null);
            WeiboMultiMessage[] messages = new WeiboMultiMessage[]{multiMessage};
            this.copyResourceTask.execute(messages);
        }

    }

(a)分享非多张图片或者video

从下面的源码中可以看到直接调用gotoWeiboComposer(),封装Intent来打开不同的Activity。

 private void gotoWeiboComposer(WeiboMultiMessage weiboMultiMessage) {
        Intent intent = this.getIntent();
        this.flag = true;
        intent.putExtra("startFlag", -1);
        Intent shareIntent = new Intent("com.sina.weibo.sdk.action.ACTION_WEIBO_ACTIVITY");
        shareIntent.setPackage(intent.getStringExtra("startPackage"));
//....省略封装的Intent对应的字段
        try {
//如果gotoActivity不为空的话,就进入到对应的Activity下
            if (!TextUtils.isEmpty(intent.getStringExtra("gotoActivity"))) {
                shareIntent.setClassName(this, intent.getStringExtra("gotoActivity"));
                this.startActivity(shareIntent);
//如果安装了微博的客户端,则进入到对应action为com.sina.weibo.sdk.action.ACTION_WEIBO_ACTIVITY的微博页面中
            } else if (WbSdk.isWbInstall(this)) {
                this.startActivityForResult(shareIntent, 765);
            } else {
//否则直接回调
                this.sendCallback(2);
            }
        } catch (Exception var10) {
           //....省略代码
        }

    }

(1)如果intent里的"gotoActivity"对应的类名不为空,则进入到对应的类名下面,而该关键字对应的是在WebShareHanderl中如果没有安装新浪的客户端的时候,直接调用到shareWebShare()时进行封装的,源码如下:

private void startWebShare(WeiboMultiMessage message) {
        Intent webIntent = new Intent(this.context, WbShareTransActivity.class);
     //。。。。省略代码
        webIntent.putExtra("gotoActivity", "com.sina.weibo.sdk.web.WeiboSdkWebActivity");
        this.context.startActivity(webIntent);
    }

可以看出对应的为WeiboSdkWebActivity,其实该类已经封装到jar包中,通过Webview加载了Sina的H5页面。

(2)如果安装了微博的客户端,则直接进入到微博的对应该action的com.sina.weibo.sdk.action.ACTION_WEIBO_ACTIVITY的Activity中,该Activity处理完逻辑之后就回调到WbShareTransActivity的onActivityResult()中。

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (this.handler != null) {
            this.handler.sendEmptyMessageDelayed(0, 100L);
        }
  }
  private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            WbShareTransActivity.this.sendCallback(1);
        }
    };

最终调用sendCallback(1);

    private void sendCallback(int resultCode) {
        if (this.rootLayout != null) {
            this.rootLayout.setVisibility(8);
        }
        try {
            Intent resultIntent = new Intent();
            Bundle bundle = new Bundle();
            bundle.putInt("_weibo_resp_errcode", resultCode);
            resultIntent.putExtras(bundle);
            resultIntent.setFlags(131072);
            resultIntent.setClassName(this, this.startActivityName);
            this.startActivity(resultIntent);
        } catch (Exception var4) {
            ;
        }
        this.finish();
    }

从源码中可以看出,其实就是重新start之前调用该API的那个Activity,即 this.startActivityName,也就是之前在弹出那个对话框中之所有有一个icon的原因所在。

注意:这里有一点,这里在启动startActivityName这个Activity的时候给Intent设置了一个Flag,我觉得这个Flag应该对应的Activity的启动模式就是类似于SingleTask,否则会影响到startActivityName的,不会重新创建startActivityName这个Acitivity实例,而是直接从onNewIntent(),也就是为什么需要在onNewIntent()中需要进行调用wbShareHandler.doResultIntent(intent, this);

(b)分享多张图片或者Video

运行CopyResourceTask这个异步线程,会在子线程中对图片或者video进行处理,然后在发送给微博处理分享的SDK,同样处理完之后也会走到gotoWeiboComposer(),同(a)。

4.另外一个icon

  • 1)安装新浪客户端

应该是跳转到的微信客户端的对应该action的com.sina.weibo.sdk.action.ACTION_WEIBO_ACTIVITY的Activity中,在关闭新浪客户单的Activity的时候,发出的该com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY

  • 2)没有安装新浪客户端

由于跳转到的是该jar包对应的WeiboSdkWebActivity这个Activity中,在点击左上角的关闭按钮

        this.leftBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                WeiboSdkWebActivity.this.webViewClient.closeWeb();
                WeiboSdkWebActivity.this.closeActivity();
            }
        });

或者完成分享操作之后,调用到webviewClient中对应的方法。进入到 ShareWebViewClient中可以看到

(a)完成分享操作
主要就是WebView的监听事件来完成对应的分享成功、失败和取消的事件

    @TargetApi(24)
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        return this.needOverLoad(request.getUrl().toString());
    }

    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (this.requestCallback != null) {
            this.requestCallback.shouldOverrideUrlLoadingCallBack(view, url);
        }

        return this.needOverLoad(url);
    }

最终调用到needOverLoad(String url),进入源码中可以看到会根据不同的errorCode来调用不同的代码来实现发送com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY

private boolean needOverLoad(String url) {
        if (url.startsWith("sinaweibo://browser/close")) {
            Bundle bundle = WbUtils.parseUri(url);
            String errCode;
            if (this.param.getBaseData() != null && !TextUtils.isEmpty(this.param.getBaseData().getCallback())) {
                errCode = this.param.getBaseData().getCallback();
      //。。。省略代码

            errCode = bundle.getString("code");
            String errMsg = bundle.getString("msg");
//向调用者发送com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY
            if (TextUtils.isEmpty(errCode)) {
                this.sendSdkCancleResponse(this.activity);
            } else if (!"0".equals(errCode)) {
                this.sendSdkErrorResponse(this.activity, errMsg);
            } else {
                this.sendSdkOkResponse(this.activity);
            }

            if (this.requestCallback != null) {
                this.requestCallback.closePage();
            }

            return true;
        } else {
            return false;
        }
    }

最终调用到sendSdkResponse()发出com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY,然后匹配到我们的APP的注册的action

private void sendSdkResponse(Activity activity, int errCode, String errMsg) {
        Bundle bundle = activity.getIntent().getExtras();
        if (bundle != null && !this.hasCallbacked) {
            Intent intent = new Intent("com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY");
//。。。省略代码

            try {
                activity.startActivityForResult(intent, 765);
            } catch (ActivityNotFoundException var8) {
                ;
            }
            this.hasCallbacked = true;
        }
    }

同样 点击左边的关闭按钮也是对应着该sendSdkResponse()。

综上,所以当APP中注册com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY的时候会出现两个icon。

第二次尝试

显然带着两个icon这种体验非常不好,所以怎么解决这种问题呢?

还是新浪的源码启发了我,WbShareTransActivity这个Activity的处理方式真的好微妙,用一个Activity起到了承前启后的作用,所以我就想着能不能把这新浪分享的调用和回调都写到一个Activity中,不在注册com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY该action,因为微信SDK肯定会重新启动调用分享API的那个Activity,回调之后直接在该Activity写逻辑岂不是一件很完美的事情。

就有了如下的代码:

public class SinaEntryActivity extends Activity implements WbShareCallback {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        installWB();
        initBundleFromIntent();
    }

    /**
     * 从Bundle中获取分享的内容
     */
    private void initBundleFromIntent() {
        Bundle bundle = getIntent().getExtras();
        if (bundle == null) {
            return;
        }
        url = bundle.getString("url");
        title = bundle.getString("title");
        text = bundle.getString("text");
        imageUrl = bundle.getString("imageUrl");  
        //调用分享图片的方法 
        shareImg2WB();      
    }

    /**
     * 初始化sina的API
     */
    private void installWB() {
        WbSdk.install(getApplicationContext(), new AuthInfo(getApplicationContext(), appkey, redirectUrl, ""));
        wbShareHandler = new WbShareHandler(activity);
        wbShareHandler.registerApp();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (wbShareHandler == null) {
            finish();
            return;
        }
        wbShareHandler.doResultIntent(intent, this);
    }

    @Override
    public void onWbShareSuccess() {
        //.......添加逻辑代码
        finish();
    }

    @Override
    public void onWbShareCancel() {
        //.......添加逻辑代码
        finish();
    }

    @Override
    public void onWbShareFail() {
              //.......添加逻辑代码
        finish();
    }

    /**
     * 微博分享图片。
     */
    private void shareImg2WB() {
      //。。。。省略代码分享的图片的代码
    }
}

最后在封装的Library的AndrodiManifest.xml文件中注册该Activity即可

        <activity
            android:name=".SinaEntryActivity"
            android:launchMode="singleTask"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

 

采用一个透明的Activity来发送消息和接收回调,不需要在页面的中单独处理回调。当需要调用微博分享功能的时候,只要start该Activity即可。 

总结

1)新浪在处理完分享结果之后,会重新打开调用分享的那个Activity

2)新浪在处理完分享结果之后,会发出打开注册com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY这个action的Activity

3)可以使用一个透明的Activity来巧妙的处理一些逻辑,解决需要在所有Acitivity里面需要处理的逻辑。

看别人的源码,真的是一件很开心的事情,可以学到一些技巧。

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值