Android 接入Facebook实现第三方登陆教程(精简版)

本文详细介绍如何集成Facebook登录功能,包括动态获取keyhashes的方法、SDK集成步骤及初始化过程,并提供了一个二次封装的实用工具类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先需要在Facebook官方注册你的应用,这个不用说,需要注意的是在创建应用的时候需要填写应用的key hashes ,这个可以用cmd命令获取,也可以用代码动态获取,我是用代码动态获取的,下面贴下方法:

// Add code to print out the key hash
    @SuppressLint("NewApi")
    private fun getKeyHashValue() {
        try {
            val info = activity!!.getPackageManager().getPackageInfo(
                    "com.wj.demo",
                    PackageManager.GET_SIGNATURES)
            for (signature in info.signatures) {
                val md = MessageDigest.getInstance("SHA")
                md.update(signature.toByteArray())
                Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT))
            }
        } catch (e: PackageManager.NameNotFoundException) {
            Log.d("KeyHash:",e.toString())
        } catch (e: NoSuchAlgorithmException) {
            Log.d("KeyHash:", e.toString())
        }

    }

然后把打印出来的字符串填写到Facebook开发者后台的key Hashes里面就可以了
这里写图片描述

然后开始在项目里面集成sdk和初始化sdk,调用登陆方法进行登陆:
在project级别的目录下的build.gradle文件种配置

repositories {
        mavenCentral()
    }

在app级别的目录下的build.gradle文件种配置sdk依赖:

  compile 'com.facebook.android:facebook-android-sdk:4.6.0'

在清单文件种配置下面:

<meta-data
        android:name="com.facebook.sdk.ApplicationId"
        android:value="@string/facebook_app_id" />

        <provider
            android:name="com.facebook.FacebookContentProvider"
            android:authorities="com.facebook.app.FacebookContentProvider5555302316225142"
            android:exported="true" />

        <activity
            android:name="com.facebook.FacebookActivity"
            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
            android:label="@string/app_name" />

在application种初始化sdk:

 FacebookSdk.sdkInitialize(applicationContext)

写登陆的关键代码,我这里整理到了工具类种FaceBookLoginUtil.kt:

import android.annotation.SuppressLint
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.util.Base64
import com.facebook.*
import com.facebook.login.LoginManager
import com.facebook.login.LoginResult
import org.json.JSONObject
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*


/**
 * @Description:  facebook 登陆二次封装
 * @Author: wjj
 * @Time:   2018/6/26 15:24
 */
class FaceBookLoginUtil {

    val TAG = "FaceBookLoginUtil"

    var activity: Activity? = null

    var loginManager: LoginManager? = null

    var call: CallbackManager? = null

    var loginListener:FacebookListener? = null

    var mName :String = ""
    var mPhoto :String = ""

    var mYear :String = "0"
    var mMonth :String = "0"
    var mDay :String = "0"

    /*初始化*/
    constructor(activity: Activity, loginListener: FacebookListener) {
        this.activity = activity
        this.loginListener = loginListener
        getKeyHashValue()
        //初始化facebook登录服务
        call = CallbackManager.Factory.create()
        loginManager = LoginManager.getInstance()
        loginManager?.registerCallback(call,
                object : FacebookCallback<LoginResult> {
                    override fun onSuccess(loginResult: LoginResult) {
                        Log.e(TAG, "onSuccess")
                        var accessToken = loginResult.getAccessToken()
                        userInfo(accessToken)
                    }

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

                    override fun onError(exception: FacebookException) {
                        Log.e(TAG, "onError")
                        loginListener.onError()
                    }
                })
    }

