zoukankan      html  css  js  c++  java
  • Android中使用Kotlin实现Google、FaceBook、Twitter登录的封装

    最近由于项目做国际化,所以需要接入Google、FaceBook、Twitter等各种第三方登录的Api,于是查找官网资料,申请各种key和密钥,最后成功完成了这三个第三方登录Api的功能,但是由于很多地方需要调用,前期做得很粗糙,发现调用很麻烦,于是做了一次封装,总结一下,关于资料的申请这里就不说了,本博客采用的是Kotlin代码,不熟悉Kotlin的同学可以学习一下,直接上封装的代码:

    一、接入Google、Facebook、Twitter之前需要安装Google服务,所以首先需要判断用户是否安装Google服务插件,这里说特别说明一下,一定要安装官网的正版Google服务插件,要不然会出现各种问题,这里就不展开了.检测用户是否安装Google服务的方法如下:


     

    /**

    * 检查用户是否安装Google Play 服务

    */

    open fun onCheckGooglePlayService(activity:Activity,code:Int){

    // 验证是否已在此设备上安装并启用Google Play服务,以及此设备上安装的旧版本是否为此客户端所需的版本

    GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(activity)

    /**

    * 通过isUserResolvableError来确定是否可以通过用户操作解决错误

    */

    if (GoogleApiAvailability.getInstance().isUserResolvableError(code)) {

        GoogleApiAvailability.getInstance().getErrorDialog(activity, code, 200).show()

    }

    }

    fun checkGooglePlayServiceExist(activity: Activity): Int {

        return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity)

    }

    二.Google登录工具类的封装:


     

    /**

    * @author: njb

    * @date: 2021/5/8 14:37

    * @desc: Google登录工具类

    */

    open class GoogleLoginUtils(private val activity: Activity, var listener: GoogleSignListener) {

        var requestCode = 10

        private var mGoogleSignInClient: GoogleSignInClient? = null

        private var googleSignListener: GoogleSignListener? = null

        init {

            //初始化谷歌登录服务

            val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)

                    .requestEmail()

                    .build()

            mGoogleSignInClient = GoogleSignIn.getClient(activity, gso)

        }

        /**

        * 登录

        */

        open fun signIn() {

            val signInIntent: Intent = mGoogleSignInClient!!.signInIntent

            activity.startActivityForResult(signInIntent, requestCode)

        }

        /**

        * 退出登录

        */

        open fun signOut() {

        }

        fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {

            try {

                val account: GoogleSignInAccount? = completedTask.getResult(ApiException::class.java)

                val status: Task<GoogleSignInAccount> = completedTask

                if (status.isSuccessful) {

                    if (account != null) {

                        //ToastUtils.showShort(activity.getString(R.string.login_success))

                        googleSignListener?.googleLoginSuccess(account)

                        LogUtils.d("account" + account?.account)

                    } else {

                        googleSignListener?.googleLoginFail(activity.getString(R.string.login_failed))

                    }

                }

            } catch (e: ApiException) {

                LogUtils.d("signInResult:failed code=" + e.statusCode)

            }

        }

        open fun setGoogleSignListener(googleSignListener: GoogleSignListener?) {

            this.googleSignListener = googleSignListener

        }

        interface GoogleSignListener {

            fun googleLoginSuccess(account: GoogleSignInAccount)

            fun googleLoginFail(message: String?)

            fun googleLogoutSuccess()

            fun googleLogoutFail()

        }

        /**

        * 检查 Google Play 服务

        */

        open fun onCheckGooglePlayServices(activity: Activity, code: Int) {

            // 验证是否已在此设备上安装并启用Google Play服务,以及此设备上安装的旧版本是否为此客户端所需的版本

            GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(activity)

            /**

            * 通过isUserResolvableError来确定是否可以通过用户操作解决错误

            */

            if (GoogleApiAvailability.getInstance().isUserResolvableError(code)) {

                GoogleApiAvailability.getInstance().getErrorDialog(activity, code, 200).show()

            }

        }

        fun checkGooglePlayServiceExist(activity: Activity): Int {

            return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity)

        }

    }

    三、FaceBook登录工具类的封装:


     

    /**

    *@author: njb

    *@date:  2021/5/8 14:26

    *@desc:  FaceBook登录工具类

    */

    open class FacebookLoginUtils(private val activity: Activity) {

        private var loginManager: LoginManager? = null

        private val permissions: List<String>

        private var callbackManager: CallbackManager? = null

        private var requestSuccessCode = 2896

        private var requestCancelCode = 2897

        private var requestFailedCode = 2898

        private var mFaceBookLoginListener: FaceBookLoginListener? = null

        var infoBean: FaceLoginInfoBean? = null

        init {

            //初始化facebook登录服务

            callbackManager = CallbackManager.Factory.create()

            getLoginManager().registerCallback(callbackManager, object : FacebookCallback<LoginResult> {

                override fun onSuccess(result: LoginResult?) {

                    activity.setResult(requestSuccessCode)

                    getLoginInfo(result?.accessToken)

                }

                override fun onCancel() {

                    activity.setResult(requestCancelCode)

                    mFaceBookLoginListener?.onLoginCancel(activity.getString(R.string.login_cancel))

                }

                override fun onError(error: FacebookException?) {

                    activity.setResult(requestFailedCode)

                    mFaceBookLoginListener?.onLoginFail(error?.message)

                    LogUtils.d(error?.message)

                }

            })

            permissions = listOf("email", "user_likes", "user_status", "user_photos", "user_birthday", "public_profile", "user_friends");

        }

        /**

        * 登陆

        */

        fun login() {

            getLoginManager().logIn(activity, permissions)

        }

        /**

        * 退出登陆

        */

        fun loginOut() {

            var logout = activity.resources.getString(R.string.com_facebook_loginview_log_out_action)

            var cancel = activity.resources.getString(R.string.com_facebook_loginview_cancel_action)

            val message: String

            val profile: Profile = Profile.getCurrentProfile()

            message = if (profile?.name != null) {

                java.lang.String.format(

                        activity.resources.getString(

                                R.string.com_facebook_loginview_logged_in_as),

                        profile.name)

            } else {

                activity.resources.getString(

                        R.string.com_facebook_loginview_logged_in_using_facebook)

            }

            val builder: AlertDialog.Builder = AlertDialog.Builder(activity)

            builder.setMessage(message)

                    .setCancelable(true)

                    .setPositiveButton(logout) { _, _ ->

                        getLoginManager().logOut()

                    }

                    .setNegativeButton(cancel, null)

            builder.create().show()

        }

        /**

        * 获取登录信息

        * @param accessToken

        */

        private fun getLoginInfo(accessToken: AccessToken?) {

            var request = GraphRequest.newMeRequest(accessToken, object : GraphRequest.GraphJSONObjectCallback {

                override fun onCompleted(`object`: JSONObject?, response: GraphResponse?) {

                    `object`?.run {

                        val id = optString("id") //比如:13813813888

                        val name = optString("name") //比如:Zhang San

                        val gender = optString("gender") //性别:比如 male (男)  female (女)

                        val email = optString("email") //邮箱:比如:11111@qq.com

                        //获取用户头像

                        val object_pic = optJSONObject("picture")

                        val object_data = object_pic.optJSONObject("data")

                        val photo = object_data.optString("url")

                        //获取地域信息

                        val locale = optString("locale") //zh_CN 代表中文简体

                        infoBean = FaceLoginInfoBean()

                        infoBean?.id = id

                        infoBean?.name = name

                        infoBean?.email = email

                        infoBean?.gender = gender

                        infoBean?.picture = object_pic.toString()

                        infoBean?.data = object_data.toString()

                        infoBean?.photo = photo

                        infoBean?.locale = locale

                        infoBean?.let { mFaceBookLoginListener?.onLoginSuccess(it) }

                    }

                }

            })

            val parameters = Bundle()

            parameters.putString("fields", "id,name,link,gender,birthday,email,picture,locale,updated_time,timezone,age_range,first_name,last_name")

            request.parameters = parameters

            request.executeAsync()

        }

        fun getCallbackManager(): CallbackManager? {

            return callbackManager

        }

        /**

        * 获取loginMananger

        * @return

        */

        private fun getLoginManager(): LoginManager {

            if (loginManager == null) {

                loginManager = LoginManager.getInstance();

            }

            return loginManager!!

        }

        companion object {

            /**

            * 是否处在登陆状态

            */

            fun isLogin(): Boolean {

                val accessToken = AccessToken.getCurrentAccessToken()

                val isLoggedIn = accessToken != null && !accessToken.isExpired

                return isLogin()

            }

        }

        open fun setFaceBookLoginListener(faceBookLoginListener: FaceBookLoginListener?) {

            this.mFaceBookLoginListener = faceBookLoginListener

        }

        interface FaceBookLoginListener {

            fun onLoginSuccess(infoBean: FaceLoginInfoBean)

            fun onLoginCancel(message: String?)

            fun onLoginFail(message: String?)

            fun onLogoutSuccess()

            fun onLogoutFail()

        }

    }

    四、Twitter登录工具类的封装:


     

    **

    * @author: njb

    * @date: 2021/5/14 10:08

    * @desc: Twitter登录工具类

    */

    class TwitterLoginUtils(activity: Activity) {

            private var activityRef: WeakReference<Activity>? = null

            var callback: Callback<TwitterSession>? = null

        @Volatile

        var authClient: TwitterAuthClient? = null

        companion object {

            const val ERROR_MSG_NO_ACTIVITY = ("TwitterLoginButton requires an activity."

                    + " Override getActivity to provide the activity for this button.")

        }

        init {

            activityRef = WeakReference(activity)

            TwitterCore.getInstance()

        }

        fun setOnLoginByTwitterClick(callback: Callback<TwitterSession>?) {

            this.callback = callback

            checkCallback(callback)

            checkActivity(activityRef?.get())

            twitterAuthClient!!.authorize(activityRef?.get(), callback)

        }

        private val twitterAuthClient: TwitterAuthClient?

            get() {

                if (authClient == null) {

                    synchronized(TwitterLoginButton::class.java) {

                        if (authClient == null) {

                            authClient = TwitterAuthClient()

                        }

                    }

                }

                return authClient

            }

        private fun checkCallback(callback: Callback<*>?) {

            if (callback == null) {

                CommonUtils.logOrThrowIllegalStateException(TwitterCore.TAG,

                        "Callback must not be null, did you call setCallback?")

            }

        }

        private fun checkActivity(activity: Activity?) {

            if (activity == null || activity.isFinishing) {

                CommonUtils.logOrThrowIllegalStateException(TwitterCore.TAG, ERROR_MSG_NO_ACTIVITY)

            }

        }

        /**

        * Call this method when [Activity]

        * is called to complete the authorization flow.

        *

        * @param requestCode the request code used for SSO

        * @param resultCode  the result code returned by the SSO activity

        * @param data        the result data returned by the SSO activity

        */

        fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

            if (requestCode == twitterAuthClient!!.requestCode) {

                twitterAuthClient!!.onActivityResult(requestCode, resultCode, data)

            }

        }

    }

     五、具体使用代码如下:

    5.1------使用Google登录时需要先判断用户是否安装Google服务,


     

     5.2------使用具体步骤如下:

     a. 先声明工具类

    private var mGoogleLogin: GoogleLoginUtils? = null

    private var mFacebookLoginUtils: FacebookLoginUtils? = null


     

     b.Google和FaceBook工具类的初始化

    private fun initGoogle() {

        mGoogleLogin = GoogleLoginUtils(this, this)

        mGoogleLogin?.setGoogleSignListener(this)

    }

    private fun initFaceBook() {

        mFacebookLoginUtils = FacebookLoginUtils(this)

        mFacebookLoginUtils?.setFaceBookLoginListener(this)

    }

    c.点击Google和FaceBook两个按钮分别调用不同的方法


     

    R.id.iv_google -> {//先检查是否安装Google服务

        checkGoogleService()

    }

    R.id.iv_face_book -> {//检查是否安装FaceBook客户端

        if (!CheckApkExist.checkFacebookExist(this)) {

            ToastUtils.showShort(getString(com.jiaoday.base.R.string.please_install_face_book_first))

        } else {

            mFacebookLoginUtils?.login()

        }

    }


     

    private fun checkGoogleService() {

        val code = mGoogleLogin?.checkGooglePlayServiceExist(this)

        if (code == ConnectionResult.SUCCESS) {

            mGoogleLogin?.signIn()

        } else {

            code?.let { mGoogleLogin?.onCheckGooglePlayServices(this, it) }

        }

    }

    d.Google和FaceBook登录回调,在最开始继承一下登录回调监听方法:

     GoogleLoginUtils.GoogleSignListener, FacebookLoginUtils.FaceBookLoginListener


     

    e.登录成功、失败、取消登录后的回调


     

    override fun googleLoginSuccess(account: GoogleSignInAccount) {

        //google登录成功后返回的信息

        if (account.email != null) {

            thirdAccountLogin(account.email.toString(), account.email.toString(), "4")

        }

    }

    override fun googleLoginFail(message: String?) {

        ToastUtils.showShort(message)

    }

    override fun googleLogoutSuccess() {

    }

    override fun googleLogoutFail() {

    }

     f.onActivityResult回调结果:


     

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == mGoogleLogin?.requestCode) {

            val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data)

            mGoogleLogin?.handleSignInResult(task)

        }

        mFacebookLoginUtils?.getCallbackManager()?.onActivityResult(requestCode, resultCode, data)

    }

     六、登录成功后处理自己的登录逻辑,调用第三方登录接口,这里Google登录使用的是最新的api,如果找不到导包大家可以修改版本,后面会给出源码地址,这里只是简单说出使用步骤,这里基本上三种登录都已经在项目中成功使用,大家可以尝试一下,如有问题,及时提出,我会修改.

  • 相关阅读:
    'Undefined symbols for architecture i386,clang: error: linker command failed with exit code 1
    The codesign tool requires there only be one 解决办法
    XCode iOS project only shows “My Mac 64bit” but not simulator or device
    Provisioning profile XXXX can't be found 的解决办法
    UIView 中的控件事件穿透 Passthrough 的实现
    Xcode4.5出现时的OC新语法
    xcode 快捷键(持续更新)
    打越狱包
    php缓存与加速分析与汇总
    浏览器的判断
  • 原文地址:https://www.cnblogs.com/ning137/p/15465914.html
Copyright © 2011-2022 走看看