Comment puis-je vérifier si une application est une application non-système dans Android?

je reçois une liste d'objets ApplicationInfo avec packageManager.gettinstalledapplications (0) et tenter de les catégoriser selon qu'il s'agit ou non d'une application système.

pendant un certain temps, j'ai utilisé la technique décrite ici , mais après avoir vu que dans mon application, certaines des applications n'étaient pas dans la liste des applications non-système (comme Facebook , qui lorsque disponible demande au système de s'installer sur la carte SD). Après la lecture suivante la documentation réelle pour ApplicationInfo.FLAG_SYSTEM , et en comprenant qu'il ne filtre pas réellement les applications système, je suis maintenant à la recherche d'une nouvelle approche.

à mon avis, il y a un grand écart entre les uid des applications système et non-système que je peux comprendre pour faire cette distinction, mais pour l'instant je n'ai pas trouvé de réponse. J'ai aussi regardé dans d'autres indicateurs, comme ApplicationInfo.FLAG_EXTERNAL_STORAGE , cependant je supporte L'API 1.5.

est-ce que quelqu'un a une VRAIE solution à cela (n'impliquant pas FLAG_SYSTEM )?

30
demandé sur Community 2012-01-09 10:06:19

11 réponses

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);          
    }
}
24
répondu Nitin 2014-02-10 14:33:55

j'avais l'impression que toutes les applications de l'image système étaient des applications système (et normalement installées dans /system/app ).

si FLAG_SYSTEM n'est défini que pour les applications système, cela fonctionnera même pour les applications en stockage externe:

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

une alternative est d'utiliser le programme de ligne de commande pm dans votre téléphone.

syntaxe:

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.

Code:

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();

puis:

boolean isUserApp(String pckg) {
    return !mSystemApps.contains(pckg);
}
23
répondu sergio91pt 2013-02-02 21:45:36

vous pouvez vérifier la signature de la demande qu'il a signé avec le système. Comme ci-dessous

/**
 * 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;
    }
}

Vous pouvez obtenir plus de code sur mon blog Comment faire pour vérifier si l'application est le système d'application ou non (En signature)

15
répondu Pankaj Kumar 2014-07-08 14:17:44

Eh bien, c'est une solution bâclée à mon avis (et si /data/app n'est pas le répertoire apps sur tous les appareils?), mais après une recherche approfondie, c'est ce que j'ai trouvé:

for (ApplicationInfo ai : appInfo) {
    if (ai.sourceDir.startsWith("/data/app/")) {
        //Non-system app
    }
    else {
        //System app
    }
}
5
répondu Phil 2012-01-09 17:19:13

si une Application est une application non-système, elle doit avoir une intention de lancement par laquelle elle peut être lancée. Si l'intention de lancement est nul, alors c'est une application système.

exemple D'applications système: "com.Android.navigateur.fournisseur", "com.Google.Android.voicesearch".

pour les applications ci-dessus, vous obtiendrez NULL lorsque vous interrogez pour l'intention de lancement.

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
    }
}
5
répondu Darshan Patel 2013-08-19 20:09:47

il y a un petit malentendu ici. Pour Android, la notion d'une" application système "est celui qui est installé sur l'image du système, il est dit rien sur ce développeur d'où il vient. Donc, si un OEM décide de précharger Facebook sur L'image du système, il s'agit d'une application système et il le restera, quel que soit l'endroit où les mises à jour de L'application seront installées. Ils ne seront pas installés sur l'image du système, bien sûr, parce qu'il est en lecture seule.

So ApplicationInfo.FLAG_SYSTEM est correct, mais ce n'est pas la question que vous posez. Je pense que vous demandez si un paquet est signé avec le certificat du système. Ce qui n'est pas nécessairement un bon indicateur de quoi que ce soit, cela peut varier d'un appareil à l'autre et certains composants surprenants sur vanilla Android ne sont pas signés avec le certificat de système, même si vous pouvez vous attendre à ce qu'ils soient.

dans les nouvelles versions D'Android il ya un nouveau chemin, / system / priv-app/ qui tente d'être l'emplacement d'installation pour système "réel" des applications. Les applications qui sont simplement pré-chargées sur l'image système finissent alors dans /system/app/. Voir PSBA Privilégié vs app Système

5
répondu cyngus 2017-05-23 12:17:25

il y a 2 types de Non - système applications:

  1. applications téléchargées à partir de Google Play Store
  2. applications préchargées par le fabricant de l'appareil

ce code retournera une liste de toutes les demandes ci-dessus:

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));
    }
}
3
répondu Kushal 2018-09-16 01:07:18
if (!packageInfo.sourceDir.toLowerCase().startsWith("/system/"))
1
répondu MiladCoder 2013-12-12 21:28:33

si vous avez un fichier APK et que vous voulez vérifier si l'application système ou L'utilisateur est installé une logique Simple:- les fichiers app système ne sont pas inscriptibles

private boolean isSystemApkFile(File file){
   return !file.canWrite();
}
1
répondu Shivam Agrawal 2016-12-27 15:46:06

voici un article que j'ai écrit dans ce but.

exemple D'Usage:

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;
    }
}
0
répondu AivarsDa 2016-07-26 15:53:21

Voici différentes manières de voir si l'application est un système d'application par son nom (utilisé certains des codes dans ce post)

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;
    }
}
0
répondu Vinayak Bevinakatti 2017-12-29 22:16:59