Android - Unable to open content: file:///storage/emulated/0

后端 未结 4 2230
悲哀的现实
悲哀的现实 2020-12-31 03:58

I\'ve a widget with nine-patch image background. The image was saved in /sdcard/mydir/bgs.

When I try to load a image with setImageViewUri method, I\'ve this error:<

相关标签:
4条回答
  • 2020-12-31 04:42

    As from Lollipop, Google introduced a new way of explicitly giving apps the permission you want them to use on your device and disabling the ones you want to deny the app. If you notice, in your android monitor, the log shows

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

    EACCESS permission denied is the cause of the java's infamous FileNotFoundException.

    To solve this, just goto your App permission and enable storage for your app

    0 讨论(0)
  • 2020-12-31 04:49

    I think you are entering SD card path manually. Instead of manually entering SD Card path you should get storage path like this :

    File extStore = Environment.getExternalStorageDirectory();
    String mPath = extStore.getAbsolutePath() + "/mydir/bgs";
    
    0 讨论(0)
  • 2020-12-31 04:50

    You need

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

    in your manifest.

    0 讨论(0)
  • 2020-12-31 04:57

    It appears setImageViewUri is no longer safe to use with file:// uris.

    Why?

    Jellybean introduced the READ_EXTERNAL_STORAGE permission. Apps that want to read from external storage must hold this permission. This wasn't enforced by default until KitKat.

    The launcher does not hold this permission. In fact you are not guaranteed that any RemoteView you attach to holds that permission. This makes it unsafe to use setImageViewUri, since you don't know if the remote image view will even be able to read the given uri.

    What now?

    Option 1: Use setImageViewBitmap.

    You may have moved away from this option due to failed binder transactions. The trick to those is just making sure your image is under 1 MB. This isn't as hard as it sounds. You can calculate exactly how big your image is going to be. For instance if you are using an ARGB_8888 image that means you'll need 4 bytes per pixel. We can calulate the max size by:

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

    Of course you can squeeze more out of it using RGB_565 to get 2x the pixels.

    Also note that you may not need a huge image if your widget is small. Your appwidget can ask about its specific options by the following:

    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);
    

    Just be aware that the returned values are in dip not pixels so you will need to convert them to scale your bitmap.

    Option 2: Use a content provider

    If for some reason you still don't like the IPC restriction, you can always build a custom content provider. Pass that uri into the setImageViewUri, and you should be good to go.

    What about the path switch?

    The path switch is not the real issue. It looks like it is a problem, but the emulation actually works fine. Try creating a file inside //storage/emulated/0/sdcard/mydir/bgs and the file will create just fine.

    You'll notice that while the exception is a FileNotFoundException the message is Permission Denied.

    0 讨论(0)
提交回复
热议问题