Android集成微信、QQ、微博等第三方登录和分享

公司项目需求,需要增加第三方登录,这里先介绍微信,其他的大同小异。
思路很简单:
第一,统一一个入口,定义规范一些方法和回调。
第二,根据不同的第三方平台,建立各自的管理中心,负责对应平台的具体逻辑。
第三,利用类型参数,把第一和第二部关联起来。
建立统一入口:

public class ShareAndLoginManager {
    private final String TAG = "ShareAndLoginManager";

    public interface ShareListener {
        void onShareSuccess(ShareType type);

        void onShareFailed(ShareType type, int code, String message);

        void onShareCancel(ShareType type, int requestCode, int resultCode);
    }

    public interface LoginListener {
        void onLoginSuccess(LoginType type, String name, String headUrl, int sex, String code);

        void onLoginFailed(LoginType type, int code, String message);

        void onLoginCancel(LoginType type, int requestCode, int resultCode);

        void onLoginDenied(LoginType type);
    }

    public enum LoginType {
        kLoginTypeWeChat,
    }

    public enum ShareType {
        kShareTypeSystem,
        kShareTypeWeChat,
        kShareTypeWeChatTimeline,
        kShareTypeWeChatFriends,
    }

    private ShareType mCurrentShareType;

    private static ShareAndLoginManager _instance = null;

    public static synchronized ShareAndLoginManager getInstance() {
        if (null == _instance) _instance = new ShareAndLoginManager();
        return _instance;
    }

    private ShareListener mListener = null;
    private LoginListener mLoginListener = null;

    public void loginByThirdParty(Activity activity, LoginType type, @Nullable LoginListener listener) {
        this.mLoginListener = listener;
        switch (type) {
            case kLoginTypeWeChat: {
                WechatInstanceManager.Companion.getInstance().loginByWx(activity);
            }
            break;
        }
    }

    public void shareImage(Activity activity, ShareType type, Object object, @Nullable ShareListener listener) {
        this.mListener = listener;
        this.mCurrentShareType = type;
        switch (type) {
            case kShareTypeWeChatFriends: {
                if (object instanceof Bitmap) {
                    Bitmap bitmap = (Bitmap) object;
                    WechatInstanceManager.Companion.getInstance().shareImageToWx(false, activity, bitmap);
                }
            }
            break;
            case kShareTypeWeChatTimeline: {
                if (object instanceof Bitmap) {
                    Bitmap bitmap = (Bitmap) object;
                    WechatInstanceManager.Companion.getInstance().shareImageToWx(true, activity, bitmap);
                }
            }
            break;
        }
    }

    public void shareWeb(Activity activity, ShareType type, String title, String content, String iconUrl,
                         Bitmap iconBitmap, String webUrl, @Nullable ShareListener listener) {
        this.mListener = listener;
        this.mCurrentShareType = type;
        switch (type) {
            case kShareTypeWeChatFriends: {
                WechatInstanceManager.Companion.getInstance().shareWebToWx(false, activity, title, content, iconBitmap, webUrl);
            }
            break;
            case kShareTypeWeChatTimeline: {
                WechatInstanceManager.Companion.getInstance().shareWebToWx(true, activity, title, content, iconBitmap, webUrl);
            }
            break;
            case kShareTypeSystem: {
                shareWebToSystem(activity, title, webUrl, 0);
            }
            break;
        }
    }

