internal static Java.IO.File GetTemporaryRootDirectory()
        {
            // If we specifically want the internal storage, no extra checks are needed, we have permission
            if (TemporaryLocation == FileProviderLocation.Internal)
            {
                return(Platform.AppContext.CacheDir);
            }

            // If we explicitly want only external locations we need to do some permissions checking
            var externalOnly = TemporaryLocation == FileProviderLocation.External;

            // Check to see if we are >= API Level 19 (KitKat) since we don't need to declare the permission on these API levels to save to the external cache/storage
            // If we're not on 19 or higher we do need to check for permissions, but if we aren't limiting to external only, don't throw an exception if the
            // permission wasn't declared because we can always fall back to internal cache
            var hasPermission = Platform.HasApiLevel(BuildVersionCodes.Kitkat);

            if (!hasPermission)
            {
                hasPermission = Permissions.IsDeclaredInManifest(global::Android.Manifest.Permission.WriteExternalStorage);

                if (!hasPermission && externalOnly)
                {
                    throw new PermissionException("Cannot access external storage, the explicitly chosen FileProviderLocation.");
                }
            }

            // make sure the external storage is available
            var hasExternalMedia = Platform.HasApiLevel(BuildVersionCodes.Lollipop)
                ? AndroidEnvironment.GetExternalStorageState(Platform.AppContext.ExternalCacheDir) == AndroidEnvironment.MediaMounted
#pragma warning disable CS0618 // Type or member is obsolete
                : AndroidEnvironment.GetStorageState(Platform.AppContext.ExternalCacheDir) == AndroidEnvironment.MediaMounted;

#pragma warning restore CS0618 // Type or member is obsolete

            // undo all the work if we have requested a fail (mainly for testing)
            if (AlwaysFailExternalMediaAccess)
            {
                hasExternalMedia = false;
            }

            // fail if we need the external storage, but there is none
            if (externalOnly && !hasExternalMedia)
            {
                throw new InvalidOperationException("Unable to access the external storage, the media is not mounted.");
            }

            // based on permssions, return the correct directory
            // if permission were required, then it would have already thrown
            return(hasPermission && hasExternalMedia
                ? Platform.AppContext.ExternalCacheDir
                : Platform.AppContext.CacheDir);
        }
Пример #2
0
        static string CacheContentFile(AndroidUri uri)
        {
            if (!uri.Scheme.Equals(UriSchemeContent, StringComparison.OrdinalIgnoreCase))
            {
                return(null);
            }

            Debug.WriteLine($"Copying content URI to local cache: '{uri}'");

            // open the source stream
            using var srcStream = OpenContentStream(uri, out var extension);
            if (srcStream == null)
            {
                return(null);
            }

            // resolve or generate a valid destination path
            var filename = GetColumnValue(uri, MediaStore.Files.FileColumns.DisplayName) ?? Guid.NewGuid().ToString("N");

            if (!Path.HasExtension(filename) && !string.IsNullOrEmpty(extension))
            {
                filename = Path.ChangeExtension(filename, extension);
            }

            // create a temporary file
            var hasPermission = Permissions.IsDeclaredInManifest(global::Android.Manifest.Permission.WriteExternalStorage);
            var root          = hasPermission
                                ? Platform.AppContext.ExternalCacheDir
                                : Platform.AppContext.CacheDir;
            var tmpFile = GetEssentialsTemporaryFile(root, filename);

            // copy to the destination
            using var dstStream = File.Create(tmpFile.CanonicalPath);
            srcStream.CopyTo(dstStream);

            return(tmpFile.CanonicalPath);
        }