Как проверить, является ли приложение несистемным приложением в Android?

Я получаю список ApplicationInfo Объекты с packageManager.getInstalledApplications(0) и попытки классифицировать их по тому, являются ли они системным приложением.

Какое-то время я использовал описанную здесь технику, однако, увидев это в своем приложении, некоторые из приложений не попали в список несистемных приложений (например, Facebook, который, когда доступно, просит систему установить себя на SD-карту). карта). После следующего прочтения фактической документации для ApplicationInfo.FLAG_SYSTEM и понимания того, что она на самом деле не фильтрует системные приложения, я сейчас ищу новый подход.

Я предполагаю, что существует большой разрыв между UID системных и несистемных приложений, которые я могу собрать, чтобы провести это различие, но пока я не нашел ответа. Я также посмотрел на другие флаги, такие как ApplicationInfo.FLAG_EXTERNAL_STORAGEОднако я поддерживаю API 1.5.

Есть ли у кого-нибудь реальное решение для этого (не включая FLAG_SYSTEM)?

14 ответов

Решение

Ну, на мой взгляд, это неаккуратное решение (а что если /data/app не каталог приложений на всех устройствах?), Но после тщательного поиска я пришел к следующему:

for (ApplicationInfo ai : appInfo) {
    if (ai.sourceDir.startsWith("/data/app/")) {
        //Non-system app
    }
    else {
        //System app
    }
}
PackageManager pm = mcontext.getPackageManager();
List<PackageInfo> list = pm.getInstalledPackages(0);

for(PackageInfo pi : list) {
    ApplicationInfo ai = pm.getApplicationInfo(pi.packageName, 0);

    System.out.println(">>>>>>packages is<<<<<<<<" + ai.publicSourceDir);

    if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
        System.out.println(">>>>>>packages is system package"+pi.packageName);          
    }
}

У меня сложилось впечатление, что все приложения в системном образе являются системными приложениями (и обычно устанавливаются в /system/app).

Если FLAG_SYSTEM устанавливается только для системных приложений, это будет работать даже для приложений во внешнем хранилище:

boolean isUserApp(ApplicationInfo ai) {
    int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
    return (ai.flags & mask) == 0;
}

Альтернативой является использование pm программа командной строки в вашем телефоне.

Синтаксис:

pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]

pm list packages: prints all packages, optionally only
  those whose package name contains the text in FILTER.  Options:
    -f: see their associated file.
    -d: filter to only show disbled packages.
    -e: filter to only show enabled packages.
    -s: filter to only show system packages.
    -3: filter to only show third party packages.
    -i: see the installer for the packages.
    -u: also include uninstalled packages.

Код:

ProcessBuilder builder = new ProcessBuilder("pm", "list", "packages", "-s");
Process process = builder.start();

InputStream in = process.getInputStream();
Scanner scanner = new Scanner(in);
Pattern pattern = Pattern.compile("^package:.+");
int skip = "package:".length();

Set<String> systemApps = new HashSet<String>();
while (scanner.hasNext(pattern)) {
    String pckg = scanner.next().substring(skip);
    systemApps.add(pckg);
}

scanner.close();
process.destroy();

Затем:

boolean isUserApp(String pckg) {
    return !mSystemApps.contains(pckg);
}

Вы можете проверить подпись приложения, которое оно подписало с системой. Как ниже

/**
 * Match signature of application to identify that if it is signed by system
 * or not.
 * 
 * @param packageName
 *            package of application. Can not be blank.
 * @return <code>true</code> if application is signed by system certificate,
 *         otherwise <code>false</code>
 */
