Android 10 - Использование PackageManager для установки новой версии apk вместо Intents на самом деле не работает - PullRequest
2 голосов
/ 17 января 2020

Способ обновления моего apk в настоящее время заключается в установке нового apk поверх старого (без перезаписи локальной базы данных или настроек).

Так как Android 10 (API 29) ACTION_VIEW устарел, так что это больше не работает:

Intent intent = new Intent(Intent.ACTION_VIEW);
//output file is the apk downloaded earlier
intent.setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package-archive");
startActivity(intent);

Следуя различным ответам, которые я нашел по inte rnet Мне нужно вместо этого начать использовать PackageInstaller. Глядя на демонстрацию, найденную в Android документах, я получаю следующее:

Intent intent = new Intent(PSMentorActivity.this,InstallApkSessionApi.class);
intent.putExtra("apkFile",outputFile);
this.startActivity(intent);

Где InstallApkSessionApi содержит кнопку, которая при нажатии должна запустить окно установки:

PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new 
    PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);
addApkToInstallSession(file, session);
// Create an install status receiver.
Context context = InstallApkSessionApi.this;
Intent intent = new Intent(context, InstallApkSessionApi.class);
intent.setAction(PACKAGE_INSTALLED_ACTION);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
IntentSender statusReceiver = pendingIntent.getIntentSender();
// Commit the session (this will start the installation workflow).
session.commit(statusReceiver);

Достаточно просто Хотя и сложнее по сравнению с прошлым. Ответ, который я получаю в onNewIntent, всегда:

 case PackageInstaller.STATUS_FAILURE:
              Toast.makeText(this, "Install failed!10 " + status + ", " + message,
                            Toast.LENGTH_SHORT).show();
              break;

, где статус и сообщение принимают следующие значения: status=1, message= "INSTALL_FAILED_INTERNAL_ERROR: Permission denied".

Поэтому я предположил, что это проблема с разрешениями. У меня уже были разрешения на чтение и запись в хранилище. Другие связанные разрешения: INSTALL_PACKAGES и REQUEST_INSTALL_PACKAGES, которые я не могу использовать из-за того, что первое не предназначено для использования третьими лицами, а последнее - уровень подписи.

Есть что-то, чего мне ужасно не хватает, или есть я не могу обновить мой Apk, не заходя в Google Play?

Ответы [ 2 ]

2 голосов
/ 17 января 2020

Я столкнулся с той же проблемой и пробовал так же (PackageInstaller), как и вы. Не работает Итак, вот решение для вас,

if(android.os.Build.VERSION.SDK_INT >= 29){
       Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
       intent.setData(Uri.fromFile(outputFile));
       intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
       startActivity(intent);   
}else{
      Intent intent = new Intent(Intent.ACTION_VIEW);
      //output file is the apk downloaded earlier
      intent.setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package- 
      archive");
      startActivity(intent);
}

Я тестировал в Android 10 (Google Pixel 2, One + 7, Samsung s10), он работает нормально. Если у вас все еще есть проблемы, пожалуйста, дайте мне знать. Примечание: Ваш код версии должен быть больше старого.

0 голосов
/ 17 января 2020

Итак, после помощи и еще нескольких поисков интересного целого rnet, я смог заставить оба метода работать на меня. Я до сих пор не понимаю, в чем причина проблемы. Ранее я создавал Uri, используемый в намерении, из файла непосредственно с Uri.fromFile(file). Это работает для всего под Android 10. Новый способ справиться с этим - использовать провайдера и получить файл, используя его.

  1. Текущий метод, который будет использоваться некоторое время, пока я не смогу правильно выполнить установку PackageManager (все еще есть некоторые проблемы, которые нужно исправить).
Uri urlapk = FileProvider.getUriForFile(this,BuildConfig.APPLICATION_ID+".fileProvider",outputFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(urlapk, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
Использование PackageManager, как указано в моем вопросе, со следующим отличием (inputStream теперь строится из Uri):
private void addApkToInstallSession(Uri uri, PackageInstaller.Session session)
            throws IOException {
        try (OutputStream packageInSession = session.openWrite("package", 0, -1);
             InputStream is = getContentResolver().openInputStream(uri)) {
            byte[] buffer = new byte[16384];

            int n;
            while ((n = is.read(buffer)) >= 0) {
                packageInSession.write(buffer, 0, n);
            }
        }
}

Основная проблема, с которой я сталкиваюсь в PackageManager, заключается в том, что он закрывается мое приложение, пока оно устанавливает, не предоставляет никакой обратной связи с пользователем по умолчанию. Так что, думаю, мне придется «сделать» эту обратную связь. Я перейду к PackageManager, поскольку ACTION_VIEW устарела для apks.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...