soccerway
soccerway

Reputation: 11961

System throws Unable to get file exception even file path and permissions are provided

On click on the 'UploadButton' I am getting an exception Unable to get file location. This most likely means that the file provider information is not set in your Android Manifest file. Further investigation found out that I am receiving error at this point var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions... Can someone please advise about the cause of this exception ?

//Register.xaml content:

<Image x:Name="imageToUpload" />
<Button x:Name="uploadButton" Text="Upload Image" Clicked="UploadButton_Clicked"/>  

//AndroidManifest.xml

<?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.soccerapp">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
    <application android:label="soccerapp.Android"></application>
  <uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission
     android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <provider android:name="android.support.v4.content.FileProvider"
                android:authorities="com.companyname.soccerapp.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths"></meta-data>
  </provider>
</manifest>

// xml created folder with file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_images" path="Pictures" />
    <external-files-path name="my_movies" path="Movies" />
</paths>

//Code below for 'UploadButton_Clicked' action:

private async void UploadButton_Clicked(object sender, EventArgs e)
        {

            if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
            {
                await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
                return;
            }
                try
                {
                    var status = await GetPermissions();

                   if(status == true)
                    {
                    var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
                    {
                        Directory = "Sample",
                        Name = "test.jpg",
                        SaveToAlbum = saveToGallery.IsToggled
                    });

                    if (file == null)
                        return;

                    await DisplayAlert("File Location", (saveToGallery.IsToggled ? file.AlbumPath : file.Path), "OK");

                    imageToUpload.Source = ImageSource.FromStream(() =>
                    {
                        var stream = file.GetStream();
                        file.Dispose();
                        return stream;
                    });
                }
                   else
                   {
                    await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");

                    //On iOS you may want to send your user to the settings screen.
                    if (Device.RuntimePlatform == Device.iOS)
                        CrossPermissions.Current.OpenAppSettings();

                } 
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Last, exception! " + ex);

                }

        }

// Created a 'GetPermissions()' method separatley to handle all permission part:

public static async Task<bool> GetPermissions()
        {
            bool permissionsGranted = true;

            var permissionsStartList = new List<Permission>()
        {
            Permission.Location,
            Permission.LocationAlways,
            Permission.LocationWhenInUse,
            Permission.Storage,
            Permission.Camera
        };

            var permissionsNeededList = new List<Permission>();
            try
            {
                foreach (var permission in permissionsStartList)
                {
                    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(permission);
                    if (status != PermissionStatus.Granted)
                    {
                        permissionsNeededList.Add(permission);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Nice, exception! " + ex);
            }

            var results = await CrossPermissions.Current.RequestPermissionsAsync(permissionsNeededList.ToArray());

            try
            {
                foreach (var permission in permissionsNeededList)
                {
                    var status = PermissionStatus.Unknown;
                    //Best practice to always check that the key exists
                    if (results.ContainsKey(permission))
                        status = results[permission];
                    if (status == PermissionStatus.Granted || status == PermissionStatus.Unknown)
                    {
                        permissionsGranted = true;
                    }
                    else
                    {
                        permissionsGranted = false;
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Last, exception! " + ex);
            }
            return permissionsGranted;
        }

Upvotes: 0

Views: 108

Answers (1)

Leo Zhu
Leo Zhu

Reputation: 14956

try to change

<?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.soccerapp">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
<application android:label="soccerapp.Android"></application>
<uses-permission
  android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
  android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<provider android:name="android.support.v4.content.FileProvider"
            android:authorities="com.companyname.soccerapp.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
 <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
</provider>
</manifest>

to :

<?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.soccerapp">
   <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
   <application android:label="soccerapp.Android">

       <provider android:name="android.support.v4.content.FileProvider"
            android:authorities="com.companyname.soccerapp.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
       <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                  android:resource="@xml/file_paths"></meta-data>
       </provider>

    </application>
<uses-permission
  android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
   android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

</manifest>

Upvotes: 1

Related Questions