前言
海外版app集成三方登录分享,早期采用umeng sdk,由于googleplay对用户隐私及用户数据的使用有比较严格规定。正好 umeng sdk会后台采集app信息,触发用户隐私相关政策条款。结果就是google play对上架的app下架处理。为了彻底解决不得已移除umeng sdk登录分享组件,采用官方Sdk,进行集成。
如何解决被 google play 下架应用重新上架问题:
1.官方解决方案
联系客服,根据 google官方提供的解决方案,在app用户隐私协议中添加对用户数据如何合理使用的解释条款。重新上架提交审核。原以为问题得以解决。正常了一个版本,紧跟着就拒绝上架了。
拒绝原因: umeng share存在获取用户数据情况
2.彻底解决
移除app中所有与umeng关联的代码包括 [统计,分享,登录]等,虽然时间成本高。能彻底解决。
步骤
2.1 移除jar,sdk 依赖,初始化代码。
2.2 集成sdk
下面采用sdk登录方式,如果对 使用 FirebaseUI 向 Android 应用轻松添加登录机制感兴趣,查看引用部分。
帮助文档入口
facebook 登录 入口facebook 分享入口google sdk 入口
代码示例
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(分享内容)
如下图
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 验证
上面方案经过验证可行
引用