Friday, February 3, 2017

Android Video ads and WRITE_EXTERNAL_STORAGE permission

Video ads are getting more and more popular and useful for both developers and publishers. However videos require more network data and disk space to work. Many AdNetworks require external storage write permission to cache videos so that many apps can utilize it.

I just integrated Unity3D, Vungle (more AdColony, AppLovin, InMobi etc later) ad networks for rewarded videos in my game SketchVania. While testing i got issues with external storage write permission. From Marshmallow runtime permission is mandatory and WRITE_EXTERNAL_STORAGE has been added into dangerous Or higher priority permission. One must be ready to handle if permission is denied. After reading setup guide of many ad-networks i found below setting was used by many of them -


android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"


This setting means Android will allow WRITE permission upto API 18. Above this API or from KitKat no such permission will be granted. This setting comes from a very important reason. To save internal memory Android Context has methods getExternalCacheDirs(), getExternalFilesDir() etc. These methods allow app's private files to be created in external storage which are deleted after APK is uninstalled. But before KitKat these methods required WRITE_EXTERNAL_STORAGE permission. However this permission resulted into full write access to external storage. This is obviously very bad idea!. Therefore from KitKat using internal architectural changes write permission to /{EXTERNAL_STORAGE}/Android/data/{app_package}/[files,cache] was granted by default.


But there is a serious problem. I was testing my game on XIAOMI REDMI Note 3G and i found using android:maxSdkVersion="18" resulted into NO permission to getExternalFilesDir() etc methods. Whereas the Android documentation says from KitKat these methods don't need write permission. This is inconsistent due to poor or non-standard implementation by manufacturers!. It was causing IOException. This means if you are using maxSdkVersion="18" then chances are high on many Android 4.4 or 18+ API devices using getExternalFilesDir() like methods may not work. In my game i was saving game stats in this directory and nothing was getting saved!. Solution is to simply avoid using max sdk version and use internal cache and files like getCacheDir(), getFilesDir(). However this issue was fixed and most of ROMs today allow access to getExternalCacheDirs() etc without write permission. You may want to dynamically check write permission and handle files. This issue is a lesson that depending on manifest settings can be problematic in future.