    // Add code to print out the key hash
    @SuppressLint("NewApi")
    private fun getKeyHashValue() {
        try {
            val info = activity!!.getPackageManager().getPackageInfo(
                    "com.wj.demo",
                    PackageManager.GET_SIGNATURES)
            for (signature in info.signatures) {
                val md = MessageDigest.getInstance("SHA")
                md.update(signature.toByteArray())
                Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT))
            }
        } catch (e: PackageManager.NameNotFoundException) {
            Log.d("KeyHash:",e.toString())
        } catch (e: NoSuchAlgorithmException) {
            Log.d("KeyHash:", e.toString())
        }

    }

    //登陆
    fun login() {
        loginManager?.logInWithReadPermissions(activity, Arrays.asList("public_profile", "user_friends", "user_status", "user_birthday", "user_location", "user_hometown"))
    }


    //登出
    fun logout() {
        loginManager!!.logOut()
    }


    fun getCallbackManager(): CallbackManager {
        return this!!.call!!
    }

    /*获取个人信息*/
    fun userInfo(accessToken: AccessToken) {

        var request = GraphRequest.newMeRequest(accessToken, object : GraphRequest.GraphJSONObjectCallback {
            override fun onCompleted(obj: JSONObject?, response: GraphResponse?) {
                //获取个人信息
                val facebook_name = obj?.optString("name")
                //生日
                val facebook_birthday = (obj?.optString("birthday").toString()).replace("/", "", true).trim()
                if (facebook_birthday.length!=0){

                    mDay = facebook_birthday.substring(0, 2)
                    mMonth = facebook_birthday.substring(2, 4)
                    mYear = facebook_birthday.substring(4, 8)
                }

                //获取用户头像
                val object_pic = obj?.optJSONObject("picture")
                val object_data = object_pic?.optJSONObject("data")
                val facebook_photo = object_data?.optString("url")

                mName = facebook_name!!
                mPhoto = facebook_photo!!

                SharedPreferencesUnitls.setParam(activity,"name",mName)
                SharedPreferencesUnitls.setParam(activity,"mPhoto",mPhoto)
                SharedPreferencesUnitls.setParam(activity, "comeTimeY", mYear)
                SharedPreferencesUnitls.setParam(activity, "comeTimeM", mMonth)
                SharedPreferencesUnitls.setParam(activity, "comeTimeD", mDay)


                loginListener?.onSuccess()
            }

        })
        var parameters = Bundle()
        parameters.putString("fields", "id,name,link,gender,birthday,email,picture,locale,updated_time,timezone,age_range,first_name,last_name")
        request.parameters = parameters
        request.executeAsync()
    }



    interface FacebookListener{
        fun onSuccess()
        fun onCancel()
        fun onError()
    }


}

然后调用关键代码:

