2013-12-17 92 views
14

我有一個九插件圖像背景的小部件。 圖像保存在/ sdcard/mydir/bgs中。Android - 無法打開的內容:file:/// storage/emulated/0

當我嘗試加載與setImageViewUri方法的圖像,我有這樣的錯誤:

Unable to open content: file:///storage/emulated/0/sdcard/mydir/bgs 

..

然後

...

open failed: EACCES (Permission denied) 

這隻出現在主屏幕上,只有Nexus 10和Nexus 7(最新的啓動器4.4這個bug沒有存在)。我的應用程序上也有一些RemoteView,並且都能正常工作。

我也將READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE添加到了清單中。

我該如何解決?

更新:我檢查了setImageViewUri方法,我發現它改變了我的文件的路徑。

if (value != null) { 
      // Resolve any filesystem path before sending remotely 
      value = value.getCanonicalUri(); 
      if (StrictMode.vmFileUriExposureEnabled()) { 
       value.checkFileUriExposed("RemoteViews.setUri()"); 
      } 
     } 

此方法接收我的值(/ SD卡/ MYDIR/BGS)和改變它代入(存儲/模擬/ 0/SD卡/ MYDIR/BGS)。但是這個文件不是通過adb存在於系統中的。

+0

分享你的代碼,並發表您的全logcat的輸出。 –

回答

6

看來setImageViewUri不再是安全與文件中使用://的URI。

爲什麼?

果凍豆介紹了READ_EXTERNAL_STORAGE權限。想要從外部存儲讀取的應用程序必須擁有此權限。在KitKat之前,這不是默認強制執行的。

啓動程序不具有此權限。實際上,您無法保證您附加的任何RemoteView擁有該權限。這使得使用setImageViewUri不安全,因爲您不知道遠程圖像視圖是否能夠讀取給定的uri。

現在是什麼?

選項1:使用setImageViewBitmap。

你可能已經從該選項離開由於未能粘合劑交易。這些技巧只是確保您的圖像低於1 MB。這聽起來並不難。你可以計算出你的圖像究竟有多大。例如,如果你使用的是ARGB_8888圖像,這意味着你需要每像素4個字節。

1 Mb = 1048576 bytes = 262144 pixels = 512 x 512 image

當然你也可以使用RGB_565獲得2倍的像素擠出更多的是:我們可以通過calulate的最大尺寸。

另請注意,如果您的小部件很小,則可能不需要大圖像。您appwidget可以通過以下詢問其具體的選項:

Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetIds[i]); 

int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); 
int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); 

int maxWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH); 
int maxHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT); 

要知道,返回的值是不沾像素,所以你需要將它們轉換爲擴展您的位圖。

選項2:使用內容提供商

如果由於某種原因,你還是不喜歡的IPC限制,你總是可以建立一個自定義的內容提供商。把這個uri傳入setImageViewUri,你應該很好走。

路徑切換怎麼樣?

路徑切換不是真正的問題。看起來這是一個問題,但仿真實際上工作正常。嘗試在//storage/emulated/0/sdcard/mydir/bgs內創建一個文件,該文件將創建得很好。

您會注意到,雖然異常是FileNotFoundException,但消息是Permission Denied。

10

你在你的清單需要

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

+1

我已經添加了。 READ和WRITE權限。 – CeccoCQ

0

我想你是手動輸入SD卡路徑。不用手動輸入SD卡路徑,你應該得到的存放路徑是這樣的:

File extStore = Environment.getExternalStorageDirectory(); 
String mPath = extStore.getAbsolutePath() + "/mydir/bgs"; 
+0

檢查我的最新編輯。謝謝。 – CeccoCQ

14

從Lollipop開始,谷歌推出了一種新的方式,明確給予應用程序您希望他們在您的設備上使用的權限,並禁用那些您想拒絕應用程序的應用程序。如果你注意到,在你的Android監控,日誌顯示

java.io.FileNotFoundException: /storage/emulated/0/advert.mp4: open failed: EACCES (Permission denied) 

EACCESS permission denied是java的臭名昭著的FileNotFoundException的原因。

爲了解決這個問題,就跳轉到你應用程序的權限,使存儲在您的應用

enter image description here

+0

所以默認情況下,所有權限都被禁用??! 用戶必須在每次安裝應用程序時啓用所有功能?我從來沒有在我的手機(版本6.0.1)上做過... – Matt

+0

請不要在已發佈的應用程序上執行此操作。你的用戶不會感謝你。您應該在運行時從您的應用程序請求權限。 https://developer.android.com/training/permissions/requesting.html – Kuffs

相關問題