Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/216.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms-如何为android定义作用域存储,如何将其实现到下载目录中的downlaod文件?_Android_Xamarin.forms_Xamarin.android - Fatal编程技术网

Forms-如何为android定义作用域存储,如何将其实现到下载目录中的downlaod文件?

Forms-如何为android定义作用域存储,如何将其实现到下载目录中的downlaod文件?,android,xamarin.forms,xamarin.android,Android,Xamarin.forms,Xamarin.android,在我的应用程序中,我可以下载PDF格式的报告。在我在安卓10及以下系统上测试我的应用程序之前,一切都很好。最近我将一台设备升级到Android 11,现在我无法下载共享存储中的任何文件。下载文件时出现访问被拒绝错误 我已授予读取和写入外部存储器的权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name

在我的应用程序中,我可以下载PDF格式的报告。在我在安卓10及以下系统上测试我的应用程序之前,一切都很好。最近我将一台设备升级到Android 11,现在我无法下载共享存储中的任何文件。下载文件时出现访问被拒绝错误

我已授予读取和写入外部存储器的权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我还在AndroidManifest.xml中设置了android:requestLegacyExternalStorage=true

我下载文件的代码如下所示

public async void DownloadSupplierSample(object sender, EventArgs e)
    {
        try
        {
            string basepath;
            if (Device.RuntimePlatform == Device.Android)
                basepath = DependencyService.Get<IDownloadPath>().GetDownloadsPath();
            else
                basepath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "..", "Library");

            PermissionStatus readstatus = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
            PermissionStatus writestatus = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();

            if (readstatus == PermissionStatus.Granted && writestatus == PermissionStatus.Granted)
            {
                DownloadSupplier(basepath);
            }
            else
            {
                var read = await Permissions.RequestAsync<Permissions.StorageRead>();
                var write = await Permissions.RequestAsync<Permissions.StorageWrite>();

                if (read == PermissionStatus.Granted && write == PermissionStatus.Granted)
                {
                    DownloadSupplier(basepath);
                }
            }
            await DisplayAlert("", "Sample is downaloaded at Downloads directory","Ok");
        }
        catch (Exception ex)
        {
        }
    }

    async void DownloadSupplier(string basepath)
    {
        using (var stream = await FileSystem.OpenAppPackageFileAsync("SupplierMaster.xlsx"))
        {
            string filename = $"SupplierMaster_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx";
            string filepath = Path.Combine(basepath, filename);

            byte[] bytes = Utils.Common.StreamToBytes(stream);
            File.WriteAllBytes(filepath, bytes);
            //using (Stream filestream = File.Create(filepath))
            //{
            //    //stream.Seek(0, SeekOrigin.Begin);
            //    stream.CopyTo(filestream);
            //}
        }
    }
我也尝试过从这个设备设置标志

如何为我的应用定义作用域存储

任何更新如何在我的下载目录中下载PDF文件

多谢各位

我如何为我的应用定义作用域存储?任何更新我如何在我的下载目录中下载PDF文件

Android 10为应用程序引入了一种新的存储模式,称为作用域存储,它改变了应用程序在设备外部存储上存储和访问文件的方式。如果您的目标是Android 10 API级别29或更高,请在应用程序的清单文件中将requestLegacyExternalStorage的值设置为true

调用android CreateFile方法

私有无效btn1\u单击对象发送者,事件参数e { DependencyService.Get.CreateFiletest.txt; }
几个月前我也有同样的问题

我在developer.android页面上发现:

第一种替代方法getExternalFilesDir无法正常工作,文件不会出现在下载目录中,此位置是应用程序的内部位置

第二种选择是媒体文件

我最后使用了第三种选择。我在Android项目中创建了一个服务类,如下所示:

public class FilesManager : IFilesManager
{
    private const int CREATE_FILE_REQUEST_CODE = 123;
    private static Context _context;
    
    public static void Init(Context context)
    {
        _context = context;
    }

    public async Task SaveFile(string fileName, byte[] content)
    { 
        Intent intent = new Intent(Intent.ActionCreateDocument);
        intent.AddCategory(Intent.CategoryOpenable);
        intent.SetType(your_file_mimeType);
        intent.PutExtra(Intent.ExtraTitle, fileName);

        var activity = (MainActivity)_context;
        var listener = new ActivityResultListener(activity);
        activity.StartActivityForResult(intent, CREATE_FILE_REQUEST_CODE);

        var result = await listener.Task;

        if (result == null)
        {
            // Cancelled by user
            return;
        }

        using (Stream os = _context.ContentResolver.OpenOutputStream(result.Data))
        {
            os?.Write(content);
            os?.Close();
        }
    }