class LoginActivity:Activity(){

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_login)   
      faceBookLoginUtil = FaceBookLoginUtil(this, object : FaceBookLoginUtil.FacebookListener {
            override fun onSuccess() {
                Toast.makeText(this@LoginActivity, "login success", Toast.LENGTH_SHORT).show()
                var intent = Intent(this@LoginActivity,HomeActivity().javaClass)
                startActivity(intent)
                finish()
            }

            override fun onCancel() {
                Toast.makeText(this@LoginActivity, "Cancel the login", Toast.LENGTH_SHORT).show()
            }

            override fun onError() {
                Toast.makeText(this@LoginActivity, "Loading failure", Toast.LENGTH_SHORT).show()
            }
        })


         //点击登陆的按钮后调用fb登陆
                faceBookLoginUtil?.login()

    }


}
<think>嗯,用户想在Kotlin的安卓应用中使用FastText模型。首先,我得确认FastText是什么。FastText是Facebook开发的一个文本分类和词向量表示库,对吧?它通常用于自然语言处理任务,比如文本分类或者词嵌入。但安卓应用中使用的话,可能需要考虑模型的大小和性能。 用户可能已经有一个训练好的FastText模型,或者打算在应用里训练,不过通常应该是加载预训练模型。安卓应用中使用机器学习模型的话,通常需要考虑模型格式和推理库的兼容性。 首先想到的是,FastText原生是用C++写的,所以直接集成到安卓可能不太方便。有没有Java或Kotlin的绑定呢?或者有没有办法将模型转换成TensorFlow Lite格式?或者使用JNI调用C++库? 接下来,可能步骤是:1. 将FastText模型转换成适合移动端的格式;2. 在安卓项目中集成推理库;3. 编写Kotlin代码加载模型并进行预测。 用户可能需要先导出模型为.bin文件,然后考虑如何加载。但直接使用C++库的话,需要配置NDK,这对部分开发者可能有难度。或者有没有现成的库可以使用?比如,有人可能已经封装了FastText的Android库,或者可以使用其他方式。 另一个思路是使用ONNX运行时,如果FastText模型可以转成ONNX格式,然后在安卓上运行。但不确定FastText是否支持导出到ONNX。或者,用户可能需要自己实现模型的前向传播,如果模型结构不太复杂的话。 或者,用户是否考虑使用其他类似的轻量级模型,比如TensorFlow Lite的文本分类模型?但用户明确提到FastText,所以应该针对这个模型解答。 可能的步骤是:将FastText模型转换为tflite格式,但需要确认是否支持。或者,使用JNI封装FastText的C++库,然后在Kotlin中调用。这可能需要编写C++代码和JNI接口,然后在安卓项目中配置。 另外,模型文件可能较大,需要考虑应用体积,可能需要模型压缩或使用较小的模型。 然后,关于如何在Kotlin中加载模型,可能涉及到将模型文件放在assets目录下,读取后通过JNI传递给C++代码进行处理。或者使用已经存在的Java封装库,比如可能有人开发了FastText的Android端口。 需要检查是否有现成的开源项目,比如GitHub上的FastText Android示例。假设用户没有现成的库,可能需要指导他们如何通过JNI集成。 另外,预处理输入文本,分词,然后调用模型获取输出,比如分类结果或词向量。 可能遇到的挑战包括:模型加载速度、内存占用、线程管理、性能优化等。 总结步骤可能是: 1. 导出FastText模型为.bin文件。 2. 将模型文件放入安卓项目的assets目录。 3. 集成FastText的C++库到安卓项目,使用NDK构建。 4. 编写JNI接口函数,用于模型加载和预测。 5. 在Kotlin中调用这些JNI方法。 或者,如果有现成的Java库,可以简化步骤。例如,使用Java版本的FastText实现,但需要确认是否存在。 另外,模型可能较大,需考虑APK大小,可能需要动态下载模型。 或者,使用第三方库,比如fastText-Android,如果有的话。需要让用户去GitHub查找相关库。 如果用户不熟悉NDK,这个过程可能比较复杂。可能需要简化步骤,或者建议使用替代方案。 可能需要分步骤详细说明,包括如何配置NDK,编写CMakeLists.txt,处理模型文件,以及Kotlin调用示例。 另外,注意性能问题,模型推理应在后台线程执行,避免阻塞UI线程。 可能还需要处理文本预处理,比如分词、过滤等,与FastText的要求一致。 综上,回答的结构应该是:先说明可能的方案,然后分步骤介绍如何集成C++库,编写JNI接口,并在Kotlin中使用,同时提到可能的替代方案和注意事项。</think>在Android应用中使用FastText模型可分为以下几个步骤,这里以`.bin`预训练模型为例进行说明: --- ### **Step 1 - 模型准备** 1. **获取模型** 从[FastText官网](https://fasttext.cc/docs/en/pretrained-vectors.html)下载预训练模型(如`cc.en.300.bin`),或使用自己的训练模型。 2. **精简模型(可选)** 使用FastText官方工具裁剪词表,减少模型体积: ```bash ./fasttext reduce-model your_model.bin 200000 > compressed_model.bin ``` --- ### **Step 2 - 集成FastText到Android** #### 方案一:通过JNI调用C++库(推荐) 1. **配置NDK** 在`build.gradle`中启用NDK: ```gradle android { defaultConfig { ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' } } } ``` 2. **导入FastText源码** 将[FastText C++源码](https://github.com/facebookresearch/fastText)复制到`app/src/main/cpp/fasttext`目录。 3. **编写JNI接口** 创建`jni_wrapper.cpp`,暴露加载模型和预测方法: ```cpp #include <jni.h> #include "fasttext/src/fasttext.h" extern "C" JNIEXPORT jlong JNICALL Java_com_example_app_FastTextWrapper_loadModel(JNIEnv *env, jobject, jstring path) { const char *modelPath = env->GetStringUTFChars(path, 0); auto *fastText = new fasttext::FastText(); fastText->loadModel(modelPath); env->ReleaseStringUTFChars(path, modelPath); return reinterpret_cast<jlong>(fastText); } extern "C" JNIEXPORT jstring JNICALL Java_com_example_app_FastTextWrapper_predict(JNIEnv *env, jobject, jlong ptr, jstring text) { auto *fastText = reinterpret_cast<fasttext::FastText *>(ptr); // 实现预测逻辑 } ``` 4. **配置CMake** 在`CMakeLists.txt`中添加FastText源码编译: ```cmake add_library( fasttext SHARED src/main/cpp/fasttext/src/*.cc ) ``` #### 方案二:使用Java封装库(简化) 若不想处理NDK,可使用第三方Java封装库如[fastText-for-Java](https://github.com/vinhkhuc/kotlin-fasttext),但性能可能略低。 --- ### **Step 3 - Kotlin调用逻辑** 1. **封装Native方法** ```kotlin class FastTextWrapper { external fun loadModel(modelPath: String): Long external fun predict(modelPtr: Long, text: String): String companion object { init { System.loadLibrary("native-lib") // 对应CMake生成库名 } } } ``` 2. **加载模型** 将模型文件放入`assets/`目录,运行时复制到本地: ```kotlin fun copyModelToStorage(context: Context): File { val modelFile = File(context.filesDir, "fasttext_model.bin") if (!modelFile.exists()) { context.assets.open("fasttext_model.bin").use { input -> FileOutputStream(modelFile).use { output -> input.copyTo(output) } } } return modelFile } ``` 3. **执行预测** ```kotlin val modelPtr = FastTextWrapper().loadModel(modelFile.absolutePath) val result = FastTextWrapper().predict(modelPtr, "Hello world") ``` --- ### **注意事项** 1. **线程安全** 模型加载和预测应在后台线程执行,避免阻塞UI。 2. **模型大小** 若模型超过100MB,建议通过网络动态下载。 3. **性能优化** 使用`quantize`压缩模型或限制词表大小。 4. **错误处理** 添加JNI异常捕获: ```cpp try { // FastText操作 } catch (const std::exception &e) { env->ThrowNew(env->FindClass("java/lang/Exception"), e.what()); } ``` --- ### **替代方案** 若需更高兼容性,可考虑: 1. 将FastText模型转换为TensorFlow Lite格式。 2. 使用服务器API部署模型,App通过网络请求调用。 根据项目需求选择最适合的方案。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值