From fd68101162e8b7f42eea523d08fd7dbe1b856038 Mon Sep 17 00:00:00 2001 From: Cristian Karmy Guzman Date: Tue, 22 Aug 2023 17:21:37 -0400 Subject: [PATCH] Fuse.Camera: update permissions for Android 13 Co-authored-by: Morten Daniel Fornes This makes the Camera and CameraRoll modules work on Android 13. Closes #1481 --- .../AndroidPermissionsInternal.uno | 15 ++ .../AndroidPermissionsInternal.uxl | 12 ++ .../Fuse.Android.Permissions/Permissions.uno | 3 + .../Fuse.Android.Permissions/Permissions.uxl | 12 ++ Source/Fuse.Camera/Android/AndroidCamera.uno | 157 +++++++++++++----- Source/Fuse.Camera/Fuse.Camera.unoproj | 1 + 6 files changed, 157 insertions(+), 43 deletions(-) diff --git a/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uno b/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uno index 80127222d..6d44d2376 100644 --- a/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uno +++ b/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uno @@ -460,6 +460,21 @@ namespace Fuse.Android.Permissions.Internal return new PlatformPermission("android.permission.READ_EXTERNAL_STORAGE"); } [TargetSpecificImplementation] + internal static extern PlatformPermission _read_media_images() + { + return new PlatformPermission("android.permission.READ_MEDIA_IMAGES"); + } + [TargetSpecificImplementation] + internal static extern PlatformPermission _read_media_audio() + { + return new PlatformPermission("android.permission.READ_MEDIA_AUDIO"); + } + [TargetSpecificImplementation] + internal static extern PlatformPermission _read_media_video() + { + return new PlatformPermission("android.permission.READ_MEDIA_VIDEO"); + } + [TargetSpecificImplementation] internal static extern PlatformPermission _read_frame_buffer() { return new PlatformPermission("android.permission.READ_FRAME_BUFFER"); diff --git a/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uxl b/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uxl index d78d5003f..9eb518c61 100644 --- a/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uxl +++ b/Source/Fuse.Android.Permissions/AndroidPermissionsInternal.uxl @@ -364,6 +364,18 @@ + + + + + + + + + + + + diff --git a/Source/Fuse.Android.Permissions/Permissions.uno b/Source/Fuse.Android.Permissions/Permissions.uno index df9409809..604ef09a5 100644 --- a/Source/Fuse.Android.Permissions/Permissions.uno +++ b/Source/Fuse.Android.Permissions/Permissions.uno @@ -209,6 +209,9 @@ namespace Fuse.Android.Permissions public static PlatformPermission READ_CALL_LOG { get { return Internal.Android._read_call_log(); } } public static PlatformPermission READ_CONTACTS { get { return Internal.Android._read_contacts(); } } public static PlatformPermission READ_EXTERNAL_STORAGE { get { return Internal.Android._read_external_storage(); } } + public static PlatformPermission READ_MEDIA_IMAGES { get { return Internal.Android._read_media_images(); } } + public static PlatformPermission READ_MEDIA_AUDIO { get { return Internal.Android._read_media_audio(); } } + public static PlatformPermission READ_MEDIA_VIDEO { get { return Internal.Android._read_media_video(); } } public static PlatformPermission READ_FRAME_BUFFER { get { return Internal.Android._read_frame_buffer(); } } public static PlatformPermission READ_HISTORY_BOOKMARKS { get { return Internal.Android._read_history_bookmarks(); } } public static PlatformPermission READ_INPUT_STATE { get { return Internal.Android._read_input_state(); } } diff --git a/Source/Fuse.Android.Permissions/Permissions.uxl b/Source/Fuse.Android.Permissions/Permissions.uxl index 9ffa31bbe..cdd063dbe 100644 --- a/Source/Fuse.Android.Permissions/Permissions.uxl +++ b/Source/Fuse.Android.Permissions/Permissions.uxl @@ -364,6 +364,18 @@ + + + + + + + + + + + + diff --git a/Source/Fuse.Camera/Android/AndroidCamera.uno b/Source/Fuse.Camera/Android/AndroidCamera.uno index cf4c2f4cb..f6f800c00 100644 --- a/Source/Fuse.Camera/Android/AndroidCamera.uno +++ b/Source/Fuse.Camera/Android/AndroidCamera.uno @@ -1,24 +1,40 @@ -using Uno.Threading; -using Uno; -using Uno.Compiler.ExportTargetInterop; using Android; -using Fuse.ImageTools; +using Fuse; using Fuse.Android.Permissions; +using Fuse.ImageTools; +using Uno; +using Uno.Compiler.ExportTargetInterop; +using Uno.Threading; + namespace Fuse.Camera { - extern (Android) static internal class AndroidCamera { internal static void TakePicture(Promise p) { - var permissions = new PlatformPermission[] + if (AndroidProperties.BuildVersion >= 33) { - Permissions.Android.CAMERA, - Permissions.Android.WRITE_EXTERNAL_STORAGE, - Permissions.Android.READ_EXTERNAL_STORAGE - }; + var permissions = new PlatformPermission[] + { + Permissions.Android.CAMERA, + Permissions.Android.READ_MEDIA_IMAGES, + Permissions.Android.READ_MEDIA_VIDEO, + Permissions.Android.READ_MEDIA_AUDIO + }; - Permissions.Request(permissions).Then(new TakePictureCommand(p).Execute, p.Reject); + Permissions.Request(permissions).Then(new TakePictureCommand(p).Execute, p.Reject); + } + else + { + var permissions = new PlatformPermission[] + { + Permissions.Android.CAMERA, + Permissions.Android.WRITE_EXTERNAL_STORAGE, + Permissions.Android.READ_EXTERNAL_STORAGE + }; + + Permissions.Request(permissions).Then(new TakePictureCommand(p).Execute, p.Reject); + } } internal static void CheckPermissions(Promise p) @@ -32,15 +48,15 @@ namespace Fuse.Camera } } - [ForeignInclude(Language.Java, - "android.provider.MediaStore", - "com.fuse.Activity", - "com.fuse.camera.Image", + [ForeignInclude(Language.Java, + "android.provider.MediaStore", + "com.fuse.Activity", + "com.fuse.camera.Image", "android.os.Build", - "androidx.core.content.FileProvider", + "androidx.core.content.FileProvider", "java.io.File", - "android.net.Uri", - "android.util.Log", + "android.net.Uri", + "android.util.Log", "android.content.Intent")] extern (Android) internal class TakePictureCommand { @@ -51,18 +67,18 @@ namespace Fuse.Camera } public void Execute(PlatformPermission[] grantedPermissions) { - if(grantedPermissions.Length<3) + if (grantedPermissions.Length < 3) { _promise.Reject(new Exception("Required permissions were not granted.")); return; } - + var photo = CreateImage(); - if(photo==null) + if (photo == null) throw new Exception("Couldn't create temporary Image"); var intent = CreateIntent(photo); - if(intent==null) + if (intent == null) throw new Exception("Couldn't create Image capture intent"); ActivityUtils.StartActivity(intent, new TakePictureCallback(_promise).OnActivityResult, (object)photo); @@ -75,9 +91,8 @@ namespace Fuse.Camera try { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - //FileProvider way for Marshmallow+ (API 23) + // FileProvider way for Marshmallow+ (API 23) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { - File photoFile = p.getFile(); if (photoFile != null) { Uri photoURI = FileProvider.getUriForFile( @@ -153,7 +168,7 @@ namespace Fuse.Camera _p.Reject(new Exception(reason)); } } - + [ForeignInclude(Language.Java, "android.provider.MediaStore", "com.fuse.Activity", "android.content.Intent", "com.fuse.camera.Image", "com.fuse.camera.ImageStorageTools", "androidx.core.content.ContextCompat")] extern (Android) class CheckPermissionsCommand { @@ -162,29 +177,55 @@ namespace Fuse.Camera var cb = new PromiseCallback(p); CheckPermissionsInternal(cb.Resolve, cb.Reject); } - + [Foreign(Language.Java)] internal static void CheckPermissionsInternal(Action onComplete, Action onFail) @{ - if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.READ_EXTERNAL_STORAGE) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) - { - onFail.run("User does not have permission to read"); - } - else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) - { - onFail.run("User does not have permission to write"); - } - else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.CAMERA) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + if (android.os.Build.VERSION.SDK_INT >= 33) { - onFail.run("User does not have permission access the camera"); + if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.READ_MEDIA_IMAGES) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission to read images"); + } + else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.READ_MEDIA_VIDEO) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission to read videos"); + } + else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.READ_MEDIA_AUDIO) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission to read audio"); + } + else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.CAMERA) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission access the camera"); + } + else + { + onComplete.run("User has permission to read, write and access camera"); + } } else { - onComplete.run("User has permission to read, write and access camera"); + if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.READ_EXTERNAL_STORAGE) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission to read"); + } + else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission to write"); + } + else if (ContextCompat.checkSelfPermission(com.fuse.Activity.getRootActivity(), android.Manifest.permission.CAMERA) != com.fuse.Activity.getRootActivity().getPackageManager().PERMISSION_GRANTED) + { + onFail.run("User does not have permission access the camera"); + } + else + { + onComplete.run("User has permission to read, write and access camera"); + } } @} } - + [ForeignInclude(Language.Java, "android.provider.MediaStore", "com.fuse.Activity", "android.content.Intent", "com.fuse.camera.Image", "com.fuse.camera.ImageStorageTools")] extern (Android) class requestAndroidPermissions { @@ -193,21 +234,51 @@ namespace Fuse.Camera { _callback = new PromiseCallback(p); } - + public void Execute() { - Permissions.Request(new PlatformPermission[] { Permissions.Android.WRITE_EXTERNAL_STORAGE, Permissions.Android.READ_EXTERNAL_STORAGE, Permissions.Android.CAMERA }).Then(OnPermissions, OnRejected); + if (AndroidProperties.BuildVersion >= 33) + { + Permissions.Request(new PlatformPermission[] { + Permissions.Android.READ_MEDIA_IMAGES, + Permissions.Android.READ_MEDIA_VIDEO, + Permissions.Android.READ_MEDIA_AUDIO, + Permissions.Android.CAMERA + }).Then(OnPermissions, OnRejected); + } + else + { + Permissions.Request(new PlatformPermission[] { + Permissions.Android.WRITE_EXTERNAL_STORAGE, + Permissions.Android.READ_EXTERNAL_STORAGE, + Permissions.Android.CAMERA + }).Then(OnPermissions, OnRejected); + } } void OnPermissions(PlatformPermission[] grantedPermissions) { - if(grantedPermissions.Length == 3) + if (AndroidProperties.BuildVersion >= 33) { - _callback.Resolve("Success"); + if (grantedPermissions.Length == 4) + { + _callback.Resolve("Success"); + } + else + { + _callback.Reject("Required permissions were not granted"); + } } else { - _callback.Reject("Required permission was not granted."); + if (grantedPermissions.Length == 3) + { + _callback.Resolve("Success"); + } + else + { + _callback.Reject("Required permissions were not granted"); + } } } diff --git a/Source/Fuse.Camera/Fuse.Camera.unoproj b/Source/Fuse.Camera/Fuse.Camera.unoproj index ee13a7315..ba7fbc0f2 100644 --- a/Source/Fuse.Camera/Fuse.Camera.unoproj +++ b/Source/Fuse.Camera/Fuse.Camera.unoproj @@ -9,6 +9,7 @@ "IsTransitive": true, "Projects": [ "../Android.ActivityUtils/Android.ActivityUtils.unoproj", + "../Fuse.Android/Fuse.Android.unoproj", "../Fuse.Android.Permissions/Fuse.Android.Permissions.unoproj", "../Fuse.ImageTools/Fuse.ImageTools.unoproj", "../Fuse.Common/Fuse.Common.unoproj",