1

I can't seem to get my App to save an image, outside of my App folder. I can save internally (image will save to app folder) but not externally. I want to see photos taken with my App in the default device gallery. I believe i have all the required App permissions. Here is my code:

\\MainActivity using System; using TCmCRS_20; using Android.App; using Android.Content.PM; using Android.Runtime; using Android.Views; using Android.Widget; using Android.OS; using SQLite; using System.IO; using Xamarin.Essentials; using Acr.UserDialogs; using Plugin.Media; namespace TCmCRS_20.Droid { [Activity(Label = "TCmCRS_20", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { protected override async void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); await CrossMedia.Current.Initialize(); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); Xamarin.FormsMaps.Init(this, savedInstanceState); UserDialogs.Init(this); string fileName = "TCmCRS_20_db.db3"; string folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); string completePath = System.IO.Path.Combine(folderPath,fileName); LoadApplication(new App(completePath)); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } } } //Android Manifest <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.TCmCRS_20" android:installLocation="preferExternal"> <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="29" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-feature android:name="android.hardware.location" android:required="false" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <uses-feature android:name="android.hardware.location.network" android:required="false" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:label="TCmCRS_20.Android"> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data> </provider> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyADDISS9WBQw8XYyWGkIF0Q5TtiAW9b_ao" /> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <uses-library android:name="org.apache.http.legacy" android:required="false" /> </application> </manifest> private async void TakePhotoButton_OnClicked(object sender, EventArgs e) { var location = await Geolocation.GetLocationAsync(); if (location != null) { PhotoLatCoord.Text = location.Latitude.ToString(); PhotoLonCoord.Text = location.Longitude.ToString(); } else { ; } string gID = Guid.NewGuid().ToString(); string fN = "RI-" + Asset_ID.Text + " " + gID + ".jpg"; if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported) { await DisplayAlert("No Camera", "No camera available", "OK"); return; } await CrossMedia.Current.Initialize(); var current = Connectivity.NetworkAccess; if (current != NetworkAccess.Internet) { var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions { Name = fN, Directory = "All_Photos", SaveToAlbum = true, }); } else { var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions { Name = fN, Directory = "Photos_for_Upload", SaveToAlbum = true, }); //Get the public album path var aPpath = file.AlbumPath; //Get private path var path = file.Path; //! added using Microsoft.WindowsAzure.Storage; var account = CloudStorageAccount.Parse("xxxhiddenxxx"); var blobClient = account.CreateCloudBlobClient(); var container = blobClient.GetContainerReference("xxx"); var blockBlob = container.GetBlockBlobReference(fN); if (file == null) return; { MainImage.Source = ImageSource.FromStream(() => file.GetStream()); await blockBlob.UploadFromStreamAsync(file.GetStream()); } } } 

Any help would be greatly appreciated

1 Answer 1

2

I think adding android:requestLegacyExternalStorage="true" to your manifest <application> tag as mentioned here: Xamarin-System.UnauthorizedAccessException: Access to the path is denied in combination with the native android path for pictures Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath; will help you.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for pointing me in the right direction @Tom0x it was doing my head in, Cheers
This solution will not work post-Android 10 I hope you guys are aware! Legacy external storage is like a cop-out that only works on Android 10, will not work on the latest Android though!!!
@FreakyAli, Indeed. But for Android 11 you dont need it as you can write to that Pictures directory just fine then.
@blackapps Are you saying that on Android 11 the above legacy issue won't exist? Because I am pretty sure it will!
@FreakyAli, On an Android 11 emulator the Pictures directory is readable and writable for all apps. Like Download, Documents, DCIM, Alarms folder and so on. Easy to test for your self. The root of external storage is again readable for all apps.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.