在做海外项目中,经常需要接入Facebook SDK ,现将CocosCreator Android 平台 Facebook 登录的接入流程记录下来,以备有需要的朋友做参考。

一、准备工作

1、首先在facebook 开发者平台 注册账号,创建app,获取app的应用编号。

怎么注册账号,怎么创建app ,这里就不再细说。

app的应用编号和密钥,如下所示:

2、设置应用密钥散列

生成密钥散列有2种方式:

(1)、通过代码获取

//获取facebook所需的密钥散列
try {PackageInfo info = getPackageManager().getPackageInfo("com.x.x",     PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {MessageDigest md = MessageDigest.getInstance("SHA");md.update(signature.toByteArray());showLog("Base64 hash------" + Base64.encodeToString(md.digest(), Base64.DEFAULT));}
} catch (PackageManager.NameNotFoundException e) {} catch (NoSuchAlgorithmException e) {}

(2)、通过工具进行获取

第一步,通过命令行的方式获取到证书指纹SHA1

发布证书指纹获取方式:

keytool -exportcert -alias YOUR_RELEASE_KEY_ALIAS -keystore YOUR_RELEASE_KEY_PATH | openssl sha1 -binary | openssl base64

开发证书指纹获取方式:

keytool -exportcert -alias androiddebugkey -keystore "C:\Users\USERNAME\.android\debug.keystore" | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" sha1 -binary | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" base64

证书指纹示例:

SHA1: 9D:2F:E0:3C:8E:DF:ED:8C:2B:28:88:92:60:A3:82:63:81:4F:3D:9D

第二步,使用工具,将SHA1 证书指纹转化为密钥散列

在线工具:http://tomeko.net/online_tools/hex_to_base64.php

详细使用步骤,请查看根据 sha-1 证书值获取 Facebook 的登录需要使用的散列值

密钥散列可填写多个:

3、添加平台

这里以添加 google play 平台为例进行说明。

(1)、点击下方“添加平台” 按钮 ,在弹出的二级页面依次选择 android ->google play 。

(2)、设置软件包名,包名就是项目包名 com.xxx.xxx。

(3)、设置类名,类名里面填写启动activity 全路径,例如:org.cocos2dx.javascript.AppActivity。

3、创建测试账号,修改密码

二、代码部分调整

1、在项目层 build.gradle ,引入facebook 最新版本sdk。

implementation 'com.facebook.android:facebook-login:latest.release'
implementation 'com.facebook.android:facebook-android-sdk:latest.release'

2、AndroidManifest.xml 配置

(1)、添加网络访问权限,如果已经开启,则忽略。

 <uses-permission android:name="android.permission.INTERNET"/>

(2)、在 application 添加 meta-data 元素 和针对 Facebook 的 activity 元素。

<!-- SDK Facebook start! --><meta-data android:name="com.facebook.sdk.ApplicationId"android:value="@string/facebook_app_id"/><activity android:name="com.facebook.FacebookActivity"android:configChanges= "keyboard|keyboardHidden|screenLayout|screenSize|orientation"android:label="@string/app_name" />
<!-- SDK Facebook end! -->

(3)、在 application 启动activity 元素添加 scheme

  <activityandroid:name="org.cocos2dx.javascript.AppActivity"android:screenOrientation="sensorPortrait"android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"android:label="@string/app_name"android:theme="@android:style/Theme.NoTitleBar.Fullscreen"android:launchMode="singleTask"android:exported="true"android:taskAffinity="" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter  android:autoVerify="true"><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="@string/fb_login_protocol_scheme" /></intent-filter></activity>

3、res/values/strings.xml 配置

    <string name="facebook_app_id">285717330186354</string><string name="fb_login_protocol_scheme">fb285717330186356</string>

facebook_app_id :app的应用编号
fb_login_protocol_scheme:fb+app的应用编号

4、登录调用、回调通知、用户信息获取简单封装

关于Facebook 登录,官方提供了 LoginButton 和LoginManager 两种方式。

不过我们经常使用自己的View 来显示 ,因此这里采用 LoginManager 的方式实现。

详细请查看以下代码:

package org.cocos2dx.javascript.tools;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookRequestError;
import com.facebook.GraphRequest;
import com.facebook.GraphResponse;
import com.facebook.HttpMethod;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;import org.cocos2dx.javascript.Native;
import org.json.JSONException;
import org.json.JSONObject;import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;public class FaceBookUtils {private CallbackManager m_callbackManager =null;private String  m_actTag ="FaceBookUtils";private String  m_facebookLoginCallBack="";private Activity m_activity=null;private static FaceBookUtils g_Instace = null;public static FaceBookUtils getInstance() {if (null == g_Instace) {g_Instace = new FaceBookUtils();}return g_Instace;}public  void loginFacebook(final String callback){m_facebookLoginCallBack = callback;LoginManager.getInstance().logInWithReadPermissions(m_activity, Arrays.asList("public_profile"));}public void onActivityResult(int requestCode, int resultCode, Intent data) {m_callbackManager.onActivityResult(requestCode,resultCode,data);}public void getUserFacebookBasicInfo(Map<String,String> inmap) {final String id = inmap.get("id");final String token = inmap.get("token");final String app = inmap.get("app");// 获取基本文本信息Log.d(m_actTag, "准备获取facebook用户基本信息");GraphRequest request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {@Overridepublic void onCompleted(JSONObject object, GraphResponse response) {if (response == null) {Log.d(m_actTag, "无法获取fb用户基本信息");return;}Log.d(m_actTag, "获取fb用户基本信息完毕,object是" + object);JSONObject responseJsonObject = response.getJSONObject();Log.d(m_actTag,  "而response 的object是" + responseJsonObject);//这两个jsonObject是一样的if (responseJsonObject == null) {Log.d(m_actTag, "无法获取fb用户基本信息" + response.getError().getErrorType() + "   " + response.getError().getErrorMessage());return;}Map<String,String> map = new HashMap<String, String>();map.put("result", "11");map.put("info", "fb info success");map.put("id", id);map.put("token", token);map.put("appid", app);map.put("firstName", getFacebookGraphResponseString(responseJsonObject, "first_name"));map.put("lastName", getFacebookGraphResponseString(responseJsonObject, "last_name"));map.put("userName", getFacebookGraphResponseString(responseJsonObject, "name"));
//                map.put("birthday", getFacebookGraphResponseString(responseJsonObject, "birthday"));//map.put("updateTime", getFacebookGraphResponseString(responseJsonObject, "updated_time"));
//                map.put("email", getFacebookGraphResponseString(responseJsonObject, "email"));
//                map.put("gender", getFacebookGraphResponseString(responseJsonObject, "gender"));//获取用户头像 (小)//JSONObject object_pic = object.optJSONObject( "picture" ) ;//JSONObject object_data = object_pic.optJSONObject( "data" ) ;//String photo = object_data.optString( "url" )  ;//map.put("head", photo);Native.nativeToLogic(m_facebookLoginCallBack,map);}});Bundle parameters = new Bundle();
//        parameters.putString("fields", "id,name,link,email,first_name,last_name,gender,picture,locale,timezone,updated_time,verified");parameters.putString("fields", "id,name,first_name,last_name");request.setParameters(parameters);request.executeAsync();}public String getFacebookGraphResponseString(JSONObject graphResponse, String flag) {String value = "";try {value = graphResponse.getString(flag);} catch (JSONException e) {e.printStackTrace();}Log.d(m_actTag, "getFacebookInfo flag="+flag+"   result="+value);return value;}public void getFacebookUserPictureAsync(String facebookUserId) {Log.d(m_actTag,  "getFacebookUserPictureAsync");Bundle parameters = new Bundle();parameters.putBoolean("redirect", false);parameters.putString("height", "200");parameters.putString("type", "normal");parameters.putString("width", "200");GraphRequest graphRequest= new GraphRequest(AccessToken.getCurrentAccessToken(), "/" + facebookUserId + "/picture", parameters, HttpMethod.GET, new GraphRequest.Callback() {public void onCompleted(GraphResponse response) {if (response == null) {Log.d(m_actTag,  "get facebook photo fail");return;}if (response.getError() != null) {FacebookRequestError facebookRequestError = response.getError();Log.d(m_actTag,  "get facebook photo fail 2::" + facebookRequestError.getErrorMessage());return;}JSONObject responseJsonObject = response.getJSONObject();if (responseJsonObject == null) {Log.d(m_actTag,  "get facebook photo fail 3");return;}Log.d(m_actTag,  "facebook photo info:" + responseJsonObject.toString());String avatarUrl = "";try {JSONObject dataJsonObject = responseJsonObject.getJSONObject("data");avatarUrl = dataJsonObject.getString("url");//分割出参数部分
//                    String[] sourceStrArray = avatarUrl.split("\\?");avatarUrl = URLEncoder.encode(avatarUrl, "UTF-8");Log.d(m_actTag,  "facebook photo avatarUrl:" + avatarUrl);Map<String,String> map = new HashMap<String, String>();map.put("result", "12");map.put("info", "fb head success");map.put("head", avatarUrl);map.put("height", dataJsonObject.getString("height"));map.put("width", dataJsonObject.getString("width"));map.put("isSilhouette", dataJsonObject.getString("is_silhouette"));Native.nativeToLogic(m_facebookLoginCallBack,map);} catch (Exception e) {Log.d(m_actTag,  "get facebook photo fail 4"+e.getStackTrace().toString());}}});Log.d(m_actTag,  "getFacebookUserPictureAsync version:"+graphRequest.getVersion()+"");graphRequest.executeAsync();}public void initSDK( final Activity activity){m_activity = activity;m_callbackManager = CallbackManager.Factory.create();Log.d("fb login","initSDK");LoginManager.getInstance().registerCallback(m_callbackManager, new FacebookCallback<LoginResult>() {@Overridepublic void onSuccess(LoginResult loginResult) {Log.e(m_actTag, "facebook login success: " + loginResult.getAccessToken().getToken());Map<String,String> map = new HashMap<String, String>();map.put("result", "1");map.put("info", "fb login success");map.put("id", loginResult.getAccessToken().getUserId());map.put("token", loginResult.getAccessToken().getToken());map.put("app", loginResult.getAccessToken().getApplicationId());Native.nativeToLogic(m_facebookLoginCallBack,map);Log.d("fb login","success!!!!!");//紧接着获取用户信息getUserFacebookBasicInfo(map);
//                getFacebookUserPictureAsync(loginResult.getAccessToken().getUserId());}@Overridepublic void onCancel() {Log.e(m_actTag, "facebook login cancel");Map<String,String> map = new HashMap<String, String>();map.put("result", "2");map.put("info", "user cancel");Log.d("user","cancel!!!!!");Native.nativeToLogic(m_facebookLoginCallBack,map);}@Overridepublic void onError(FacebookException error) {Log.e(m_actTag, "facebook login error:" + error.toString());Map<String,String> map = new HashMap<String, String>();map.put("result", "3");map.put("info", error.toString());Log.d("facebook login","error!!!!!");Native.nativeToLogic(m_facebookLoginCallBack,map);}});}
}

5、AppActivity 中使用 FaceBookUtils 封装类

(1)、onCreate 时初始化

   FaceBookUtils.getInstance().initSDK(this);

(2)、设置回调

 @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {FaceBookUtils.getInstance().onActivityResult(requestCode, resultCode, data);super.onActivityResult(requestCode, resultCode, data);
}

(3)、登录接口导出

 public static void loginFacebook(final String callback) {FaceBookUtils.getInstance().loginFacebook(callback);}

6、js 层 对java 的 Native 封装

private static CallBackKey: string = "nativeCallback";private static _callBackPrefix: string; //回调集合字符前缀private static _prevErr = ""private static _hasInited = false;public static init() {if (cc.sys.isBrowser) {return}if (this._hasInited) {return}this._hasInited = true;window[this.CallBackKey] = {}; //回调函数集合this._callBackPrefix = "window." + this.CallBackKey + ".";//捕获异常if (cc.sys.isNative) {window.__errorHandler = function (file: any, line: any, error: any, stack: any) {if (this._prevErr != error + line) {stack = String(stack)console.log("========== GOT JS/TS ERROR ==========")console.log("file:" + file, "line:" + line, "error:" + error)console.log(stack)this._prevErr = error + line;}}}}// 登陆fb   Native.loginFacebook((ret:any)=>{cc.log(ret)},"(%s)")public static loginFacebook(func: any,funcParams:string): void {if (cc.sys.isNative) {let cbKey: string = "loginFacebook"window[this.CallBackKey][cbKey] = funclet ret = 0;if (cc.sys.os == cc.sys.OS_ANDROID) {ret = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "loginFacebook", "(Ljava/lang/String;)V", this._callBackPrefix + cbKey + funcParams);}}}

7、js 层调用Native. loginFacebook

      getPlayerInfoBySdk(){let self = this;Native.loginFacebook((ret: any) => {self.facebookSdkBack(ret)},"(%s)")}//请求SDK返回facebookSdkBack(backInfo:any){if(backInfo){if(backInfo.result == "2"){//用户取消FB登录UIHelper.UICenterNotice(backInfo.info)}else if(backInfo.result == "3"){//FB登录失败UIHelper.UICenterNotice(backInfo.info)}else if(backInfo.result == "11"){//FB登录成功并返回用户数据this.checkFbToken(backInfo);}else if(backInfo.result == "12"){//FB登录成功并返回头像信息}}}

三、测试登录

需要注意2点:

(1)、使用的打包证书需要与facebook 开发者平台生成密钥散列证书一致。

(2)、需要使用 facebook 测试账号进行登录测试。

Cocos Creator Android 平台 Facebook 原生登录相关推荐

  1. Cocos Creator Android 平台 Google 原生登录

    在海外项目中,我们通常需要接入 Google 帐号登录,这样可以提高应用使用率. 下面以 Android 平台 接入 Google 原生登录为例,进行详细说明. 一.准备工作 1.需要 Android ...

  2. Android Facebook原生登录

    前言: 在写这篇文章之前先吐槽一下自己的英文水平,之前一直没感觉,因为做的项目都是国内的项目,很少看英文文档.但是,自从换了一个工作之后,做的是国外的项目.并且,写了给第三方写了一个SDK,需要使用G ...

  3. cocos creator利用ShareSDK实现微信登录功能

    首先在ShareSDK官网下载SDK或者在android studio中配置build.gradle. ShareSDK Maven集成文档 注:使用ShareSDK maven集成方式,不需要在An ...

  4. cocos creator ios 接入 facebook sdk login

    主程序是cocos creator 发布ios时要接facebook登录的sdk cocos creator 发布ios版本后 按官方文档配置接入,碰到以下问题 执行 sudo gem install ...

  5. cocos creator android 真机调试配置密匙

    android 真机调试与打包 真机调式 cocos creator 环境配置完成后 选择 编辑器 => 项目 => 构建发布 => android => 构建 构建完成后打开 ...

  6. Android——第三方Facebook授权登录获取用户信息

    由于项目中需要使用Facebook进行一键登录,所以记录下步骤,其实小伙伴直接看官网也可以,介绍的蛮详细的,先看下效果图吧. 遵循以下步骤将Facebook登录添加到您的应用. Facebook开发者 ...

  7. 用 Cocos Creator 制作平台跳跃游戏

    前言 平台跳跃类游戏如<超级马里奥><Celeste蔚蓝>等,非常考验玩家的操作和判断,有着非常本真的游戏乐趣.这类游戏乍一看,挺容易做的,但是要做好却不太容易.今天,我将使用 ...

  8. cocos creator android之微信开放平台修改签名 baseResp.errCode=-6

    1.baseResp.errCode=-6 就代表签名和打包的秘钥生成的签名不一致,会导致调起来的微信授权登录页一片空白,我用cocos的应用包名去生成md5签名和用keystore生成的签名不一致, ...

  9. Android集成Facebook第三方登录,全流程

    首次接触海外项目,开发环节与测试流程刚开始搞得一头雾水,历时两周终于把登录和支付调通了,特此记录下: 不过总结下来,与国内流程不同的点,主要是测试流程,需要专门的测试账号与测试权限才能测通 首先打开开 ...

最新文章

  1. 【网络流24题】飞行员配对方案问题
  2. javascript DOM基础(一)
  3. [Idea Fragments]2013.08.08
  4. top.location.href和localtion.href有什么不同
  5. oracle密码不能重复用_重复码
  6. iOS开发之#iPhone6与iPhone6Plus适配#Xcode6.0/Xcode6.1上传应用过程中一些变动以及#解决方案#
  7. vue ---- 组件综合案例(购物车案例)
  8. 互联网十几年 我们错失了哪些创业机会
  9. 使用soap遇到的缓存问题
  10. 传统词向量nlp处理的优缺点_吴恩达深度学习笔记(126) | NLP | GloVe 词向量
  11. 学习成果区块链问世,中科宇创为人才能力认证提供权威账本
  12. 在火狐浏览器里怎么看请求头
  13. 在Vue项目中使用阿里巴巴矢量图
  14. android布局跑马灯,Android之跑马灯详解
  15. 计算机网络怎样连手机软件,手机怎么共享网络给电脑_手机如何共享电脑网络-win7之家...
  16. [设备驱动] 最简单的内核设备驱动--字符驱动
  17. 面向对象封装案例 --- 士兵突击
  18. 佐治亚大学计算机工程本科课程,美国大学本科专业排名:计算机工程.docx
  19. Match Points CodeForces 1156C 二分答案
  20. 淘淘商城第44讲——搭建搜索系统工程

热门文章

  1. 多数据源/动态数据源的解决方案
  2. ‘gbk‘ codec can‘t decode byte 0xa4 in position 4: illegal multibyte sequence
  3. 图像处理实验,中值滤波处理椒盐噪声
  4. xfire ---java web服务器引擎
  5. matlab离散数据微积分
  6. OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)
  7. 使用Visual Studio+OpenCV进行的Susan算子边缘检测及数米粒图像处理实验
  8. xp锁定计算机快捷方式,XP系统怎么锁定界面快捷方式到任务栏
  9. 身在互联网,该如何提高自身的核心竞争力?
  10. 智能巡更系统|工业园区无线通信系统