2017-06-01 56 views
1

試圖讓Android選擇器顯示可供用戶啓動存儲在本地文件夾中的PDF文件的操作。 當我通過文件名如/data/user/0/myappappname/files/output.pdf(當然存在),我得到一個很好的選擇器與所有可以接受PDF文件的應用程序。但是,當我選擇其中的任何一個時,出現錯誤(來自外部應用程序)文檔路徑無效。不會引發異常。Android:我如何構建*完整*路徑傳遞給Intent.CreateChooser

然後我試圖(用於測試目的),以FNAME設置類似/storage/emulated/0/Download/TLCL.pdf(文件還存在),一切工作正常。

起初,我以爲這有什麼文件權限做(因爲第一個路徑是專用於我的應用程序),但後來我發現標誌ActivityFlags.GrantReadUriPermission正是爲了給其他臨時授權文件訪問的目的建造應用。結果仍然相同。

由於這是一個Xamarin.forms項目,我在選擇文件創建位置方面有限(我使用PCLStorage,它總是寫入app-private,本地文件夾),所以我沒有生成文件的選項在/文檔,/下載等。

我顯然做錯了什麼。任何想法讚賞。

是否有一個選項,以獲取來自系統路徑,包括/存儲/模擬/ 0部分(或任何這將是在其他設備上)?也許這會有所幫助?


一段代碼:

(mime類型被定義爲 「應用程序/ 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; 
      } 

回答

1

我解決了這個,你想要什麼這可能不是,是生成一個文件(在我的情況下是一個zip文件),將其導出到公用文件夾,然後將該文件用於選擇器。

使用這些:

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 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函數的字符串相同。

+0

嘿,這看起來像一個很好的解決方法。明天我會先試一試。感謝您花費時間和精力。我會等待一段時間,看看是否有人能解決我原來的問題(無需導出到公共文件夾),如果沒有 - 這就是我將要做的。 – bocko

0

我們使用的是Acr.IO而不是PCLStorage,我記得它有一個屬性會爲您返回完整路徑。 我們正在使用的代碼如下,但我不知道你是否簡單地在你的路徑開始時丟失了「file://」,因爲我注意到了我們代碼中的那些,以及此前的類似答案問題這一個,open a PDF in Xamarin.Forms (Android) 我們在Android上使用依賴的FileService並使用此代碼打開PDF文件:

public void OpenNatively(string filePath) { 
     Android.Net.Uri uri; 
     if (filePath.StartsWithHTTP()) { 
      uri = Android.Net.Uri.Parse(filePath); 
     } 
     else { 
      uri = Android.Net.Uri.Parse("file:///" + filePath); 
     } 
     Intent intent = new Intent(Intent.ActionView); 
     var extension = filePath.Substring(filePath.LastIndexOf(".")+1); 
     if (extension == "ppt" || extension == "pptx") { 
      extension = "vnd.ms-powerpoint"; 
     } 
     var docType = "application/" + extension; 
     intent.SetDataAndType(uri, docType); 
     intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask); 

     try { 
      Xamarin.Forms.Forms.Context.StartActivity(intent); 
     } 
     catch (Exception e) { 
      Toast.MakeText(Xamarin.Forms.Forms.Context, "No Application found to view " + extension.ToUpperInvariant() + " files.", ToastLength.Short).Show(); 
     } 
    } 
+0

謝謝。這與我所做的基本相同。問題是在應用程序私人文件夾中創建的文件的訪問權限。 Acr.IO乍一看似乎很好,謝謝你的信息。 – bocko