it-swarm.com.de

Wie überprüfe ich, ob eine App eine Nicht-System-App in Android ist?

Ich erhalte eine Liste von ApplicationInfo-Objekten mit packageManager.getInstalledApplications (0) und versuche, sie danach zu kategorisieren, ob sie eine Systemanwendung sind oder nicht.

Ich verwende seit einiger Zeit die beschriebene Methode here , jedoch nachdem ich in meiner Anwendung gesehen hatte, dass einige der Apps nicht in der Liste der Nicht-System-Apps enthalten waren (z. B. Facebook) das System auf der SD-Karte zu installieren). Nachdem ich die eigentliche Dokumentation für ApplicationInfo.FLAG_SYSTEM gelesen und verstanden habe, dass sie System-Apps nicht wirklich filtert, suche ich jetzt nach einem neuen Ansatz. 

Meine Vermutung ist, dass es eine große Kluft zwischen UIDs von System- und Nicht-System-Apps gibt, die ich sammeln kann, um diese Unterscheidung zu treffen, aber bis jetzt habe ich keine Antwort gefunden. Ich habe auch andere Flags wie ApplicationInfo.FLAG_EXTERNAL_STORAGE durchgesehen, unterstütze jedoch API 1.5.

Hat jemand eine echte Lösung dafür (ohne FLAG_SYSTEM)?

31
Phil

Nun, es ist meiner Meinung nach eine schlampige Lösung (was wäre, wenn/data/app nicht das apps-Verzeichnis auf allen Geräten ist?), Aber nach einer gründlichen Suche habe ich Folgendes gefunden:

for (ApplicationInfo ai : appInfo) {
    if (ai.sourceDir.startsWith("/data/app/")) {
        //Non-system app
    }
    else {
        //System app
    }
}
6
Phil
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
Nitin

Ich hatte den Eindruck, dass alle Apps im System-Image System-Apps sind (und normalerweise in /system/app installiert sind).

Wenn FLAG_SYSTEM nur auf Systemanwendungen eingestellt ist, funktioniert dies auch für Apps im externen Speicher:

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

Alternativ können Sie das Befehlszeilenprogramm pm in Ihrem Telefon verwenden.

Syntax:

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

Dann:

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

Sie können die Signatur der Anwendung überprüfen, die mit dem System signiert wurde. Wie unten

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

Sie können mehr Code auf meinem Blog erhalten So überprüfen Sie, ob die Anwendung eine System-App ist oder nicht (durch signierte Signatur)

16
Pankaj Kumar

Wenn es sich bei einer Anwendung um eine Nicht-Systemanwendung handelt, muss sie einen Start-Intent haben, mit dem sie gestartet werden kann. Wenn der Start-Intent null ist, ist es eine System-App.

Beispiel für System-Apps: "com.Android.browser.provider", "com.google.Android.voicesearch". 

Für die obigen Apps erhalten Sie NULL, wenn Sie Intent abfragen.

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
Darshan Patel

Hier gibt es ein kleines Missverständnis. Für Android ist der Begriff "System-App" eine, die auf dem System-Image installiert wird. Sie sagt nothing darüber, von welchem ​​Entwickler sie stammt. Wenn also ein OEM entscheidet, Facebook vorab auf das System-Image zu laden, handelt es sich um eine System-App, die auch weiterhin gilt, unabhängig davon, wo Updates für die App installiert werden. Sie werden nicht sicher auf dem System-Image installiert, da dies schreibgeschützt ist.

ApplicationInfo.FLAG_SYSTEM ist also korrekt, aber das scheint nicht die Frage zu sein, die Sie stellen. Ich denke, Sie fragen, ob ein Paket mit dem Systemzertifikat signiert ist. Was nicht unbedingt ein guter Indikator für alles ist, kann von Gerät zu Gerät unterschiedlich sein und einige überraschende Komponenten von Vanilla Android sind nicht mit dem Systemzertifikat signiert, auch wenn Sie dies erwarten.

In neueren Versionen von Android gibt es einen neuen Pfad (/ system/priv-app /), der versucht, der Installationsort für "echte" System-Apps zu sein. Apps, die gerade im System-Image vorinstalliert sind, landen in/system/app /. Siehe AOSP Privileged vs System App

5
cyngus

Es gibt 2 Arten von Nicht-SystemAnwendungen:

  1. Apps, die aus dem Google Play Store heruntergeladen wurden
  2. Vorinstallierte Apps nach Gerätehersteller

Dieser Code gibt eine Liste aller oben genannten Anwendungen zurück:

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));
    }
}
4
Kushal

Wenn Sie eine APK-Datei haben und prüfen möchten, ob es sich um eine System-App oder einen Benutzer handelt Eine einfache Logik: - System-App-Dateien sind nicht beschreibbar

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

Es gibt verschiedene Möglichkeiten, um zu sehen, ob die App eine System-App anhand ihres Paketnamens ist (einige der Codes in diesem Beitrag werden verwendet)

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;
    }
}
1
if (!packageInfo.sourceDir.toLowerCase().startsWith("/system/"))
1
MiladCoder

Dies ist eine vereinfachte und effizientere Version anderer hier aufgeführter Antworten. Es ist effizienter, wenn Sie direkt über die ApplicationInfos iterieren.

    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
        }
    }
1
Tyler

Hier ist eine AppUtil, die ich zu diesem Zweck geschrieben habe .
Anwendungsbeispiel:

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
AivarsDa