Альтернативный способ получить значок и имя приложения в Android 11+?

После того, как пользователь включил доступ к использованию, вам, похоже, требуется новое разрешение QUERY_ALL_PACKAGES в Android 11+ для доступа к имени и значку пакета с помощью следующего кода:

String appName = packageManager.getApplicationLabel( packageManager.getApplicationInfo(packageName,0) );
Drawable appIcon = packageManager.getApplicationIcon(packageName);

В противном случае я бы получил PackageManager.NameNotFoundException для любой строки кода, что, очевидно, означает, что у меня нет доступа к понятному имени и значку приложения.

Есть ли другой способ добиться этого без разрешения? Я не могу найти другого способа, кроме кода до Android 11.

Я поддерживаю приложение, которое также имеет функцию экранного времени, но Google отказался одобрить включение этого «конфиденциального разрешения» в мое обновление, несмотря на то, что оно является основной функцией моего приложения, утверждая, что есть другие способы добиться этого, но также отказывается разрабатывать.

Ведение белого списка приложений с помощью <queries> на самом деле не является жизнеспособным способом сделать это, очевидно, из-за бесконечного количества возможностей. Даже простое ведение списка самых популярных приложений потребует от пользователей присылать мне список своих приложений, и даже в этом случае мне придется каждый раз выпускать новое обновление.

«Очевидно, что вести белый список приложений с использованием <queries> на самом деле не является жизнеспособным способом из-за бесконечного количества возможностей» — если вам нужны только приложения с запускаемыми действиями, используйте <queries> для этой Intent структуры.

CommonsWare 23.05.2024 14:10

Великолепно! Никогда не думал об использовании фильтра намерений запросов таким образом... Выглядит хорошо. Теперь мне не нужно удалять функцию, потому что Google не одобрил бы новое разрешение в моем обновлении. Не уверен, что мне следует добавить это в качестве ответа здесь, но большое спасибо! = Д

Ken 23.05.2024 22:05
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

           if (appInfo != null) {
                String appName = appInfo.appName;
                Drawable appIcon = appInfo.appIcon;
                Log.d("AppInfo", "App Name: " + appName);
            } else {
                Log.d("AppInfo", "App not found");
            }

// использование приведенного выше кода в методе oncreate

    private AppInfo getAppInfo(String packageName) {
            PackageManager packageManager = getPackageManager();
            try {
                ApplicationInfo appInfo;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    appInfo = packageManager.getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA));
                } else {
                    appInfo = packageManager.getApplicationInfo(packageName, 0);
                }
                String appName = packageManager.getApplicationLabel(appInfo).toString();
                Drawable appIcon = packageManager.getApplicationIcon(packageName);
                return new AppInfo(appName, appIcon);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        private static class AppInfo {
            String appName;
            Drawable appIcon;
    
            AppInfo(String appName, Drawable appIcon) {
                this.appName = appName;
                this.appIcon = appIcon;
            }
        }

Спасибо за быстрый ответ. К сожалению, без разрешения «Запросить все» выдается то же самое исключение NameNotFound в Android 13. getApplicationInfo для работы также требуется минимум Тирамису 33, а не 30 рандов.

Ken 23.05.2024 13:08

Я попробую для вас что-нибудь еще, это поможет расширить мои знания.

Viraj S 23.05.2024 13:21
Ответ принят как подходящий

Я провел немало исследований по этому поводу, когда писал эту бесплатную книгу. По крайней мере, на данный момент правила видимости пакетов очень детализированы: если пакет соответствует правилу белого списка, то все, что есть в пакете, доступно в PackageManager.

Итак, вам нужно посмотреть, есть ли общий белый список, который вы можете использовать (или, возможно, несколько), который будет охватывать большинство или все приложения, которые вас интересуют.

Так, например, если для вас важны пакеты с запускаемыми действиями, вы можете использовать:

    <queries>
        <intent>
            <action android:name = "android.intent.action.MAIN" />
            <category android:name = "android.intent.category.LAUNCHER" />
        </intent>
    </queries>

Это разблокирует все в PackageManager для приложений с запускаемыми действиями, даже такие вещи, как getApplicationLabel() и getApplicationIcon(), которые технически не связаны с запускаемыми действиями.

Другие вопросы по теме