【Unity开发】安卓应用开发中,用户进行权限请求

一、作用

在开发安卓应用时,根据功能需求获取对应的权限

1、Unity中封装好的权限

相机、麦克风、精细位置、粗略定位、存储

2、自己添加的权限

获取wifi信息、打开设置界面等

需要自己写对应的扩展

二、具体实现

1、Unity中封装好的权限

(1)创建自定义Manifest.xml文件

ProjectSettings/Player/Android/Publishing Settings/Custom Main Manifest 打开

自动创建文件 Assets/Plugins/Android/AndroidManifest.xml

(2)打开AndroidManifest.xml添加要请求的对应权限

(3)调用代码(以调用相机为例)

csharp 复制代码
	//获取相机权限
	void GetCamera()
	{
		hasCameraDeniedBefore = PlayerPrefs.GetInt("hasCameraDeniedBefore");
		if (!Permission.HasUserAuthorizedPermission(Permission.Camera))
		{
			//之前已经拒绝过,显示打开设置界面提示
			if (hasCameraDeniedBefore==1)
			{
				GFBuiltin.BuiltinView.ShowDialog(GFBuiltin.Localization.GetString("权限请求!"),
										 GFBuiltin.Localization.GetString("该功能需要打开相机权限,否则无法使用,请前往设置中进行授权"),
										 GFBuiltin.Localization.GetString("前往"),
										 GFBuiltin.Localization.GetString("拒绝"),
										 () =>
										 {
											 OpenAppSettings();
										 },
										 GFBuiltin.BuiltinView.HideDialog);
			}
			//显示权限请求弹窗
			else
			{
				GFBuiltin.BuiltinView.ShowDialog(GFBuiltin.Localization.GetString("权限请求!"),
											 GFBuiltin.Localization.GetString("请求相机权限"),
											 GFBuiltin.Localization.GetString("同意"),
											 GFBuiltin.Localization.GetString("拒绝"),
											 () =>
											 {
												 PermissionCallbacks callbacks = new PermissionCallbacks();
												 callbacks.PermissionGranted += PerssionGranted;
												 callbacks.PermissionDenied += PerssionDenied;
												 Permission.RequestUserPermission(Permission.Camera, callbacks);
											 },
											 GFBuiltin.BuiltinView.HideDialog);
			}			
		}
		else
		{
			Debug.Log("开始拍照");
		}
	}

	//权限允许回调
	void PerssionGranted(string permission)
	{
		Debug.Log(permission + "请求允许");
	}

	//权限拒绝回调
	void PerssionDenied(string permission)
	{

		// 记录对应权限已拒绝过
		if (permission == Permission.Camera)
		{
			hasCameraDeniedBefore = 1;
			PlayerPrefs.SetInt("hasCameraDeniedBefore", hasCameraDeniedBefore);
		}			
		else if (permission == Permission.FineLocation)
		{
			PlayerPrefs.SetInt("hasLocationDeniedBefore", 1);
		}
			
		else if (permission == Permission.Microphone)
		{
			PlayerPrefs.SetInt("hasLocationDeniedBefore", 1);
		}
		PlayerPrefs.Save();


		Debug.Log(permission + "请求拒绝");
		Debug.Log("权限拒绝后的值:"+hasCameraDeniedBefore);

	}

	//打开应用权限设置界面
	void OpenAppSettings()
	{
		using (var unityActivity =
			new AndroidJavaClass("com.unity3d.player.UnityPlayer")
			.GetStatic<AndroidJavaObject>("currentActivity"))
		{
			using (var intent = new AndroidJavaObject("android.content.Intent",
				"android.settings.APPLICATION_DETAILS_SETTINGS"))
			{
				string packageName = unityActivity.Call<string>("getPackageName");
				AndroidJavaObject uri = new AndroidJavaClass("android.net.Uri")
					.CallStatic<AndroidJavaObject>("parse", "package:" + packageName);

				intent.Call<AndroidJavaObject>("setData", uri);
				unityActivity.Call("startActivity", intent);
			}
		}
	}

(4)请求权限流程

(5)注意点

  • 电脑使用安卓模拟器会自动拿到需要的权限,不会像用户进行请求
  • 在请求权限时,用户选择拒绝并不再询问(在较新的 Android 版本中,它通过第二次拒绝来表达)或操作系统确定不再需要请求时执行。如果未订阅此事件,PermissionCallbacks.PermissionDenied 将作为后备触发。在较新的 Android 版本上不可靠,建议仅连接到PermissionCallbacks.PermissionDenied。

2、自己扩展的权限调用(以Wifi信息获取为例)

(1)在 Assets/Plugins/Android/AndroidManifest.xml文件中添加对应的权限

(2)写对应的java插件放在Assets/Plugins/Android文件夹下

java 复制代码
//java文件内容
package com.example.networkinfo;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;

import com.unity3d.player.UnityPlayer;

public class NetworkInfoPlugin {

