Unity2019中的android动态申请权限(Permissions)
目录1.先上最终研究成果(unity已经提供了面向Android的 权限申请方法)2.疑难问题3.原理解析:1.先上最终研究成果(unity已经提供了面向Android的 权限申请方法)ex:UnityEngine.Android.Permission.RequestUserPermission(s);重要提示:使用unity的动态权限申请可以动态的弹出是否同意该权限......
请使用最新文章:
Unity2022中的android权限处理(Permissions)
动态权限,权限弹窗
注意事项:
1.因为新规等因素需要提前弹出游戏自己的权限描述界面
2.玩家连续多次拒绝权限的处理
下面的文章可以参考android的实现原理,代码已过时
目录
第一步 unity activity中设置屏蔽android权限弹窗,避免一点开应用各种权限无序弹出
第三步 对于实在搞不明白Android权限申请处理和弹窗的,提供个三方类库,直接引用使用(easypermissions)
1.unity2019中已经提供了面向Android的 权限申请方法
4.ex:unity+android权限--打开应用不弹权限,动态请求权限 完整例子展示
0.unity2020 最正确的权限处理打开方式
第一步 unity activity中设置屏蔽android权限弹窗,避免一点开应用各种权限无序弹出
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
<application
android:name="com.longtu.android.channels.Info.LTBase_Channels_Application"
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:label="@string/app_name">
<activity android:name="com.longtugame.rjsdk.MainActivity"
android:configChanges="orientation|keyboard|keyboardHidden|screenLayout|screenSize"
android:allowEmbedded="@string/app_name"
android:exported = "true"
android:theme="@android:style/Theme.NoTitleBar">
<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" />
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
</activity>
第二步 在C#中指定调用接口,方便控制各个功能的权限弹出
/// <summary>
/// 极光初始化(初始化接口,请求必须权限,打开极光推送日志)
/// </summary>
public static void LT_JPushInit()
{
s_LTSDKImpl.LT_RequestPermissions();
s_LTSDKImpl.LT_SetDebugMode(true);
s_LTSDKImpl.LT_JPushInit();
}
第三步 对于实在搞不明白Android权限申请处理和弹窗的,提供个三方类库,直接引用使用(easypermissions)
具体可百度easypermissions框架使用,
也可参考:
Android调用相册、相机(兼容6.0、7.0、8.0)_P_Frank的博客-CSDN博客_android打开相册
//动态权限申请库
implementation 'pub.devrel:easypermissions:1.3.0'
1.unity2019中已经提供了面向Android的 权限申请方法
其实调用的是Android内的方法,不过还是建议使用Android原生方法进行判断,可以监听权限申请结果和判断。
ex:UnityEngine.Android.Permission.RequestUserPermission(s);
重要提示:使用unity的动态权限申请可以动态的弹出是否同意该权限界面,方便了很多
string[] strs=new string[] {
"android.permission.INTERNET",
"android.permission.READ_PHONE_STATE",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.ACCESS_WIFI_STATE",
"android.permission.ACCESS_NETWORK_STATE",
"android.permission.GET_TASKS",
"android.permission.REQUEST_INSTALL_PACKAGES",
"android.permission.WAKE_LOCK",
"android.permission.SYSTEM_ALERT_WINDOW",
"android.permission.CHANGE_WIFI_STATE",
"android.permission.CHANGE_NETWORK_STATE",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.SYSTEM_OVERLAY_WINDOW",
"android.permission.ACCESS_COARSE_UPDATES",
"android.permission.WRITE_SETTINGS",
"android.permission.BATTERY_STATS",
"android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
};
// Use this for initialization
void Start () {
Debug.Log("start main");
// var iscon= PlayerConnection.instance.isConnected;
strs.ToList().ForEach(s=>{
//Debug.Log("RequestUserPermission: "+s);
//if (!Permission.HasUserAuthorizedPermission(s))
//{
Permission.RequestUserPermission(s);
Debug.Log("add RequestUserPermission: " + s);
//}
//else
//{
// Debug.Log("it has RequestUserPermission: " + s);
//}
});
//UnityEngine.Networking.PlayerConnection.PlayerConnection.
//实例化上下文环境
// adUnionContext = AdUnionContext.GetInstance();
初始化SDK
//AdUnionSDK.Init(APP_ID, new OnAuInitListenerProxy());
初始化unity自带的控件
initComponents();
}
2.疑难问题以及如何解决
.权限不弹提示窗
android 中的权限只有部分危险权限会弹窗,结合相关功能,查找某条弹窗权限如文件写入,相机使用等,需要和弹窗一 一对应,没有提示的权限建议不要动态申请,或者不做权限检测
中间遇到的问题,配置在AndroidManifest.xml中的权限有时候会导致不能动态申请到所需权限,所以可以全部注释掉,然后动态添加。
系统权限分为两类:正常权限和危险权限。
- 正常权限不会直接给用户隐私权带来风险。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。
- 危险权限会授予应用访问用户机密数据的权限。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。如果您列出了危险权限,则用户必须明确批准您的应用使用这些权限。
权限是分组的,同一组的权限申请其中一个,同组的权限就全部都申请了。
特殊权限组:
- CALENDAR 日历
- CAMERA 相机
- CONTACTS 联系人
- LOCATION 定位
- MICROPHONE 麦克相关,比如录音
- PHONE 手机状态
- SENSORS 传感器
- SMS 短信
- STORAGE 存储权限
.自定义弹窗不展示
有时候权限申请需要自己写弹窗,需要在主线程和UI线程调用,可以参考上面的例子。
3.原理解析以及在Android中的使用(建议使用):
其实调用的是Android内的方法
.监听权限处理结果
@Override
public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)
{
LTBaseSDK.getInstance (this).onRequestPermissionsResult (requestCode, permissions, grantResults);
super.onRequestPermissionsResult (requestCode, permissions, grantResults);
if (requestCode ==250 || requestCode==251)
{
//特殊处理截图权限
LTSDK.LT_AutoPermissionChecker(requestCode, permissions, grantResults);
}
}
.动态检查权限
// 动态检查权限
public static void LT_AutoPermissionChecker ( int requestCode, String[] permissions, int[] grantResults)
{
Log.i ("LTSDK_Java", "LT_AutoPermissionChecker requestCode:"+requestCode);
String pName="";
if (requestCode ==250 )
{
pName="android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
}
else if(requestCode==251)
{
pName="android.permission.WRITE_EXTERNAL_STORAGE";
}
LT_RequirePermission (pName,requestCode);
}
.请求权限
public static void LT_RequirePermission (final String pName,final int requestCode)
{
Log.i ("LTSDK_Java", "LT_RequirePermission pName:"+pName+requestCode);
if (ContextCompat.checkSelfPermission(UnityPlayer.currentActivity, pName) != PackageManager.PERMISSION_GRANTED)
{
Log.i ("LTSDK_Java", "checkSelfPermission pName: false:"+pName);
// if (ActivityCompat.shouldShowRequestPermissionRationale(UnityPlayer.currentActivity, pName))
// {
((MainActivity)UnityPlayer.currentActivity).runOnUiThread(new Runnable() {
public void run() {
final String perName=pName;
AlertDialog.Builder builder=new AlertDialog.Builder(UnityPlayer.currentActivity);
builder.setTitle("提示:")
.setMessage("需要权限:"+requestCode)
.setPositiveButton("OK", new OnClickListener() {
public void onClick(DialogInterface var1, int var2) {
Log.i ("LTSDK_Java", "requestPermissions pName: :"+perName);
ActivityCompat.requestPermissions(UnityPlayer.currentActivity,new String[] {perName}, requestCode);
}
})
.setNegativeButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface var1, int var2) {
}
});
builder.create().show();
}
});
// }
}
}
.ex.简单示例 (截图保存到相册并刷新,动态申请权限)
public static void LT_SavePhoto (String photoPath,String tarPath)
{
// if (ContextCompat.checkSelfPermission(UnityPlayer.currentActivity,android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) != PackageManager.PERMISSION_GRANTED )
// {
// LTSDK.LT_RequirePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,250);
// Log.i ("LTSDK_Java", "LT_SavePhoto LT_RequirePermission:"+250);
// }
if(ContextCompat.checkSelfPermission(UnityPlayer.currentActivity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
LTSDK.LT_RequirePermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,251);
Log.i ("LTSDK_Java", "LT_SavePhoto LT_RequirePermission:"+251);
}
else
{
//copy to picture
copyFile(photoPath,tarPath);
Log.i ("LTSDK_Java", "LT_SavePhoto copyFile");
//refpic
String[] paths = {photoPath,tarPath};
String[] mimeTypes = {"image/jpeg", "image/png"};
MediaScannerConnection.scanFile(UnityPlayer.currentActivity, paths, mimeTypes,
new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.i ("LTSDK_Java", "photoPath suck");
}
});
}
}
.unity 内直接调用Android方法
#if UNITY_ANDROID
private AndroidJavaClass _request;
public AndroidJavaClass Request {
get {
if (_request == null)
_request = new AndroidJavaClass ("com.example.androidpermissionmgr.PermissionProvider");
return _request;
}
}
#else
public void RequestPermissions (int requestCode, params string[]permissions)
{
Debug.Log ("[PermissionProvider] Requesting permissions: "+ requestCode + " " + permissions );
//Request.CallStatic ("verifyPermissions", gameObject.name, requestCode, permissions);
//requestPermissions
Request.CallStatic ("verifyPermissions");
}
java 内申请权限
import android.support.v4.content.PermissionChecker;
import android.support.v4.app.ActivityCompat;
//前面说过了静态方法,android.permission.WRITE_EXTERNAL_STORAGE是外部存储权限,同理其他权限也可以动态请求
public static void verifyPermissions() {
//检查权限避免重复请求相同权限,参数:activity,权限名
if (PermissionChecker.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != 0) {
ActivityCompat.requestPermissions(this, new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 100);//请求权限,参数:activity,权限名,请求码(不同的权限要求不同的请求码,可以自己定,比如我这个权限是100,另外的可以填102,103...)
}
}
4.ex:unity+android权限--打开应用不弹权限,动态请求权限 完整例子展示
首先,屏蔽权限弹窗,AndroidManifest.xml里面加入
<!-- Unity打包屏蔽android权限弹窗-->
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
接下来是请求权限,在你需要的位置请求
//unity api 请求
Permission.RequestUserPermission(s);
//java 请求
if (PermissionChecker.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != 0) {
ActivityCompat.requestPermissions(this, new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 100);//请求权限,参数:activity,权限名,请求码(不同的权限要求不同的请求码,可以自己定,比如我这个权限是100,另外的可以填102,103...)
}
//java层 监听结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(100 != requestCode)return;//我们刚才定义的请求码是100,名称也可以判断
//给个弹窗告知玩家这个权限不会对他造成影响
if (ActivityCompat.shouldShowRequestPermissionRationale("只会写入游戏安装目录,不会影响系统安全", "android.permission.WRITE_EXTERNAL_STORAGE")) {
(new Builder(this)).setMessage(string.storage_permissions_remind)
.setPositiveButton("OK", new OnClickListener() {
public void onClick(DialogInterface var1, int var2) {
//点击ok,则再次请求
requestExternalStorage();
}
}).setNegativeButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface var1, int var2) {
//点击cancel,todo
}
}).create().show();
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
更多推荐