Как управлять установкой из неизвестных источников в Android Oreo?

В Android Oreo (8.0) было внесено несколько изменений, касающихся разрешения установки приложений из неизвестных источников (с точки зрения пользователя) и процесса получения разрешения на их установку (с точки зрения разработчика).

Поскольку мне было особенно трудно найти все шаги, необходимые на стороне разработчика, я подумал, что было бы полезно спросить здесь о решении и ответить на вопрос самому, теперь, когда я нашел ответы, для дальнейшего использования теми, кто сталкиваются с теми же препятствиями.

Ответ будет включать следующие вопросы:

  1. Как проверить, разрешено ли мне запрашивать установку пакета?
  2. Какое именно разрешение я должен запросить?
  3. Как я могу предложить пользователю предоставить это разрешение?
  4. Как предложить пользователю установить указанный .apk?

(Если я все еще что-то упускаю здесь, я был бы признателен за любые дополнительные ответы или комментарии, указывающие на это.)


person Patneu    schedule 14.04.2018    source источник
comment
Здравствуйте, спасибо за ответ, есть один вопрос. Мои targetSdkVersion is 22 и compileSdkVersion is 26 , Как я могу проверить getPackageManager().canRequestPackageInstalls() для этого случая. метод всегда возвращает false.   -  person Chirag Savsani    schedule 19.11.2018
comment
@Чираг Савсани: Вы не можете. Как указано в моем ответе ниже, вы должны объявить targetSdkVersion 26 или выше. В противном случае этот метод всегда возвращает false - это предполагаемое поведение. Так что, боюсь, вы не обойдетесь внесением необходимых изменений для более высокой targetSdkVersion вашего приложения.   -  person Patneu    schedule 20.11.2018


Ответы (2)


Для начала ваше приложение должно объявить targetSdkVersion из 26 (уровень API Android Oreo) или выше в файле build.gradle или AndroidManifest.xml, чтобы все это работало.

Затем, чтобы ответить на вопросы выше:

  1. Как проверить, разрешено ли мне запрашивать установку пакета?

Вы можете проверить это с помощью getPackageManager().canRequestPackageInstalls() в любом месте вашего Код активности. Обратите внимание, что этот метод всегда возвращает false, если вы не объявили соответствующее разрешение или указали неправильную версию SDK.

  1. Какое именно разрешение я должен запросить?

Вы должны объявить Manifest.permission.REQUEST_INSTALL_PACKAGES в своем AndroidManifest.xml, например :

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
  1. Как я могу предложить пользователю предоставить это разрешение?

Вы можете отправить пользователя в соответствующее место назначения с намерением ACTION_MANAGE_UNKNOWN_APP_SOURCES. :

startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES));

Вы также можете напрямую направить пользователя к конкретным настройкам вашего приложения с помощью:

startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:your.application.package")));
  1. Как предложить пользователю установить указанный .apk?

