Программно установить apk в Android 7/api24 отвечает аналогично вопрос, но я хочу программно установить APK из внутренней памяти приложения (на SD-карте) и в Android 5.0 - 6.0.
Если бы это не было из внутренней памяти приложения, я мог бы startActivity()
с намерением, действие которого ACTION_VIEW
и чей URI данных имеет схему file://
(используя Uri.fromFile()
). Но я пробовал это, и это не будет работать с внутренней памятью приложения, которая не читается другими приложениями. Я основываюсь на таких сообщениях журнала, как
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)
Я пробовал создавать подклассы ContentProvider, используя схему content://
. Но, по-видимому (и см. ответ CommonsWare здесь), установщик пакетов не поддерживает схему content://
до Android 7.0. В 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)
где единственная очевидная разница между намерением, которое соответствует установщику пакета, и намерением, которое не соответствует, заключается в изменении URI данных с file://
... на content://
....
В другом месте есть ответы по автоматической установке приложения, что не является требованием для моего проекта. Существуют также решения, использующие отражение для доступа к недокументированным функциям или требующие рутирования устройства, но эти методы слишком ненадежны или неудобны для пользователя для этого проекта.
Существует также возможность скопировать APK из внутреннего хранилища приложения во внешнее хранилище перед запуском установщика. Возможно, нам придется пойти туда, но причина, по которой APK находится во внутренней памяти, в первую очередь заключается в целях конфиденциальности и безопасности. (Я понимаю, что это далеко не пуленепробиваемый вариант, но это лучше, чем ничего, и именно этого хотят наши клиенты.)
Я готов сделать условное на основе текущей версии Android, но на данный момент я все еще не знаю, что делать в 5.0–6.0.
Спасибо за любые предложения.
getFilesDir()
. SD-карту лучше называть съемным хранилищем. Что касается вашей проблемы, AFAIK, вам не повезло - APK должен быть на внешнем хранилище (getExternalFilesDir()
и т. д.) до Android 7.0. Я жаловался на это громко, но безрезультатно. - person CommonsWare   schedule 02.11.2017Uri.fromFile()
без ContentProvider (до 7.0). Насколько я знаю, тот факт, что он находится на съемном носителе, на этот вопрос не влияет. - person LarsH   schedule 03.11.2017Uri.fromFile()
не работает для вас. Только у вас есть доступ к этому каталогу; другие приложения, включая установщик, нет. Вы столкнетесь с той же проблемой, используяgetFilesDir()
, поскольку другие приложения не имеют доступа к этому местоположению. И вы не можете использоватьcontent
в качестве схемы до версии 7.0, что оставляет вам внешнее хранилище... и все, насколько я знаю. - person CommonsWare   schedule 03.11.2017