    private class ActivityResultListener
    {
        private readonly TaskCompletionSource<Intent> Complete = new TaskCompletionSource<Intent>();
        public Task<Intent> Task { get { return this.Complete.Task; } }

        public ActivityResultListener(MainActivity activity)
        {
            // subscribe to activity results
            activity.ActivityResult += OnActivityResult;
        }

        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if(requestCode != CREATE_FILE_REQUEST_CODE)
            {
                return;
            }

            // unsubscribe from activity results
            var activity = (MainActivity)_context;
            activity.ActivityResult -= OnActivityResult;

            // process result
            if (resultCode == Result.Ok)
            {
                Complete.TrySetResult(data);
            }
            else
            {
                Complete.TrySetResult(null);
            }
        }
    }
}

注意:此方法需要用户交互。系统将提示用户选择保存文件的位置。

在Android 11设备上,您应该能够像在其他Android版本上一样,在外部存储的下载目录中创建文件。你们并没有下载问题,只是下载目录中的一个文件创建问题,我不明白。您添加了要求用户在运行时确认写入权限的代码?并不是说Android 11设备上需要它。我的下载路径是,这是您获取路径的代码。你走哪条路?请告诉我它的价值。请填写完整路径。这是下载目录/storage/emulated/0/Download/SupplierMaster_20210310141155.xlsx的路径。若我能够下载文件,即使在安卓11,那个么为什么我得到访问拒绝错误?这在Android 10或belowAccess上有效拒绝什么?你是说下载文件时拒绝访问错误,但我不这么认为。是的,我错了,你是对的。当我尝试创建文件时会出现错误好的,这意味着我必须在Android和iOS上分别实现文件创建逻辑。我一定要试一试。谢谢你的支持answer@Monica如果我的回复对您有帮助,请记住将我的回复标记为答案。是的,当然,我已经编写了您的代码,但无法对其进行测试。由于过去两个小时,我无法在android project上运行我的应用程序。System.IO.DirectoryNotFoundException:找不到路径“/Users/apple/Library/Android/sdk”的一部分。。一旦我解决了这个问题,我将测试你的答案,并将其标记为接受。我再次遇到这个错误。昨天还在工作。但同样的拒绝访问问题再次出现。@Monica您使用Visual studio for mac?如果是,请手动将Android SDK文件从默认路径复制到错误消息中的硬编码路径,更多详细信息,请查看:谢谢您的回答。我在activity.ActivityResult中遇到错误。未找到ActivityResult。我应该在MainActivity中添加什么?没问题,我编辑了答案。感谢您编辑答案。在调用SaveFile之前是否需要调用Init?因为我在_上下文中变为空。是的,当然,我再次编辑:非常感谢@alexgavru对我的帮助。它现在正在工作。
public class FilesManager : IFilesManager
{
    private const int CREATE_FILE_REQUEST_CODE = 123;
    private static Context _context;
    
    public static void Init(Context context)
    {
        _context = context;
    }

    public async Task SaveFile(string fileName, byte[] content)
    { 
        Intent intent = new Intent(Intent.ActionCreateDocument);
        intent.AddCategory(Intent.CategoryOpenable);
        intent.SetType(your_file_mimeType);
        intent.PutExtra(Intent.ExtraTitle, fileName);

        var activity = (MainActivity)_context;
        var listener = new ActivityResultListener(activity);
        activity.StartActivityForResult(intent, CREATE_FILE_REQUEST_CODE);

        var result = await listener.Task;

        if (result == null)
        {
            // Cancelled by user
            return;
        }

        using (Stream os = _context.ContentResolver.OpenOutputStream(result.Data))
        {
            os?.Write(content);
            os?.Close();
        }
    }

    private class ActivityResultListener
    {
        private readonly TaskCompletionSource<Intent> Complete = new TaskCompletionSource<Intent>();
        public Task<Intent> Task { get { return this.Complete.Task; } }

        public ActivityResultListener(MainActivity activity)
        {
            // subscribe to activity results
            activity.ActivityResult += OnActivityResult;
        }

        private void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if(requestCode != CREATE_FILE_REQUEST_CODE)
            {
                return;
            }

            // unsubscribe from activity results
            var activity = (MainActivity)_context;
            activity.ActivityResult -= OnActivityResult;

            // process result
            if (resultCode == Result.Ok)
            {
                Complete.TrySetResult(data);
            }
            else
            {
                Complete.TrySetResult(null);
            }
        }
    }
}
public event Action<int, Result, Intent> ActivityResult;

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) 
{
    ActivityResult?.Invoke(requestCode, resultCode, data); 
}
FilesManager.Init(this);