Unity 之 Android 【获取设备的序列号 (Serial Number)/Android_ID】功能的
Unity 之 Android 【获取设备的序列号 (Serial Number)/Android_ID】功能的简单封装目录
Unity 之 Android 【获取设备的序列号 (Serial Number)/Android_ID】功能的简单封装
一、简单先容
二、获取设备的序列号 (Serial Number) 实现原理
1、Android
2、 Unity
三、注意实现
四、案例实现简单步骤
五、关键代码
一、简单先容
Unity 是一个功能强大的跨平台游戏引擎,广泛用于开发视频游戏和其他及时3D互动内容,如模拟器和虚拟实际应用。
游戏引擎:
[*] Unity:Unity Technologies 开发的跨平台游戏引擎,支持2D和3D图形、物理引擎、音频、视频、网络和多平台发布。
[*] 跨平台支持:Unity 支持在多个平台上发布,包罗 Windows、macOS、Linux、iOS、Android、WebGL、PlayStation、Xbox、Switch 等。
开发环境:
[*] Unity Editor:用于创建和管理 Unity 项目的集成开发环境(IDE)。开发者可以在其中创建场景、设计关卡、编写代码和调试游戏。
[*] 场景(Scene):Unity 中的根本构建块,一个场景可以被视为一个关卡或一个游戏中的独立部分。
编程语言:
[*] C#:重要编程语言。Unity 使用 C# 脚本来控制游戏对象和实现游戏逻辑。
[*] UnityScript(已弃用):曾经支持的 JavaScript 变种,但已经被弃用。
Unity 进阶开发涉及更复杂的技能和更深入的知识,以创建高性能、复杂和专业的游戏和应用程序。以下是一些 Unity 进阶开发的关键领域和技能:
设计模式:
[*] 学习和应用常见的设计模式(如单例模式、工厂模式、观察者模式)以便更好地组织和管理代码。
异步编程:
[*] 使用 C# 的 async 和 await 关键字进行异步编程,以进步应用的相应速度和性能。
依赖注入:
[*] 使用依赖注入(如 Zenject)来管理对象的依赖关系,减少耦合,进步代码的可测试性和可维护性。
二、获取设备的序列号 (Serial Number) 实现原理
1、Android
在 Android 10 及以上版本,由于隐私和安全缘故起因,获取设备的序列号 (SN) 变得更加受限。
在 Android 10 及以上版本,可以使用 Build.getSerial() 方法来获取设备的序列号。不过,这需要获取 READ_PRIVILEGED_PHONE_STATE 权限,该权限仅限于系统应用。因此,对于普通应用,可以使用 Build.SERIAL 作为替代,但在 Android 10 上,这个常量已经被弃用并会返回一个占位符值。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String serial = Build.getSerial();
} else {
String serial = Build.SERIAL;
}
需要注意的是,在 Android 9(API 28)及以下版本,Build.SERIAL 可以直接使用。在 Android 10 及以上版本,需要系统权限。
2、 Unity
在 Unity 中开发 Android 应用时,获取设备的序列号(SN)也受到 Android 10 及以上版本隐私和安全策略的影响。以下是怎样在 Unity 中实现这些功能的方法:
对于 Android 10 及以上版本,获取设备序列号需要使用 Build.getSerial() 方法,并且需要特定的权限。由于 Unity 使用 C# 代码,你需要通过调用 Java 方法来实现这一点。
1)首先,需要在 AndroidManifest.xml 文件中声明权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
2)然后,使用 Unity 的 AndroidJavaObject 类来调用 Java 代码:
using UnityEngine;
public class DeviceInfo : MonoBehaviour
{
public string GetSerialNumber()
{
string serialNumber = "Unknown";
if (Application.platform == RuntimePlatform.Android)
{
try
{
using (AndroidJavaClass buildClass = new AndroidJavaClass("android.os.Build"))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
using (AndroidJavaObject buildObject = buildClass.CallStatic<AndroidJavaObject>("getSerial"))
{
serialNumber = buildObject.Call<string>("toString");
}
}
else
{
serialNumber = buildClass.GetStatic<string>("SERIAL");
}
}
}
catch (System.Exception e)
{
Debug.LogError("Error getting serial number: " + e.Message);
}
}
return serialNumber;
}
}
三、注意实现
[*]权限管理:确保在运行时请求须要的权限,特别是在 Android 6.0(API 23)及以上版本中,动态权限请求是必需的。
[*]兼容性检查:由于不同 Android 版本的行为可能不同,代码中需要进行版本检查。
[*]隐私合规:获取设备的敏感信息时,请确保应用符合相干的隐私政策和法律法规,关照用户并获得须要的同意。
通过上述步骤,你应该可以大概在 Unity 中乐成获取 Android 10 及以上版本设备的序列号。
四、案例实现简单步骤
1、创建 Unity 工程
https://img-blog.csdnimg.cn/direct/1cd66ffedee24c828957cbb9965b20a9.png
2、新建脚本 DeviceInfo ,编写代码获取设备的序列号
https://img-blog.csdnimg.cn/direct/f6292b951afd465b87d180eda0800dfd.png
3、由于这个可能需要权限申请,编写代码申请权限
https://img-blog.csdnimg.cn/direct/65a06373a276481e967aa86d65ddced9.png
4、实现申请电话权限,获取设备序列号(TestDeviceInfo.cs)
https://img-blog.csdnimg.cn/direct/ec8581c68d084b0ca26c439fa17d5175.png
5、把脚本 TestDeviceInfo.cs 挂载到场景中
https://img-blog.csdnimg.cn/direct/3fd7e33104b244d397ff9b22bfc5f9ce.png
6、在 Player Settings 中的 Build 中勾选 Custom Main Manifest ,添加相干 Phone 权限申请
https://img-blog.csdnimg.cn/direct/c7e60d7941e84be89a69d1c6982d62a7.png
https://img-blog.csdnimg.cn/direct/59bc8992d8074351a7a7938682488d47.png
7、打包运行,可能报如下错误
Exception getting serial number: java.lang.SecurityException: getSerial: The uid 10170 does not meet the requirements to access device identifiers.
https://img-blog.csdnimg.cn/direct/29fd72e3f58043e3b33d645daea949bd.png
错误表明尝试获取设备序列号时碰到了权限问题。在 Android 10(API level 29)及以上版本中,获取设备的序列号需要特别权限,而这些权限通常不适用于普通应用程序。使用 Settings.Secure.ANDROID_ID 是一种更合适的替代方案,因为它不需要这些特别权限。
8、下面是怎样精确使用 Settings.Secure.ANDROID_ID 来获取设备的 Android ID:
/// <summary>
/// 获取设备的 Android ID
/// </summary>
/// <returns></returns>
public static string GetAndroidId()
{
string deviceId = string.Empty;
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
using (AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver"))
{
using (AndroidJavaClass secure = new AndroidJavaClass("android.provider.Settings$Secure"))
{
deviceId = secure.CallStatic<string>("getString", contentResolver, "android_id");
}
}
}
}
catch (AndroidJavaException e)
{
Debug.LogError("Exception getting Android ID: " + e.Message);
}
#endif
return deviceId;
}
9、打包运行,能获取到 设备的 Android ID
https://img-blog.csdnimg.cn/direct/50de8de9f57b4c4ea9b5daef5e2664c8.png
10、获取设备的 Android ID的 注意事项
[*] 唯一性:
[*]ANDROID_ID 在设备重置时可能会更改,因此不能作为硬件唯一标识符使用,但对于大多数应用场景,它足够可靠。
[*] 权限:
[*]由于不涉及敏感权限,你不需要在 AndroidManifest.xml 中添加任何额外权限。
五、关键代码
1、DeviceInfo
using UnityEngine;public class DeviceInfo { /// <summary> /// 获取设备序列号 /// 需要系统权限 /// </summary> public static string GetSerialNumber() { string serialNumber = string.Empty;#if UNITY_ANDROID && !UNITY_EDITOR try { using (AndroidJavaClass buildClass = new AndroidJavaClass("android.os.Build")) { if (GetSDKInt() >= 26) // Build.VERSION_CODES.O == 26 { serialNumber = buildClass.CallStatic<string>("getSerial"); } else { serialNumber = buildClass.GetStatic<string>("SERIAL"); } } } catch (AndroidJavaException e) { Debug.LogError("Exception getting serial number: " + e.Message); }#endif return serialNumber; } /// <summary> /// 获取版本 /// </summary> /// <returns></returns> private static int GetSDKInt() { int sdkInt = 0;#if UNITY_ANDROID && !UNITY_EDITOR using (AndroidJavaClass versionClass = new AndroidJavaClass("android.os.Build$VERSION")) { sdkInt = versionClass.GetStatic<int>("SDK_INT"); }#endif return sdkInt; } /// <summary>
/// 获取设备的 Android ID
/// </summary>
/// <returns></returns>
public static string GetAndroidId()
{
string deviceId = string.Empty;
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
using (AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver"))
{
using (AndroidJavaClass secure = new AndroidJavaClass("android.provider.Settings$Secure"))
{
deviceId = secure.CallStatic<string>("getString", contentResolver, "android_id");
}
}
}
}
catch (AndroidJavaException e)
{
Debug.LogError("Exception getting Android ID: " + e.Message);
}
#endif
return deviceId;
}}
2、PermissionWrapper
using UnityEngine;
using UnityEngine.Android;
public class PermissionWrapper : MonoSingleton<PermissionWrapper>
{
/// <summary>
/// 请求权限
/// </summary>
/// <param name="permission">权限名称</param>
/// <param name="callback">权限回调:true 权限获取成功回调,false 权限获取失败回调</param>
public void RequestPermission(string permission, System.Action<string, bool> callback)
{
if (Permission.HasUserAuthorizedPermission(permission))
{
callback?.Invoke(permission, true);
}
else
{
StartCoroutine(RequestAndCheckPermission(permission, callback));
}
}
/// <summary>
/// 协程请求权限
/// </summary>
/// <param name="permission">权限名称</param>
/// <param name="callback">权限回调:true 权限获取成功回调,false 权限获取失败回调</param>
/// <returns></returns>
private System.Collections.IEnumerator RequestAndCheckPermission(string permission, System.Action<string, bool> callback)
{
Permission.RequestUserPermission(permission);
yield return new WaitForSeconds(1.0f);
bool granted = Permission.HasUserAuthorizedPermission(permission);
callback?.Invoke(permission, granted);
}
}
3、TestDeviceInfo
using UnityEngine;
public class TestDeviceInfo : MonoBehaviour
{
/// <summary>
/// TAG
/// </summary>
const string TAG = " ";
// Start is called before the first frame update
void Start()
{
GetSerialNumber();
}
private void GetSerialNumber()
{
string permission = "android.permission.READ_PHONE_STATE";
string sn = string.Empty;
PermissionWrapper.Instance.RequestPermission(permission, (permission, isGranted) => {
if (isGranted)
{
//sn = DeviceInfo.GetSerialNumber();
sn = DeviceInfo.GetAndroidId();
}
else
{
sn = "unknown";
}
Debug.Log(TAG + "GetAndroidId() = " + sn);
});
}
}
4、AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools">
<!-- 获取 sn 的权限 Start-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<!-- 获取 sn 的权限 End-->
<application>
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:theme="@style/UnityThemeSelector">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
</manifest>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]