Android - Unable to open content: file:///storage/emulated/0
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
You need
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
in your manifest.
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.