public boolean isSystemApp(String packageName) {
    try {
        // Get packageinfo for target application
        PackageInfo targetPkgInfo = mPackageManager.getPackageInfo(
                packageName, PackageManager.GET_SIGNATURES);
        // Get packageinfo for system package
        PackageInfo sys = mPackageManager.getPackageInfo(
                "android", PackageManager.GET_SIGNATURES);
        // Match both packageinfo for there signatures
        return (targetPkgInfo != null && targetPkgInfo.signatures != null && sys.signatures[0]
                .equals(targetPkgInfo.signatures[0]));
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

Вы можете получить больше кода в моем блоге. Как проверить, является ли приложение системным или нет (подписано подписью)

Существует 2 типа несистемных приложений:

  1. Приложения, загруженные из Google Play Store
  2. Предустановленные приложения производителем устройства

Этот код вернет список всех вышеперечисленных приложений:

ArrayList<ApplicationInfo> mAllApp = 
        mPackageManager.getInstalledApplications(PackageManager.GET_META_DATA);

for(int i = 0; i < mAllApp.size(); i++) {
    if((mAllApp.get(i).flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
         // 1. Applications downloaded from Google Play Store
        mAllApp1.add(mAllApp.get(i));
    }

    if((mAllApp.get(i).flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
        // 2. Applications preloaded in device by manufecturer
        mAllApp1.add(mAllApp.get(i));
    }
}

Здесь есть небольшое недоразумение. Для Android понятие "системное приложение" - это то, которое устанавливается на образ системы, оно ничего не говорит о том, от какого разработчика оно пришло. Таким образом, если OEM решит предварительно загрузить Facebook в образ системы, это будет системное приложение, и оно останется таковым, независимо от того, где будут установлены обновления приложения. Они точно не будут установлены на образ системы, потому что он доступен только для чтения.

Поэтому ApplicationInfo.FLAG_SYSTEM верен, но это не тот вопрос, который вы задаете. Я думаю, что вы спрашиваете, подписан ли пакет с системным сертификатом. Что не обязательно является хорошим показателем чего-либо, это может варьироваться от устройства к устройству, и некоторые удивительные компоненты на Android Android не подписаны сертификатом системы, даже если вы ожидаете, что они будут.

В более новых версиях Android существует новый путь, /system/ priv-app/, который пытается быть местом установки "реальных" системных приложений. Приложения, которые предварительно загружены в образ системы, затем попадают в /system/ app/. См. Приложение AOSP Privileged vs System

Если приложение является несистемным приложением, оно должно иметь намерение запуска, с помощью которого оно может быть запущено. Если цель запуска равна нулю, то это системное приложение.

Пример системных приложений: "com.android.browser.provider", "com.google.android.voicesearch".

Для вышеуказанных приложений вы получите NULL при запросе запуска Intent.

PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for(ApplicationInfo packageInfo:packages){
    if( pm.getLaunchIntentForPackage(packageInfo.packageName) != null ){
                String currAppName = pm.getApplicationLabel(packageInfo).toString();
               //This app is a non-system app
    }
}

Вот различные возможные способы узнать, является ли приложение системным приложением по имени пакета (использовались некоторые коды из этого поста)

package com.test.util;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Pattern;

import timber.log.Timber;


public class SystemAppChecker {
    private PackageManager packageManager = null;

    public SystemAppChecker(Context context) {
        packageManager = context.getPackageManager();
    }

    /**
     * Check if system app by 'pm' command-line program
     *
     * @param packageName
     *            package name of application. Cannot be null.
     * @return <code>true</code> if package is a system app.
     */
    public boolean isSystemAppByPM(String packageName) {
        if (packageName == null) {
            throw new IllegalArgumentException("Package name cannot be null");
        }
        ProcessBuilder builder = new ProcessBuilder("pm", "list", "packages", "-s");
        Process process = null;
        try {
            process = builder.start();
        } catch (IOException e) {
            Timber.e(e);
            return false;
        }

        InputStream in = process.getInputStream();
        Scanner scanner = new Scanner(in);
        Pattern pattern = Pattern.compile("^package:.+");
        int skip = "package:".length();

        Set<String> systemApps = new HashSet<String>();
        while (scanner.hasNext(pattern)) {
            String pckg = scanner.next().substring(skip);
            systemApps.add(pckg);
        }

        scanner.close();
        process.destroy();

        if (systemApps.contains(packageName)) {
            return true;
        }
        return false;
    }

    /**
     * Check if application is preloaded.
     *
     * @param packageName
     *            package name of application. Cannot be null.
     * @return <code>true</code> if package is preloaded.
     */
    public boolean isSystemPreloaded(String packageName) {
        if (packageName == null) {
            throw new IllegalArgumentException("Package name cannot be null");
        }
        try {
            ApplicationInfo ai = packageManager.getApplicationInfo(
                    packageName, 0);
            if (ai.sourceDir.startsWith("/system/app/") || ai.sourceDir.startsWith("/system/priv-app/")) {
                return true;
            }
        } catch (NameNotFoundException e) {
            Timber.e(e);
        }
        return false;
    }

    /**
     * Check if the app is system signed or not
     *
     * @param packageName
     *            package of application. Cannot be blank.
     * @return <code>true</code> if application is signed by system certificate,
     *         otherwise <code>false</code>
     */
    public boolean isSystemSigned(String packageName) {
        if (packageName == null) {
            throw new IllegalArgumentException("Package name cannot be null");
        }
        try {
            // Get packageinfo for target application
            PackageInfo targetPkgInfo = packageManager.getPackageInfo(
                    packageName, PackageManager.GET_SIGNATURES);
            // Get packageinfo for system package
            PackageInfo sys = packageManager.getPackageInfo(
                    "android", PackageManager.GET_SIGNATURES);
            // Match both packageinfo for there signatures
            return (targetPkgInfo != null && targetPkgInfo.signatures != null && sys.signatures[0]
                    .equals(targetPkgInfo.signatures[0]));
        } catch (PackageManager.NameNotFoundException e) {
            Timber.e(e);
        }
        return false;
    }

    /**
     * Check if application is installed in the device's system image
     *
     * @param packageName
     *            package name of application. Cannot be null.
     * @return <code>true</code> if package is a system app.
     */
    public boolean isSystemAppByFLAG(String packageName) {
        if (packageName == null) {
            throw new IllegalArgumentException("Package name cannot be null");
        }
        try {
            ApplicationInfo ai = packageManager.getApplicationInfo(
                    packageName, 0);
            // Check if FLAG_SYSTEM or FLAG_UPDATED_SYSTEM_APP are set.
            if (ai != null
                    && (ai.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
                return true;
            }
        } catch (NameNotFoundException e) {
            Timber.e(e);
        }
        return false;
    }
}

Это упрощенная и более эффективная версия других ответов, перечисленных здесь. Это более эффективно, если вы просто перебираете ApplicationInfos напрямую.

    List<ApplicationInfo> applications = context.getPackageManager()
            .getInstalledApplications(PackageManager.GET_META_DATA);
    for(ApplicationInfo appInfo : applications){
        if((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0){
            // Not a system app
        }
    }

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

Ниже KitKat 4.4 всем приложениям в / system / app были предоставлены привилегированные разрешения. Они были даже в приложении «Калькулятор». Это могло быть нарушение безопасности. Таким образом, они были разделены на обычные и привилегированные системные приложения, а обычные не имеют привилегированных разрешений выше KitKat 4.4. Итак, эти утилиты имеют это в виду. Также они имеют в виду следующие обозначения:

  • Подписанное платформой приложение: любое приложение, подписанное с помощью ключа платформы / системы (чтобы у них были разрешения на подпись системы), независимо от того, установлено оно в системных разделах или нет.
  • Системное приложение: любое приложение, установленное в разделах системы.
  • Обновленное системное приложение: любое системное приложение, которое было обновлено (то есть теперь оно также установлено в / data / app).
  • Привилегированное системное приложение: ниже KitKat 4.4, любое приложение, установленное в / system / app; начиная с KitKat 4.4, только приложения, установленные в / system / priv-app (я действительно имею в виду только / system). У этих приложений есть привилегированные разрешения.
  • Обычное системное приложение: только с KitKat 4.4, без привилегированных разрешений, даже если они все еще являются системными приложениями. Ниже KitKat 4.4 их не существует.

Примечания к системному разделу: до Oreo 8.1 был только один: / system. Начиная с Pie (9), есть также / vendor и / product.

Имея это в виду, вот 2 функции:

      /**
 * <p>Checks if an app is installed on the system partitions and was updated.</p>
 *
 * @param applicationInfo an instance of {@link ApplicationInfo} for the package to be checked
 *
 * @return true if it is, false otherwise
 */
private static boolean isUpdatedSystemApp(@NonNull final ApplicationInfo applicationInfo) {
    return (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}

/**
 * <p>Checks if an app is installed in the system partitions (ordinary app or privileged app, doesn't matter).</p>
 *
 * @param applicationInfo an instance of {@link ApplicationInfo} for the package to be checked
 *
 * @return true if it is, false otherwise
 */
private static boolean isSystemApp(@NonNull final ApplicationInfo applicationInfo) {
    // Below Android Pie (9), all system apps were in /system. As of Pie, they can ALSO be in /vendor and /product.
    boolean ret_value = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        // FLAG_SYSTEM checks if it's on the system image, which means /system. So to check for /vendor and
        // /product, here are 2 special flags.
        ret_value = ret_value || (applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
        ret_value = ret_value || (applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
    }

    return ret_value;
}

Чтобы проверить, является ли приложение привилегированным системным приложением или обычным системным приложением и / или подписано ли оно ключом платформы / системы, я оставлю 3 функции ниже. Я считаю, что это не по теме вопроса, но я поставлю его на случай, если кому-то вроде меня это понадобится.

      /**
 * <p>Checks if an app is an ordinary system app (installed on the system partitions, but no privileged or signature
 * permissions granted to it).</p>
 * <p>Note: will return false for any app on KitKat 4.4 and below.</p>
 *
 * @param applicationInfo an instance of {@link ApplicationInfo} for the package to be checked
 *
 * @return true if it is, false otherwise
 */
private static boolean isOrdinarySystemApp(@NonNull final ApplicationInfo applicationInfo) {
    // It's an ordinary system app if it doesn't have any special permission privileges (it's not a Privileged app
    // nor is it signed with the system key).
    boolean ret_value = isSystemApp(applicationInfo) && !hasPrivilegedPermissions(applicationInfo);
    final boolean signed_system_key = hasSystemSignaturePermissions(applicationInfo);
    ret_value = ret_value && signed_system_key;

    return ret_value;
}

/**
 * <p>Checks if an app has signature permissions - checks if it's signed with the platform/system certificate by
 * comparing it to the "android" package.</p>
 * <br>
 * <p>ATTENTION: if the chosen app was signed multiple times and the system is running below Android Pie, this check
 * may return false wrongly, since it checks if ALL the signatures from the "android" package and the chosen
 * application match. If at least one doesn't match in both, this will return false. So use with caution in case of
 * multiple signers. With only one signer, it's all right.</p>
 *
 * @param applicationInfo an instance of {@link ApplicationInfo} for the package to be checked
 * @return true if it is, false otherwise
 */
private static boolean hasSystemSignaturePermissions(@NonNull final ApplicationInfo applicationInfo) {
    // If on Pie or above, check with a private flag (appeared on Pie only).
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        return (applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY) != 0;
    }

    // Else, check by comparing signatures of a platform-signed app and the chosen app.
    return UtilsGeneral.getContext().getPackageManager().checkSignatures(applicationInfo.packageName, "android")
            == PackageManager.SIGNATURE_MATCH;
}

/**
 * <p>"Value for {@link ApplicationInfo#flags}: set to {@code true} if the application
 * is permitted to hold privileged permissions.</p>
 *
 * {@hide}"
 * <p>NOTE: Only on API 19 through API 22.</p>
 */
private static final int FLAG_PRIVILEGED = 1 << 30;

/**
 * <p>Checks if an app is a Privileged App.</p>
 * <p>Note: will return true for any system app below KitKat 4.4.</p>
 *
 * @param applicationInfo an instance of {@link ApplicationInfo} for the package to be checked
 *
 * @return true if it is, false otherwise
 */
private static boolean hasPrivilegedPermissions(@NonNull final ApplicationInfo applicationInfo) {
    // Check if it's an app installed in the system partitions. If it is, check with methods that apply only to
    // apps installed on the system partitions.
    if (isSystemApp(applicationInfo)) {
        // If it's below KitKat 4.4 and it's a system app, it's a privileged one automatically.
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return true;
        }

        // If on Marshmallow or above, check with a private flag.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
                return true;
            }
        }

        // If between KitKat 4.4 and Lollipop 5.1, use a deleted flag.
        if ((applicationInfo.flags & FLAG_PRIVILEGED) != 0) {
            return true;
        }
    }

    // In case none returned true above, the app may still be signed with the platform/system's key, which will
    // grant it exactly all permissions there are (which includes privileged permissions - ALL permissions).
    return hasSystemSignaturePermissions(applicationInfo);
}

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

      /**
 * <p>Gets a list of folders a system app might be installed in, depending on the device's Android version.</p>
 * <p>Note that an updated system app will report as being installed in /data/app. For these locations to be
 * checked, the app must not have been updated. If it has, it's not possible to tell using the directory, I think.</p>
 *
 * @param privileged_app true if it's to return a list for privileged apps, false if it's for ordinary system apps,
 *                       null if it's to return a list for both types
 *
 * @return a list of folders its APK might be in
 */
@NonNull
private static String[] getAppPossibleFolders(@Nullable final Boolean privileged_app) {
    final Collection<String> ret_folders = new ArrayList<>(5);

    final String PRIV_APP_FOLDER = "/system/priv-app";
    final String ORD_APP_SYSTEM_FOLDER = "/system/app";
    final String ORD_APP_VENDOR_FOLDER = "/vendor/app";
    final String ORD_APP_PRODUCT_FOLDER = "/product/app";

    if (privileged_app == null) {
        ret_folders.add(PRIV_APP_FOLDER);
        ret_folders.add(ORD_APP_SYSTEM_FOLDER);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            ret_folders.add(ORD_APP_VENDOR_FOLDER);
            ret_folders.add(ORD_APP_PRODUCT_FOLDER);
        }
    } else if (privileged_app) {
        ret_folders.add(PRIV_APP_FOLDER);
    } else {
        ret_folders.add(ORD_APP_SYSTEM_FOLDER);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            ret_folders.add(ORD_APP_VENDOR_FOLDER);
            ret_folders.add(ORD_APP_PRODUCT_FOLDER);
        }
    }

    // Leave it in 0 size allocation. Or null values will appear, and I don't want to need to be careful about it.
    return ret_folders.toArray(new String[0]);

    /*
    Use with:

    // If it's an updated system app, its APK will be said to be in /data/app, and the one on the system partitions
    // will become unused. But if it's not updated, it's all fine and the APK path can be used to check if it's
    // a privileged app or not.
    if (!isUpdatedSystemApp(applicationInfo)) {
        for (final String folder : getAppPossibleFolders(false)) {
            if (applicationInfo.sourceDir.startsWith(folder)) {
                return true;
            }
        }
    }
    */
}
if (!packageInfo.sourceDir.toLowerCase().startsWith("/system/"))

Если у вас есть APK-файл и вы хотите проверить, является ли это Системное приложение или Пользователь установил простую логику:-Системное приложение. Файлы недоступны для записи.

private boolean isSystemApkFile(File file){
   return !file.canWrite();
}

Вы можете использовать checkSignatures чтобы определить, является ли приложение системным или нет.

Все системные приложения подписаны одним и тем же ключом.

https://developer.android.com/reference/android/content/pm/PackageManager

А подписанный системным ключом стоит пакет "android".

    val checkPackage: String = "com.package.to.check"
    val systemPackageName = "android"
    if (packageManager.checkSignatures(systemPackageName, checkPackage) == PackageManager.SIGNATURE_MATCH) {
        Log.d("TUT", "System app")
    } else {
        Log.d("TUT", "Non-System app")
    }

Вот приложение, которое я написал для этой цели.
Пример использования:

new AppsUtil(this).printInstalledAppPackages(AppsUtil.AppType.USER);

AppsUtil.java

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;

public class AppsUtil
{
    public static final String  TAG = "PackagesInfo";
    private Context             _context;
    private ArrayList<PckgInfo> _PckgInfoList;

    public enum AppType 
    {
        ALL {
            @Override
            public String toString() {
              return "ALL";
            }
          },
        USER {
            @Override
            public String toString() {
              return "USER";
            }
          },
        SYSTEM {
            @Override
            public String toString() {
              return "SYSTEM";
            }
          }
    }

    class PckgInfo
    {
        private AppType appType;
        private String  appName     = "";
        private String  packageName = "";
        private String  versionName = "";
        private int     versionCode = 0;

        private void prettyPrint()
        {
            Log.i(TAG, appName + "\n  AppType: " + appType.toString() + "\n  Package: " + packageName + "\n  VersionName: " + versionName + "\n  VersionCode: " + versionCode);
        }
    }

    public AppsUtil(Context context)
    {
        super();
        this._context = context;
        this._PckgInfoList = new ArrayList<PckgInfo>();
    }

    public void printInstalledAppPackages(AppType appType)
    {
        retrieveInstalledAppsPackages();
        Log.i(TAG, "");
        for (int i = 0; i < _PckgInfoList.size(); i++)
        {
            if (AppType.ALL == appType)
            {
                _PckgInfoList.get(i).prettyPrint();
            }
            else
            {
                if (_PckgInfoList.get(i).appType == appType)
                    _PckgInfoList.get(i).prettyPrint();
            }
        }
    }

    public ArrayList<PckgInfo> getInstalledAppPackages(AppType appType)
    {
        retrieveInstalledAppsPackages();
        ArrayList<PckgInfo> resultPInfoList = new ArrayList<PckgInfo>();

        if (AppType.ALL == appType)
        {
            return _PckgInfoList;
        }
        else
        {
            for (int i = 0; i < _PckgInfoList.size(); i++)
            {
                if (_PckgInfoList.get(i).appType == appType)
                    resultPInfoList.add(_PckgInfoList.get(i));
            }
            return resultPInfoList;
        }
    }

    private void retrieveInstalledAppsPackages()
    {
        PackageManager pm = _context.getPackageManager();
        List<PackageInfo> packs = pm.getInstalledPackages(0);
        for (PackageInfo pi : packs)
        {
            try
            {
                PckgInfo newInfo = new PckgInfo();
                ApplicationInfo ai = pm.getApplicationInfo(pi.packageName, 0);

                newInfo.appType = getAppType(ai);
                newInfo.appName = pi.applicationInfo.loadLabel(pm).toString();
                newInfo.packageName = pi.packageName;
                newInfo.versionName = pi.versionName;
                newInfo.versionCode = pi.versionCode;
                _PckgInfoList.add(newInfo);
            }
            catch (NameNotFoundException e)
            {
                e.printStackTrace();
            }
        }
    }

    AppType getAppType(ApplicationInfo ai)
    {
        AppType resultType ;
        if (isUserApp(ai))
            resultType = AppType.USER;
        else
            resultType = AppType.SYSTEM;

        return resultType;
    }

    boolean isUserApp(ApplicationInfo ai)
    {
        int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
        return (ai.flags & mask) == 0;
    }
}
Другие вопросы по тегам