Programmatically install an apk in Android 7 / api24 answers a similar question, but I want to programmatically install an APK from app internal storage (on an SD card) in Android 5.0 - 6.0 too.
If it weren't from app internal storage, I could startActivity()
with an intent whose action is ACTION_VIEW
and whose data URI has a file://
scheme (using Uri.fromFile()
). But I've tried that and it won't work with app internal storage, which isn't readable by other apps. I'm basing this on log messages like
W/asset: Asset path /storage/C5DF-1113/Android/data/com.example/files/foo.apk is neither a directory nor file (type=1).
W/InstallFlowAnalytics: Failed to hash APK contents
java.io.FileNotFoundException: /storage/C5DF-1113/Android/data/com.example/files/foo.apk: open failed: ENOENT (No such file or directory)
I've tried subclassing ContentProvider, using a content://
scheme. But apparently (and see CommonsWare's answer here), the package installer doesn't support the content://
scheme until Android 7.0. I get log messages like the following in Android 6.0:
I/ActivityManager: START u0 {act=android.intent.action.VIEW dat=content://com.example.provider/internal/foo.apk typ=application/vnd.android.package-archive flg=0x10000001} from uid 10159 on display 0
E/Updates: installNewApk
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://com.example.provider/internal/foo.apk typ=application/vnd.android.package-archive flg=0x10000001 }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
where the only apparent difference between an intent that matches the package installer and an intent that doesn't, is the data URI changing from file://
... to content://
....
There are answers elsewhere on installing an app silently, which is not a requirement for my project. There are also solutions that use reflection to get at undocumented features, or that require the device to be rooted, but those techniques are too brittle or user-unfriendly for this project.
There is also the option to copy the APK from app internal storage to external storage before launching the installer. We might have to go there, but the reason the APK is in internal storage in the first place is for purposes of privacy and security. (I realize this is far from bulletproof, but it is better than nothing and it's what our clients want.)
I'm willing to do a conditional based on the present version of Android, but at this point I still don't know what to do in 5.0 - 6.0.
Thanks for any suggestions.