天天看點

Android 內建原生google,facebook 登入分享sdk

前言

海外版app內建三方登入分享,早期采用umeng sdk,由于googleplay對使用者隐私及使用者資料的使用有比較嚴格規定。正好 umeng sdk會背景采集app資訊,觸發使用者隐私相關政策條款。結果就是google play對上架的app下架處理。為了徹底解決不得已移除umeng sdk登入分享元件,采用官方Sdk,進行內建。

如何解決被 google play 下架應用重新上架問題:

Android 內建原生google,facebook 登入分享sdk

1.官方解決方案

聯系客服,根據 google官方提供的解決方案,在app使用者隐私協定中添加對使用者資料如何合理使用的解釋條款。重新上架送出稽核。原以為問題得以解決。正常了一個版本,緊跟着就拒絕上架了。

拒絕原因: umeng share存在擷取使用者資料情況

Android 內建原生google,facebook 登入分享sdk

2.徹底解決

移除app中所有與umeng關聯的代碼包括 [統計,分享,登入]等,雖然時間成本高。能徹底解決。

步驟

2.1 移除jar,sdk 依賴,初始化代碼。

2.2 內建sdk

下面采用sdk登入方式,如果對 使用 FirebaseUI 向 Android 應用輕松添加登入機制感興趣,檢視引用部分。

幫助文檔入口

​​facebook 登入 入口​​​​facebook 分享入口​​​​google sdk 入口​​

代碼示例

facebook

class LoginWithFacebookUtils(val context: Activity) {

    var callbackManager: CallbackManager? = null
    //使用fiebase進行擷取需要設定
    //var callbackCredentials: ((AuthCredential) -> Unit)? = null

    init {
        callbackManager = CallbackManager.Factory.create()
        // registerCallback()
    }

    private fun registerCallback(facebookCallback: FacebookCallback<LoginResult>) {
        if (facebookCallback != null) {
            LoginManager.getInstance().registerCallback(callbackManager, facebookCallback)
        } else {
            LoginManager.getInstance().registerCallback(callbackManager, object :
                    FacebookCallback<LoginResult> {
                override fun onSuccess(result: LoginResult) {
//                    val credentials = FacebookAuthProvider.getCredential(result.accessToken.token)
//                    callbackCredentials?.invoke(credentials)

                }
                override fun onCancel() {
                    println("cancel")
                }
                override fun onError(error: FacebookException?) {
                    error?.printStackTrace()
                    print("${error?.message}")
                }
            })
        }
    }

    fun startLoginFacebook(facebookCallback: FacebookCallback<LoginResult>) {
        isLoginIn()
        registerCallback(facebookCallback)
        LoginManager.getInstance().logInWithReadPermissions(context, Arrays.asList("public_profile"));


    }

    fun startLoginFacebook(facebookCallback: SimpleFaceBookCallBack<LoginResult>) {
        isLoginIn()
        registerCallback(facebookCallback)
        LoginManager.getInstance().logInWithReadPermissions(context, Arrays.asList("public_profile"));
    }

    /**
     * 登出
     */
    fun isLoginIn() {
        val accessToken = AccessToken.getCurrentAccessToken()
        val isLoggedIn = accessToken != null && !accessToken.isExpired
        if (isLoggedIn) {
            val loginManager = LoginManager.getInstance()
            loginManager.logOut()
        }
    }

    open abstract class SimpleFaceBookCallBack<LoginResult> : FacebookCallback<LoginResult> {
        override fun onSuccess(result: LoginResult?) {
            print("success")
        }

        override fun onCancel() {
            Log.e("error", "cancel")
        }

        override fun onError(error: FacebookException?) {
            Log.e("error", "$error")
        }
    }

}      

調用入口

public void toFacebookLogin() {
        loginWithFacebookUtils = new LoginWithFacebookUtils(this);
        //login
        loginWithFacebookUtils.startLoginFacebook(new LoginWithFacebookUtils.SimpleFaceBookCallBack<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                thirdUserInfo = new ThirdUserInfo();
                // App code
                thirdUserInfo.setType("facebook");
                thirdUserInfo.setOpenid(loginResult.getAccessToken().getUserId());
                UserRequest.makeUserRequest(new GetUserCallback(LoginActivity.this).getCallback());
            }

        });
    }      

2.3 facebook 分享

之前接入的是umeng三方分享,分享圖文+url方式很友善。例如

友盟分享圖文
        UMWeb web = new UMWeb(shareUrl);
        web.setTitle(title);//标題
        web.setThumb(image);  //縮略圖
        web.setDescription(content);//描述
        new ShareAction(getActivity())
                .setPlatform(share_media)//傳入平台
//              .withText(mShareDate.content)//分享内容
                .withMedia(web)
                .setCallback(umShareListener)//回調監聽器
                .share();      

facebook 的分享翻遍了官方sdk文檔,沒有直接進行圖文分享的api,找到一個Html解析分享方式,但是需要web頁面添加一些中繼資料,供facebook抓取。

分享源碼

/**
 * facebook分享
 * 1.如果沒有安裝facebook 會喚起網頁版facebook 進行登入
 *
 */
object ShareWithFaceBook {
    val TAG = "ShareWithFaceBook"
    var callbackManager: CallbackManager? = null

    init {
        callbackManager = CallbackManager.Factory.create()
    }

