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,如果找不到導包大家可以修改版本,后面會給出源碼地址,這里只是簡單說出使用步驟,這里基本上三種登錄都已經在項目中成功使用,大家可以嘗試一下,如有問題,及時提出,我會修改.

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,923評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,740評論 3 420
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,856評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,175評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,931評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,321評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,383評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,533評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,082評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,891評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,618評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,319評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,732評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,987評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,794評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,076評論 2 375

推薦閱讀更多精彩內容