Cocos Creator Android 平台 Facebook 原生登录

2023-10-27



在做海外项目中,经常需要接入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



  <activity
            android: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() {
            @Override
            public 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>() {
            @Override
            public 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());
            }

            @Override
            public 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);
            }

            @Override
            public 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)、设置回调



 @Override
 protected 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] = func
            let 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 测试账号进行登录测试。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Cocos Creator Android 平台 Facebook 原生登录 的相关文章

随机推荐

  • 微信小程序之短信验证码

    目录 1 前提 2 开通静态 2 1 点击云开发中更多 gt 静态网站 2 2 点击开通 使用管理员验证即可 3 短信发送规则 3 1 短信内容 3 2 短信规则 3 3 短信内容长度计算规则 3 4 短信内容规范 3 5 短信发送记录查询
  • Tensorflow2.0

    注 本文的python实现基于论文 Dynamic scheduling for flexible job shop with new job insertions by deep reinforcement learning 论文详情可见
  • 线性代数1 矩阵

    1 概念定义 1 1 正定矩阵 Positive definite matrix 1 2 实对称矩阵 若矩阵A为实对阵矩阵 则满足A A T a ij a ji 1 3 埃尔米特矩阵 Hermitian matrix 埃尔米特矩阵中每一个第
  • node.js回调函数的一点理解

    刚开始入坑node js 花了一下午才搞清楚什么是回调函数 回调函数是作为参数传递给另一个函数的 比如说function human man callback 这里的callback就是回调函数 看了很多篇文章有一句话给我留下了很深的印象就
  • java虚拟机有哪几部分组成,Java虚拟机基本结构

    Java虚拟机是JVM类语言的根基 其中动态内存管理和垃圾收集技术是JVM中最重要的特性 本节主要讲述其中的内存管理相关概念 一 Java虚拟机的基本结构 Java虚拟机结构 jpg 如图所示为Java虚拟机的基本结构 每个模块介绍如下 类
  • JavaFX技巧3:使用回调接口

    作为UI框架开发人员 提供自定义控件外观和行为的方法是我工作的一部分 在许多情况下 这是通过允许框架用户在控件上注册工厂来完成的 过去 我会为此创建一个工厂接口 并在框架内提供一个或多个默认实现 这些事情在JavaFX中的处理方式有所不同
  • 短视频矩阵管理系统私信群聊功能源码开发分享

    短视频获客工具的兴起 也有越来越多的企业及商家在发现了更多商机 除了在做短视频推广获客的同时 也有不少意向客户潜藏在评论区需要我们深度挖掘 那么对于一些流量比较高的账号 想在成千上万的评论区里挖掘意向客户 还是挺消耗人力的 那么一款自动化获
  • VMware虚拟机官网下载安装,虚拟机中安装Linux系统CentOS7(图文详解)

    虚拟机的安装下载和用法 第一章 VMware下载 第二章 以VMware12为例安装虚拟机 第三章 虚拟机安装Linux的CentOS7 第四章 CentOS系统设置 第五章 查看网络是否连接成功 友情提醒 先看文章目录 大致了解文章知识点
  • vue自定义指令

    除了核心功能默认内置的指令 v model 和 v show Vue 也允许注册自定义指令 有的情况下 对普通 DOM 元素进行底层操作 这时候就会用到自定义指令 下面定义了一个v test指令绑定数据name
  • 【Python】函数与模块

    函数的引入和定义 首先我们先来明确为什么Python中引入函数的概念 函数就是一部分代码模块 将这部分写好的代码模块封装成一个函数 这个函数具有你所编写的特定功能 并且以后使用时还可以调用 举个例子 就是一套你总结出来的公式 以后需要时还可
  • (一) Three.js 简介

    Three js 简介 源目录结构 组件
  • 西门子博途顺序控制车间皮带逆序停止程序

    自动控制要求 如果处于自动档 首先需要按下警示铃按钮 警示铃鸣5S后可以进行启动 如果自动档切到手动档 那么停止所有传送带并且重新鸣铃后可以进行手动测试 按下自动启动按钮后 1 5号传送带 按编号顺序启动 每次间隔五秒 如果启动过程中出现报
  • openGL之API学习(四十一)立方体贴图Cubemap

    基本上说cubemap它包含6个2D纹理 这每个2D纹理是一个立方体 cube 的一个面 也就是说它是一个有贴图的立方体 你可能会奇怪这样的立方体有什么用 为什么费事地把6个独立纹理结合为一个单独的纹理 只使用6个各自独立的不行吗 这是因为
  • Elasticsearch集群部署详解

    文章目录 Elasticsearch功能与特性 Elasticsearch 单节点安装部署 Elasticsearch 集群安装部署 附件 1 安装Java JDK 2 问题一 2 问题二 Elasticsearch功能与特性 1 分布式搜
  • SpringBoot拦截器Interceptor的使用-基础篇

    1 拦截器 Interceptor 简介 1 1 拦截器 Interceptor 介绍 拦截器是Spring中的概念 和过滤器类似 可以对用户请求进行拦截过滤处理 但是相对于过滤器而言 拦截器要的控制更加的细节 拦截器可以在三个地方进行执行
  • API是什么?深入探索编程中的应用接口

    在编程领域 API Application Programming Interface 应用程序编程接口 是指一组定义和规范了软件组件之间交互的方法和协议 它提供了一种编程接口 允许不同的软件系统之间进行通信和交互 API可以被看作是软件组
  • 函数模板与类模板的具体化

    这两天在学习 C primer 这本书时 发现有关函数与类模板的相关内容多且繁琐 而且容易混淆 因此决定写一篇博客 将它们的概念与之间的区别梳理一下 一 函数模板 在 C primer 一书中 函数模板的具体化包括了三个部分 显式具体化 隐
  • CVPR 2021|一个绝妙的想法:在类别不平衡的数据上施展半监督学习

    点击上方 视学算法 选择加 星标 或 置顶 重磅干货 第一时间送达 作者丨kid丶 知乎 已授权 来源丨https zhuanlan zhihu com p 360067653 编辑丨极市平台 CReST A Class Rebalanci
  • elasticsearch 设置seed hosts

    es集群中配置的seed hosts 通过seed hosts provider提供 provider的数据来源有集群配置文件和第三方插件提供 集群配置文件又有两种方式 一种是直接在elasticsearch yml配置文件中通过disco
  • Cocos Creator Android 平台 Facebook 原生登录

    在做海外项目中 经常需要接入Facebook SDK 现将CocosCreator Android 平台 Facebook 登录的接入流程记录下来 以备有需要的朋友做参考 一 准备工作 1 首先在facebook 开发者平台 注册账号 创建