我編寫了一個將某些數據導出到文件的Android應用程序。如何訪問由文件管理器共享的文件(如果我的應用程序沒有READ_EXTERNAL_STORAGE
該文件通過ACTION_SEND
Intent
和我的自定義ContentProvider
發佈到其他應用程序。它工作正常。文件可以附加到電子郵件或通過Bluetooth
發送。
現在,同一故事的另一方面是應用程序應該能夠接收文件來導入它。我的目的是讓用戶在文件管理器中選擇一個文件並選擇「共享」選項。現在我的intent-filter
應該被激活,我的應用程序應該訪問該文件。
我的應用程序沒有READ_EXTERNAL_STORAGE
權限,因爲通常它不需要訪問外部存儲中的文件。我不想添加此權限,我不想讓用戶知道我的應用可能訪問他們的照片等等。
根據Intent
類的文檔,如果調用應用程序添加了FLAG_GRANT_READ_URI_PERMISSION
,它應該足以讓我的應用程序讀取共享文件。
我intent-filter
:
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SENDTO"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="*/*"/>
</intent-filter>
通過意向濾鏡接收我的代碼來處理的意圖:
Uri uri = null;
if (uri == null)
{
uri = intent.getData();
}
if (uri == null)
{
if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction()))
{
uri = (Uri) intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM).get(0);
}
else
{
uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
}
}
if (uri != null)
{
try
{
InputStream stream = getContentResolver().openInputStream(uri);
stream.read();
stream.close();
Toast.makeText(this, "Success " + intent.getAction() + " " + uri.toString(), Toast.LENGTH_LONG).show();
}
catch (IOException e)
{
Toast.makeText(this, "Error " + intent.getAction() + " " + uri.toString() + " " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
這僅僅是一個「測試」的代碼,所以我只是儘量讀什麼從文件開始檢查它是否有效。
結果是:
我使用ES文件瀏覽器和驚喜「共享」文件到我的應用程序嘗試。通常收到的
Uri
是一個文件Uri ("file://" scheme)
並試圖打開此文件失敗openInputStream
與我的應用程序無權訪問該文件的信息。由於某些原因,我從ES文件資源管理器共享一個媒體文件的文件時,行爲會發生變化。我收到一個
"content://" Uri
,我的應用程序可以訪問該文件。驚奇似乎仍然發送"file://" Uri
並打開文件失敗。我試圖修改代碼以從
ClipData
(如果可用)獲得Uris,但它沒有改變任何東西。當我嘗試從內置的
MIUI
電子郵件客戶端打開附件時,我還收到file:// Uris
並且該文件無法訪問。 (測試此我不得不使用ACTION_VIEW
行動,而不是ACTION_SEND
)
我也嘗試了其他方式。我使用ACTION_GET_CONTENT
Intent
從我的應用中調用了一個文件選取器,並想從我的應用中使用返回的Uri
。結果更糟,因爲即使"content://" Uris
也不起作用。
所以,問題是 - 有什麼辦法來訪問的方式,可以讓我的應用程序來訪問共享文件,而不添加READ_EXTERNAL_STORAGE permission
從流行的文件管理共享的文件?
我可以在Android的文檔有關FLAG_GRANT_READ_URI_PERMISSION
閱讀和file:// Uris
被禁止在Android 7.0 開始,所以一切都是理論上的準備,使工作,但在現實世界中我撞到牆上......
我知道我總是可以將READ_EXTERNAL_STORAGE
權限添加到我的應用中,或者讓用戶手動將文件複製到我應用的外部存儲目錄(路徑getExternalFilesDir
返回的路徑),然後在那裏訪問文件,但這兩個操作都有嚴重的缺陷(安全影響源自不必要的許可或糟糕的用戶體驗)。
是否有任何其他選項可用於使其工作?
'我使用ACTION_GET_CONTENT Intent從我的應用程序中調用了一個文件選取器,並且想從我的應用程序中使用返回的Uri。結果更糟糕,因爲即使是「content://」Uris也不行。抱歉。我不明白什麼是行不通的。您的應用可以使用內容方案打開文件。你還想要什麼? – greenapps
問題是我無法在這種情況下打開內容Uris,因爲系統表示我沒有權限這樣做。我懷疑選擇器應用程序未將Intent中的FLAG_GRANT_READ_URI_PERMISSION標誌設置回發送給我的應用程序,但我沒有ES文件資源管理器的源,因此我無法驗證此內容。 – Bieniu
很難相信。我從未見過ACTION_GET_CONTENT獲取的內容方案不可用。爲什麼在談論ACTION_GET_CONTENT時提到ES文件資源管理器? – greenapps