You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity与Android Studio数据交互:从原生App传Token至Unity脚本

我刚好做过类似的Unity与Android原生集成的项目,给你分享下可行的解决方案:

1. 通过Intent向Unity脚本传递数据

这完全可行,分两种场景处理:

场景1:启动Unity库Activity时传递数据

在原生Android端启动Unity对应的Activity(通常是UnityPlayerActivity或你自定义的继承类)时,把数据存入Intent的Extra中,再在Unity的C#脚本中读取。

Android端代码(Kotlin示例):

val intent = Intent(this, UnityPlayerActivity::class.java)
intent.putExtra("USER_TOKEN", yourEncryptedToken) // 可传加密或已解密的Token,按需选择
startActivity(intent)

Unity端C#代码:

在Unity的启动GameObject上挂载如下脚本,获取并读取Intent数据:

using UnityEngine;

public class TokenHandler : MonoBehaviour
{
    void Start()
    {
        // 获取Android当前Activity的Intent实例
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>("getIntent");

        // 读取传递的Token
        if (intent.Call<bool>("hasExtra", "USER_TOKEN"))
        {
            string receivedToken = intent.Call<string>("getStringExtra", "USER_TOKEN");
            Debug.Log("从Android端收到Token: " + receivedToken);
            // 后续用该Token处理服务器请求逻辑
        }
    }
}

场景2:UnityActivity已启动后传递数据

如果Unity已在后台运行,用UnityPlayer.UnitySendMessage直接调用Unity方法会比Intent更高效:

Android端发送数据:

// 参数说明:Unity中接收数据的GameObject名称、脚本中的方法名、传递的Token字符串
UnityPlayer.UnitySendMessage("TokenHandlerObject", "OnReceiveToken", decryptedToken)

Unity端接收方法:

public class TokenHandler : MonoBehaviour
{
    // 方法名需与Android端调用的完全一致
    public void OnReceiveToken(string token)
    {
        Debug.Log("通过UnitySendMessage收到Token: " + token);
        // 处理Token逻辑
    }
}
2. Unity中解密Token的可行方案

优先推荐在Android端解密后再传递给Unity,因为加密逻辑原本在原生层,解密也在原生层处理更安全,避免密钥等敏感信息暴露到Unity层。如果必须在Unity中解密,提供两种思路:

方案A:Android端解密后传递(推荐)

利用Encrypted SharedPreference的API在Android端解密Token,再通过上述UnitySendMessage传递:

Android端解密代码示例(Kotlin):

// 初始化加密SharedPreference
val masterKey = MasterKey.Builder(this)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
    .build()

val encryptedPrefs = EncryptedSharedPreferences.create(
    this,
    "your_encrypted_prefs_name",
    masterKey,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

// 获取并解密Token
val decryptedToken = encryptedPrefs.getString("user_token", "") ?: ""
// 传递给Unity
UnityPlayer.UnitySendMessage("TokenHandlerObject", "OnReceiveToken", decryptedToken)

方案B:Unity端实现解密逻辑

如果必须在Unity中解密,要确保C#的解密算法与Android端Encrypted SharedPreference使用的完全一致(默认是AES-256-GCM/SIV组合)。但注意:Android的MasterKey存储在系统Keystore中,无法直接获取,这种方式存在安全风险,仅适合自定义加密场景(比如你自己管理密钥)。

Unity端AES解密示例(C#):

using System;
using System.Security.Cryptography;
using System.Text;

public class TokenDecryptor
{
    // 需保证key、iv、加密模式/填充方式与Android端完全一致
    public static string DecryptAes(string encryptedToken, byte[] key, byte[] iv)
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = key;
            aesAlg.IV = iv;
            aesAlg.Mode = CipherMode.CBC;
            aesAlg.Padding = PaddingMode.PKCS7;

            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            byte[] encryptedBytes = Convert.FromBase64String(encryptedToken);
            byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);

            return Encoding.UTF8.GetString(decryptedBytes);
        }
    }
}
注意事项
  • 安全层面:Token是敏感信息,尽量减少明文传递次数,在Android端解密后仅传递一次,用完及时销毁内存中的明文Token。
  • 集成验证:确保Unity作为Library的集成步骤正确,UnityPlayer类可正常调用。
  • 数据类型:Intent传递优先用字符串,避免复杂对象带来的序列化问题。

内容的提问来源于stack exchange,提问作者Pankaj Sharma

火山引擎 最新活动