    private void shareWebToSystem(Activity activity, String title, String webUrl, int requestCode) {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, title + webUrl);//注意:这里只是分享文本内容
        sendIntent.setType("text/plain");
        activity.startActivityForResult(sendIntent, requestCode);
    }

    public void onShareSuccess(ShareType type) {
        if (null != this.mListener) {
            this.mListener.onShareSuccess(type);
        }
    }

    public void onShareCancel(ShareType type, int requestCode, int resultCode) {
        if (null != this.mListener) {
            this.mListener.onShareCancel(type, requestCode, resultCode);
        }
    }

    public void onShareFailed(ShareType type, int code, String message) {
        if (null != this.mListener) {
            this.mListener.onShareFailed(type, code, message);
        }
    }

    public void onLoginSuccess(LoginType type, String name, String headUrl, int sex, String code) {
        if (null != this.mLoginListener) {
            this.mLoginListener.onLoginSuccess(type, name, headUrl, sex, code);
        }
    }

    public void onLoginCancel(LoginType type, int requestCode, int resultCode) {
        if (null != this.mLoginListener) {
            this.mLoginListener.onLoginCancel(type, requestCode, resultCode);
        }
    }

    public void onLoginFailed(LoginType type, int code, String message) {
        if (null != this.mLoginListener) {
            this.mLoginListener.onLoginFailed(type, code, message);
        }
    }

    public void onLoginDenied(LoginType type) {
        if (null != this.mLoginListener) {
            this.mLoginListener.onLoginDenied(type);
        }
    }

    public void onActivityResult(Activity activity, final int requestCode, final int resultCode, Intent data) {

    }
}

建立微信的处理中心:

class WechatInstanceManager private constructor() {
    private val TAG = "WechatInstanceManager"

    companion object {
        val instance = InstanceHolder.holder
        private var iwxapi: IWXAPI? = null

        fun getWechatApi(context: Context): IWXAPI {
            if (iwxapi == null) {
                iwxapi = WXAPIFactory.createWXAPI(context, null)
                iwxapi!!.registerApp(Config.WECHAT_APP_ID)
            }
            return iwxapi!!
        }
    }


    fun loginByWx(activity: Activity) {
        val iwxapi = getWechatApi(activity)
        if (iwxapi.isWXAppInstalled) {
            val request = SendAuth.Req()
            request.scope = "snsapi_userinfo"
            request.state = "wechat_login"
            iwxapi.sendReq(request)
        } else {
            ToastUtil.showToast(R.string.no_install_app, ToastUtil.LENGTH_SHORT)
        }
    }


    fun shareImageToWx(isTimeline: Boolean, activity: Activity, bitmap: Bitmap) {
        val iwxapi = getWechatApi(activity)
        if (iwxapi.isWXAppInstalled) {
            val imageObject = WXImageObject(bitmap)
            val message = WXMediaMessage()
            message.mediaObject = imageObject
            val request = SendMessageToWX.Req()
            request.transaction = buildWxTransaction("img")
            request.message = message
            request.scene =
                if (isTimeline) SendMessageToWX.Req.WXSceneTimeline else SendMessageToWX.Req.WXSceneSession
            val sharedResult = iwxapi.sendReq(request)
            Log.d(TAG, "result=$sharedResult")
        } else {
            ToastUtil.showToast(R.string.no_install_app, ToastUtil.LENGTH_SHORT)
        }
    }

    fun shareWebToWx(
        isTimeLine: Boolean,
        activity: Activity,
        title: String,
        content: String,
        iconBitmap: Bitmap,
        webUrl: String
    ) {
    }

    private fun buildWxTransaction(type: String?): String? {
        return if (type == null) System.currentTimeMillis()
            .toString() else type + System.currentTimeMillis()
    }

    private object InstanceHolder {
        val holder = WechatInstanceManager()
    }
}

微信结果的返回处理:

class WXEntryActivity : WeChatHandleActivity(), IWXAPIEventHandler {

