В доступе типа окна 2038 отказано - PullRequest
0 голосов
/ 21 октября 2018

Я исправляю не разработанное мной приложение для Android, несколько дней назад клиент попросил меня установить targetSdkVersion на 26 (до 14), после того как я заметил, что приложение в некоторых случаях падает, дляпример вылетает, когда отображается ProgressDialog.Это часть кода с этой проблемой:

mProgressDialog.setTitle(getString(R.string.downloading_data));
mProgressDialog.setMessage(mAlertMsg);
Drawable icon = getActivity().getDrawable(android.R.drawable.ic_dialog_info);
icon.setColorFilter(Color.parseColor("#00cbac"), PorterDuff.Mode.SRC_ATOP);
mProgressDialog.setIcon(icon);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
mProgressDialog.setButton(getString(R.string.cancel), loadingButtonListener);
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mProgressDialog.show();

Когда выполняется последняя строка, приложение вылетает и появляется эта ошибка в Logcat:

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@b784d3a -- permission denied for window type 2003

Эта проблема возникает, когдаприложение работает на устройствах с Android 8 и 9. Я искал решения для подобных проблем и обнаружил, что было бы лучше использовать WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY вместо TYPE_SYSTEM_ALERT, а затем изменил вторую последнюю строку кодаЯ писал в этом посте, но это ничего не меняет, приложение вылетает так же, и в журнале появляется эта ошибка:

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@b784d3a -- permission denied for window type 2038

В Манифесте у меня есть разрешение:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Я также включил все разрешения приложения из настроек устройства.Как я могу решить эту проблему?

1 Ответ

0 голосов
/ 21 октября 2018

Android Oreo и выше строго ограничивают типы наложения, которые вы можете использовать, как вы уже видели.В Oreo введена новая константа TYPE_APPLICATION_OVERLAY для приложений, но при этом она устарела и запрещена для старых констант.

Однако TYPE_APPLICATION_OVERLAY не существует в Nougat и ниже, поэтому попытка его использования приведет кSecurityException.

Заменить

mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

на

mProgressDialog.getWindow().setType(
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
        else 
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);

Что касается того, почему он все еще падает на Oreo и выше с TYPE_APPLICATION_OVERLAY, разрешение SYSTEM_ALERT_WINDOW нене является обычным разрешением во время выполнения и не отображается в разделе «Разрешения» в информации о приложении.Имя пользователя для него - «Рисовать поверх других приложений» (обычно), и оно находится на странице общей информации о приложении или в разделе «Настройки»> «Приложения»> «Специальный доступ».

Вы не можете предоставить его программнокак с разрешениями во время выполнения, где у вас есть простой диалог для его предоставления.Вместо этого вам нужно проверить, предоставлено ли разрешение, а если нет, запустите страницу «Настройки», чтобы позволить пользователю предоставить его: Как программно предоставить разрешение «рисовать поверх других приложений» в Android?


Тем не менее, я не очень понимаю, почему простой диалог прогресса должен быть полноценным оверлеем.Фактически, ProgressDialog полностью устарел.Вам следует подумать о переходе на простой ProgressBar или, если вы хотите сохранить ProgressDialog, удалить строку setType().

...