После того, как вы убедитесь, что вам предоставлено соответствующее разрешение, вы можете предложить пользователю установить ваш файл .apk в любом месте кода вашей активности (где this относится к вашей активности Context), используя:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setDataAndType(FileProvider.getUriForFile(this, "your.application.package.fileprovider", new File("/path/to/your/apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(intent);

Вы также можете добавить intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) и начать с startActivityForResult(Intent, int), если хотите знать, была ли установка успешной, отменена или не удалась.

Информацию о том, как правильно получить Uri файла .apk, см. в разделе FileProvider. .

person Patneu    schedule 14.04.2018
comment
Привет, Могу ли я сделать так, чтобы сторонние приложения или SDK автоматически устанавливались один раз, когда приложение Android устанавливается на телефонных устройствах (Oreo)? - person Achiever; 23.07.2018
comment
Например, при попытке установить Ola APK он устанавливается на устройство Oreo. Сторонний GPS SDK вызывает через приложение OLA для Android. Таким образом, GPS SDK должен устанавливаться автоматически, не заставляя пользователя разрешать или запрещать установку неизвестных приложений. - person Achiever; 23.07.2018
comment
@Achiever: Звучит несколько запутанно, но я так понимаю, вы хотите установить стороннее программное обеспечение на Android-устройство без взаимодействия с пользователем? Если это так, то этот ответ не для вас. Я предполагаю, что вам понадобится root-доступ к устройству пользователя (при условии, что оно имеет root-права), и вам все равно сначала нужно будет предоставить это (что требует взаимодействия с пользователем). - person Patneu; 25.07.2018
comment
Я создал одно приложение для Android. Например, имя моего приложения для Android — приложение MobileShopping. Я попытался установить это приложение MobileShopping на мобильное устройство Oreo. Внутри приложения MobileShopping у меня есть платежный SDK, который позволяет проводить банковские транзакции. В устройстве Oreo даже после установки приложения MobileBanking запрашивает разрешение на установку стороннего приложения, т.е. Платежный SDK, который уже встроен в приложение MobileShopping (согласно разработке) - person Achiever; 26.07.2018
comment
Мне нужно показать пользователю диалоги с предоставленными разрешениями только тогда, когда я впервые пытаюсь установить приложение MobileShopping на устройстве oreo. Я не хочу показывать диалоговое окно разрешений или запрашивать какие-либо разрешения у пользователя даже для доступа к сторонним приложениям, которые есть в приложении MobileShopping. - person Achiever; 26.07.2018
comment
@Achiever: Чтобы уточнить: приложение «MobileShopping» — это приложение, которое вы разработали? Как он устанавливается в первую очередь? Через PlayStore или сторонний магазин приложений? И что такое «Платежный SDK»? Библиотека или отдельное приложение? Вы его разработали или кто-то другой? Почему вам нужно установить его позже, а не компилировать как зависимость приложения «Мобильные покупки»? В любом случае, я все еще не думаю, что этот ответ - это то, что вы ищете. Возможно, вам следует задать новый вопрос, чтобы другие тоже могли вам помочь. - person Patneu; 27.07.2018
comment
Приложение «MobileShopping» — это приложение, которое я разработал сам. Как он устанавливается в первую очередь? - Устанавливается через USB путем переноса APK из системной папки на мобильное устройство. И «Payment SDK» — это отдельное приложение, разработанное другими, APK которого был скомпилирован, когда я пытаюсь создать приложение MobileShopping. Который присутствует в папке Assets как PaymentSdk.apk - person Achiever; 28.07.2018
comment
Почему вам нужно установить его позже, а не компилировать как зависимость приложения «Мобильные покупки»? - Да, как это сделать? Есть идеи? - person Achiever; 28.07.2018
comment
Здравствуйте, спасибо за ответ, есть один вопрос. Моя targetSdkVersion — 22, а compileSdkVersion — 26. Как я могу проверить getPackageManager().canRequestPackageInstalls() для этого случая. метод всегда возвращает false. - person Chirag Savsani; 19.11.2018
comment
я не могу включить свое приложение с помощью startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse(package:your.application.package))); это отключено - person Omid Ziyaee; 08.05.2019
comment
Подтверждена работа с Samsung TabActive 2 с Android 9.1. Я могу понять, почему они не хотят, чтобы ваше приложение зависало, если пользователь отзовет это разрешение, но я действительно скучаю по старым временам, когда вы получали ошибку в logcat при отсутствии разрешения. Так что было довольно сложно найти это решение. - person FrankKrumnow; 18.09.2019
comment
@Patneu Что касается № 3, спасибо за полезную информацию и есть ли способ перезвонить после того, как пользователь включил разрешение. Я попытался получить результат возврата с помощью intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); вместе с StartActivityForResult, но он не возвращает мне результат. Есть ли способ сделать это? - person Anish Kumar; 10.12.2019
comment
@Anish Kumar: Нет, насколько я знаю, вы не можете напрямую получить отзыв о том, включил ли пользователь разрешение или нет, потому что ваше намерение просто показывает пользователю соответствующую настройку, он не обязан это делать что-нибудь об этом (поэтому тост, объясняющий пользователю, что на самом деле делать, может быть полезен). Если вы хотите узнать, предоставлено ли вам разрешение сейчас, вам просто нужно будет проверить еще раз, как на шаге 1. как только пользователь вернется к вашей деятельности. - person Patneu; 12.12.2019

Из оболочки adb вы можете управлять разрешениями для конкретных приложений, используя appops. Пример:

# To get a list of packagenames that is allowed to install from other sources
appops query-op REQUEST_INSTALL_PACKAGES allow 

# To allow an app install packages from other sources
appops set <package name> REQUEST_INSTALL_PACKAGES deny 

Текст справки, выводимый при запуске adb shell appops help:

AppOps service (appops) commands:
  help
    Print this help text.
  set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>
    Set the mode for a particular application and operation.
  get [--user <USER_ID>] <PACKAGE | UID> [<OP>]
    Return the mode for a particular application and optional operation.
  query-op [--user <USER_ID>] <OP> [<MODE>]
    Print all packages that currently have the given op in the given mode.
  reset [--user <USER_ID>] [<PACKAGE>]
    Reset the given application or all applications to default modes.
  write-settings
    Immediately write pending changes to storage.
  read-settings
    Read the last written settings, replacing current state in RAM.
  options:
    <PACKAGE> an Android package name.
    <OP>      an AppOps operation.
    <MODE>    one of allow, ignore, deny, or default
    <USER_ID> the user id under which the package is installed. If --user is not
              specified, the current user is assumed.
person tobalr    schedule 14.11.2019
comment
Невозможно выполнить набор приложений ‹имя пакета› REQUEST_INSTALL_PACKAGES разрешить из приложения Android? - person Daniele; 14.01.2021