天天看点

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 验证

上面方案经过验证可行