    private static Context getContext() {
        return UnityPlayer.currentActivity.getApplicationContext();
    }

    // 获取网络类型(安全)
    public static String getNetworkType() {
        ConnectivityManager cm =
            (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);

        if (cm == null) return "No Network";

        NetworkCapabilities nc = cm.getNetworkCapabilities(cm.getActiveNetwork());
        if (nc == null) return "No Network";

        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
            return "WiFi";

        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
            return "Cellular";

        return "Unknown";
    }

    // 获取 WiFi 名称
    public static String getWifiSSID() {
        WifiManager wm =
            (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
        if (wm == null) return "";

        WifiInfo info = wm.getConnectionInfo();
        if (info == null) return "";

        return info.getSSID();
    }

    // WiFi 信号强度(0-100)
    public static int getWifiSignalLevel() {
        WifiManager wm =
            (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
        if (wm == null) return 0;

        WifiInfo info = wm.getConnectionInfo();
        if (info == null) return 0;

        return WifiManager.calculateSignalLevel(info.getRssi(), 100);
    }
}

(3)进行调用

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using System.Security;
using UnityEngine;

public class WifiPermission
{
	static AndroidJavaClass pluginClass;
	public WifiPermission()
	{
		pluginClass = new AndroidJavaClass("com.example.networkinfo.NetworkInfoPlugin");
	}


#if UNITY_EDITOR
	public string GetNetworkType()
	{
		switch (Application.internetReachability)
		{
			case NetworkReachability.NotReachable:
				return "No Network";
			case NetworkReachability.ReachableViaCarrierDataNetwork:
				return "Mobile Data";
			case NetworkReachability.ReachableViaLocalAreaNetwork:
				return "WiFi";
			default:
				return "Unknown";
		}
	}

	public string GetNetworkName()
	{
		return "PC端无法获取网络名称";
	}
	public int GetNetworkLevel()
	{
		return 0;
	}
	public void OpenWifiSettings()
	{
		//模拟Wifi界面 
		GFBuiltin.BuiltinView.ShowDialog("WiFi设置界面", "是否连接WiFi", "连接", "取消");
	}



#elif UNITY_ANDROID
	public string GetNetworkType()
	{
		return pluginClass.CallStatic<string>("getNetworkType");
	}
	
	public string GetNetworkName()
	{
		return pluginClass.CallStatic<string>("getWifiSSID");
	}

	public int GetNetworkLevel()
	{
		return pluginClass.CallStatic<int>("getWifiSignalLevel");
	}

	public void OpenWifiSettings()
	{
        using (AndroidJavaClass unityPlayer =
               new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            AndroidJavaObject activity =
                unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

            using (AndroidJavaObject intent =
                   new AndroidJavaObject("android.content.Intent",
                       "android.settings.WIFI_SETTINGS"))
            {
                activity.Call("startActivity", intent);
            }
        }
	}

#elif UNITY_IOS
	//TODO

#else
	public string GetNetworkType()
	{
		return "Not supported";
	}
	public string GetNetworkName()
	{
		return "Not supported";
	}
	public int GetNetworkLevel()
	{
		return 0;
	}
	public void OpenWifiSettings()
	{
		//模拟Wifi界面
		GFBuiltin.BuiltinView.ShowDialog("WiFi设置界面", "是否连接WiFi", "连接", "取消");
	}
#endif

}
相关推荐
Android打工仔12 分钟前
Kotlin 协程源码解析:DispatchedContinuation 里的 Dispatcher 从哪里来?
android·kotlin
打工仔折腾 AI24 分钟前
从BPE到SentencePiece:Transformer分词原理与Python实战对比
android·人工智能·python·深度学习·langchain·transformer·ai agent 实战
Dovis(誓平步青云)1 小时前
几个方案来回选不定?做一个随时切换的候选推荐页
android·java·服务器·开发语言·javascript·数据库·智能化
小贺儿开发2 小时前
Unity 文物新生 会讲故事的文物展墙
人工智能·科技·unity·ai·视频·互动·演示
恋猫de小郭5 小时前
KMP 又改了编译流程, Separate Compilation 禁止了 `commonMain` 的依赖穿透
android·前端·flutter
执明wa5 小时前
Android RecyclerView 实战:点击频道栏切换对应内容
android·开发语言·windows·microsoft·android studio
新鲜势力呀5 小时前
PHP 定时数据同步实战:从第三方接口超时到异步同步 + 增量更新架构优化全过程
android
淡海水7 小时前
02-03-原理篇-大对象堆
unity·c#·游戏引擎·.net·gc
星间都市山脉7 小时前
RecoveryUI 圆角屏安全边距配置及代码调用链
android·java·linux·windows·ubuntu
打工仔折腾 AI7 小时前
DiPlay 实测:iPhone 绕过硬件盒子直连 BYD 车机的思路拆解
android·人工智能·后端·python·gradle·iphone·ai agent 实战