c# - Android:如何构造*完整*路径以传递给 Intent.CreateChooser

标签 c# android xamarin.android xamarin.forms

试图让 Android 选择器显示可用的操作,以便用户启动存储在我的本地文件夹中的 PDF 文件。 当我传递像 /data/user/0/myappappname/files/output.pdf 这样的文件名时(当然存在),我得到了一个不错的选择器,其中包含所有可以接受pdf文件。但是当我选择其中任何一个时,我收到一个错误(来自外部应用程序)文档路径无效。没有抛出异常。

然后我尝试(出于测试目的)将 fname 设置为类似 /storage/emulated/0/Download/TLCL.pdf 的内容(文件也存在),并且一切正常。

起初,我认为这与文件权限有关(因为第一个路径对我的应用程序是私有(private)的),但后来我发现标志 ActivityFlags.GrantReadUriPermission 正是为了临时授予的目的而构建的对其他应用程序的文件访问。还是一样的结果。

由于这是一个 Xamarin.forms 项目,我在文件创建位置的选择上受到限制(我使用 PCLStorage,它总是写入 app-private 本地文件夹),所以我没有生成文件的选项/文档、/下载等

我显然做错了什么。任何想法表示赞赏。

是否有从系统获取完整路径的选项,包括/storage/emulated/0部分(或其他设备上的任何内容)?也许这会有所帮助?


一段代码:

(mimeType前面定义为“application/pdf”)

 public async Task<bool> LaunchFile(string fname, string mimeType)
        {
            var uri = Android.Net.Uri.Parse("file://" + fname );
            var intent = new Intent(Intent.ActionView);
            intent.SetDataAndType(uri, mimeType);

            intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission );

            try
            {
                Forms.Context.StartActivity(Intent.CreateChooser(intent, "ChooseApp"));
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine("LaunchFile: " + ex.Message);
                return false;
            }

最佳答案

我的解决方案(可能不是您想要的)是生成一个文件(在我的例子中是一个 zip 文件),将其导出到一个公共(public)文件夹,然后将该文件用于选择器。

使用这些:

private readonly string PublicDocsPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/AppName";
private readonly string PrivateDocsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);

和一些基本功能:

    public Stream GetOutputStream(string destFilePath)
    {
        string destFolderPath = Path.GetDirectoryName(destFilePath);
        if (!Directory.Exists(destFolderPath))
            Directory.CreateDirectory(destFolderPath);
        return new FileStream(destFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
    }
    public Stream GetInputStream(string sourceFilePath)
    {
        if (!File.Exists(sourceFilePath)) throw new FileNotFoundException();
        string sourceFolderPath = Path.GetDirectoryName(sourceFilePath);
        return new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
    }

您可以将您的文件复制到您的公共(public)文件夹(或子文件夹,您只需要组装路径)并将该文件用于您的选择器:

    public void SendEmail(string subject, string body, string recipient, string mimeType, string attachmentFilePath, string activityTitle)
    {
        var emailIntent = new Intent(Intent.ActionSendMultiple);
        if (string.IsNullOrEmpty(subject)) throw new ArgumentException();
        emailIntent.PutExtra(Intent.ExtraSubject, subject);
        if (!string.IsNullOrEmpty(recipient))
            emailIntent.PutExtra(Intent.ExtraEmail, new[] { recipient });
        if (!string.IsNullOrEmpty(body))
            emailIntent.PutExtra(Intent.ExtraText, body);
        if (!string.IsNullOrEmpty(attachmentFilePath))
        {
            var file = new Java.IO.File(attachmentFilePath);
            file.SetReadable(true, true);
            var uri = Android.Net.Uri.FromFile(file);
            emailIntent.PutParcelableArrayListExtra(Intent.ExtraStream, new List<IParcelable>(){uri});                              
        }
        emailIntent.SetType(mimeType);
        _activity.StartActivity(Intent.CreateChooser(emailIntent, activityTitle));
    }

此选择器特别允许用户通过电子邮件或谷歌驱动器发送他们的文件,但您可以根据需要组合它。该函数的attachmentFilePath与上面传入GetOutputStream函数的字符串相同。

关于c# - Android:如何构造*完整*路径以传递给 Intent.CreateChooser,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44314908/

相关文章:

c# - 带字符串插值的重载字符串方法

c# - Sitecore 使用 Git autocrlf 序列化项目

android - android中的壁纸服务和普通服务

c# - 如何从我的应用程序强制停止不同的 Android 服务?

c# - 将 Entity Framework Core 实体转换为 SQL 字符串

c# - 无法在 Android 上获取 SignalA 以连接到 SignalR 后端

Android:如何像 YouTube 在他的应用程序中那样创建 WebView

java - 如何通过 tcp 套接字将对象发送到 android 设备?

c# - 如何获取 Android 应用程序当前使用的堆大小?

c# - 在 Xamarin Android 中启用 Multi-Dex 后出错