    private var api: IWXAPI? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        api = getWechatApi(this);
        try {
            api?.handleIntent(intent, this)
        } catch (e: Exception) {

        }
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        setIntent(intent)
    }

    override fun onReq(req: BaseReq) {

    }

    override fun onResp(resp: BaseResp) {
        if (resp.type == ConstantsAPI.COMMAND_SENDAUTH) {
            when (resp.errCode) {
                BaseResp.ErrCode.ERR_OK -> {
                    if (resp.type == ConstantsAPI.COMMAND_SENDAUTH) {
                        val authResp: SendAuth.Resp = resp as SendAuth.Resp
                        val code: String = authResp.code
//                        getAccessToken(code)
                        ShareAndLoginManager.getInstance().onLoginSuccess(ShareAndLoginManager.LoginType.kLoginTypeWeChat,
                            "",
                            "",
                            0,
                            code)
                    }
                }
            }
        }
        finish()
    }


    private fun getAccessToken(code: String) {
        //这个接口需用get请求
        val path =
            ("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + Config.WECHAT_APP_ID + "&secret="
                    + Config.WECHAT_APP_SECRET + "&code=" + code + "&grant_type=authorization_code")
        val client = OkHttpClient()
        val request = Request.Builder()
            .url(path)
            .build()
        val call = client.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                finish()
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                if (null != response.cacheResponse()) {
                    val str = response.cacheResponse().toString()
                } else {
                    val body = response.body()!!.string()
                    val str = response.networkResponse().toString()
                    runOnUiThread {
                        try {
                            val jsonObject = JSONObject(body)
                            val access_token = jsonObject.getString("access_token")
                            val expires_in = jsonObject.getInt("expires_in")
                            val refresh_token = jsonObject.getString("refresh_token")
                            val openid = jsonObject.getString("openid")
                            val scope = jsonObject.getString("scope")
                            val unionid = jsonObject.getString("unionid")
                            getAsyncPersonData("https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid")
                        } catch (e: JSONException) {
                            e.printStackTrace()
                        }
                    }
                }
            }
        })
    }


    private fun getAsyncPersonData(url: String) {
        val client = OkHttpClient()
        val request = Request.Builder()
            .url(url)
            .build()
        val response: Response? = null
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                finish()
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                if (null != response.cacheResponse()) {
                    val str = response.cacheResponse().toString()
                } else {
                    val bod = response.body()!!.string()
                    val str = response.networkResponse().toString()
                    Log.e("bod", "bod---$bod")
                    runOnUiThread {
                        try {
                            val jsonObject = JSONObject(bod)
                            val nickname = jsonObject.getString("nickname") //微信用户昵称
                            val headImgUrl = jsonObject.getString("headimgurl") //微信用户头像
                            val unionId = jsonObject.getString("unionid") //用户统一标识
                            val sex = jsonObject.getInt("sex") //性别
                            ShareAndLoginManager.getInstance().onLoginSuccess(
                                ShareAndLoginManager.LoginType.kLoginTypeWeChat,
                                nickname,
                                headImgUrl,
                                sex,
                                unionId
                            )
                            finish()
                        } catch (e: JSONException) {
                            finish()
                            e.printStackTrace()
                        }
                    }
                }
            }
        })
    }
}

这里是处理登录的流程,分别有3步,获取code、获取AccessToken、获取用户个人数据。具体需要调用到哪一步,看跟自己项目服务器的需要,我这里只需要第一步获取code就行。
配置文件

<!-- Optional 微信分享回调,wxapi必须在包名路径下,否则回调不成功-->
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:taskAffinity="${applicationId}"
            android:launchMode="singleTask"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />

使用:


    private fun loginByWechat(){
        ShareAndLoginManager.getInstance().loginByThirdParty(this,ShareAndLoginManager.LoginType.kLoginTypeWeChat,
            object :ShareAndLoginManager.LoginListener{
                override fun onLoginSuccess(
                    type: ShareAndLoginManager.LoginType?,
                    name: String?,
                    headUrl: String?,
                    sex: Int,
                    code: String?
                ) {
                    Log.d("TAG","code=$code")
                    //微信验证成功,接下来在这里继续你想实现的逻辑。
                }

                override fun onLoginFailed(
                    type: ShareAndLoginManager.LoginType?,
                    code: Int,
                    message: String?
                ) {
                    ToastUtil.showToast("登录失败")
                }

                override fun onLoginCancel(
                    type: ShareAndLoginManager.LoginType?,
                    requestCode: Int,
                    resultCode: Int
                ) {
                    ToastUtil.showToast("取消登录")
                }

                override fun onLoginDenied(type: ShareAndLoginManager.LoginType?) {

                }

            })
    }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容