    /**
     * 分享連結
     */
    fun shareUrl(context: Activity, url: String) {
        val content = ShareLinkContent.Builder()
                .setContentUrl(Uri.parse(url))
                .build()
        // 對話框
        val shareDialog = ShareDialog(context)
        // 分享回調G
        shareDialog.registerCallback(callbackManager, object : FacebookCallback<Sharer.Result?> {
            override fun onSuccess(result: Sharer.Result?) {
                Log.e(TAG, "onSuccess")
            }

            override fun onCancel() {
                Log.e(TAG, "onCancel")
            }

            override fun onError(error: FacebookException) {
                Log.e(TAG, "onError$error")
            }
        })
        shareDialog.show(content)
    }

    /**
     * 分享圖檔
     */
    fun shareImage(context:Activity,imagePath: String) {
        val filePath: String = imagePath
        val image = BitmapFactory.decodeFile(filePath)
        val photo = SharePhoto.Builder()
                .setBitmap(image)
                .build()
        // 對話框
        val shareDialog = ShareDialog(context)
        val content = SharePhotoContent.Builder()
                .addPhoto(photo)
                .build()
        shareDialog.show(content)
    }

    fun shareImage(context: Activity, drawable: Int) {
        val image = BitmapFactory.decodeResource(context.resources, drawable)
        val photo = SharePhoto.Builder()
                .setBitmap(image)
                .build()
        val content = SharePhotoContent.Builder()
                .addPhoto(photo)
                .build()
        // 對話框
        val shareDialog = ShareDialog(context)
        shareDialog.registerCallback(callbackManager,object : FacebookCallback<Sharer.Result?> {
            override fun onSuccess(result: Sharer.Result?) {
                Log.e(TAG, "onSuccess")
            }

            override fun onCancel() {
                Log.e(TAG, "onCancel")
            }

            override fun onError(error: FacebookException) {
                Log.e(TAG, "onError$error")
            }
        })
        shareDialog.show(content)
//        ShareApi.share(content, object : FacebookCallback<Sharer.Result?> {
//            override fun onSuccess(result: Sharer.Result?) {
//                Log.e(TAG, "onSuccess")
//            }
//
//            override fun onCancel() {
//                Log.e(TAG, "onCancel")
//            }
//
//            override fun onError(error: FacebookException) {
//                Log.e(TAG, "onError$error")
//            }
//        })
    }

    /**
     * 分享視訊
     */
    fun shareVideo(videoUrl: Uri) {
        val video = ShareVideo.Builder()
                .setLocalUrl(videoUrl)
                .build();
        val content = ShareVideoContent.Builder()
                .setVideo(video)
                .build();

    }



}      

tips:

facebok 分享文案需要分享圖檔或者url調起facebook 個人首頁後填寫,fecebook 支援web界面登入,即使本地沒有安裝facebook,也可以進行facebok登入或者分享。分享api需要裝在一個ShareDialog容器中。

val shareDialog = ShareDialog(context)
shareDialog.show(分享内容)      

如下圖

Android 內建原生google,facebook 登入分享sdk

2.4 google 登入

/**
 * google 登入封裝
 */
class LoginWithGoogleUtils(val context: Activity) {

    private val TAG = "LoginWithGoogle"
    private val GOOGLE_SIGN_IN = 9001
    private val activity = context
    private var googleApiAvailability: GoogleApiAvailability? = null
    public var googleSignInClient: GoogleSignInClient? = null

    init {
        googleApiAvailability = GoogleApiAvailability.getInstance()
        googleSignInClient = getGoogleSignInOptions()
    }


    /**
     * google service 是否可用
     */
    fun isGoogleServiceAvailable(): Int {
        return googleApiAvailability?.isGooglePlayServicesAvailable(context)!!
    }

    private fun getGoogleSignInOptions(): GoogleSignInClient {
        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .requestProfile()
                .build()

        return GoogleSignIn.getClient(context, gso)
    }

    fun startLoginGoogle() {
        context.startActivityForResult(
                googleSignInClient?.signInIntent, GOOGLE_SIGN_IN
        )
    }

    fun startLoginGoogleAfterLoginOut() {
        googleSignInClient?.signOut()
        context.startActivityForResult(
                googleSignInClient?.signInIntent, GOOGLE_SIGN_IN
        )
    }

    fun onActivityResult(requestCode: Int, data: Intent?, callGoogleLoginResult: GoogleLoginResult) {
        if (requestCode == GOOGLE_SIGN_IN) {
            try {
                val task = GoogleSignIn.getSignedInAccountFromIntent(data)
                handleSignInResult(task, callGoogleLoginResult)
            } catch (e: ApiException) {
                if (e.statusCode == 7) {
                    Toast.makeText(activity, "NETWORK_ERROR", Toast.LENGTH_SHORT).show()
                    Log.e(TAG, e.message)
                } else {
                    Log.e(TAG, e.message)
                }
            }
        }
    }


    private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>, callGoogleLoginResult: GoogleLoginResult) {
        val account = completedTask.getResult(ApiException::class.java)
        account?.let { callGoogleLoginResult.callBack(it) }
        Log.d(TAG, account.toString())
    }

    interface GoogleLoginResult {

        fun callBack(account: GoogleSignInAccount)
    }

}      

tips:

google 登入在不翻牆的情況下,登入提示apiExcetpin code ==7 。需要try 一下

2.5 驗證

上面方案經過驗證可行