获取已安装的应用程序

yan*_*nko 18 android

我正在试图弄清楚如何获得已安装应用的大小.
什么已经失败:
- new File('/data/app/some.apk')报告不正确的大小
- PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer)- @hide并依赖于一些模糊IPackageStatsObserver的结果,所以我不能通过反射调用它.

Jos*_*ger 27

不幸的是,目前没有正式的方法可以做到这一点.但是,如果将aID 和AIDL导入到项目中并生成存根,则可以调用PackageManager隐藏getPackageSize方法.然后,您可以使用反射来调用:PackageStatsIPackageStatsObservergetPackageSize

PackageManager pm = getPackageManager();

Method getPackageSizeInfo = pm.getClass().getMethod(
    "getPackageSizeInfo", String.class, IPackageStatsObserver.class);

getPackageSizeInfo.invoke(pm, "com.android.mms",
    new IPackageStatsObserver.Stub() {

        @Override
        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
            throws RemoteException {

            Log.i(TAG, "codeSize: " + pStats.codeSize);
        }
    });
Run Code Online (Sandbox Code Playgroud)

这显然是一个大黑客,不应该用于公共应用程序.

  • 在Android N中不再有效:https://code.google.com/p/android/issues/detail?id = 222516&sort = - open&cfpec = ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20已开启 (5认同)
  • 我发现有些设备没有getPackageSizeInfo()然后你得到这个java.lang.NoSuchMethodException:getPackageSizeInfo() (4认同)

kra*_*iec 19

你可以通过gettting到apk文件的路径,并检查其长度来简化:

final PackageManager pm = context.getPackageManager();
ApplicationInfo applicationInfo = pm.getApplicationInfo(appInfo.getPackage(), 0);
File file = new File(applicationInfo.publicSourceDir);
int size = file.length();
Run Code Online (Sandbox Code Playgroud)

  • 这是APK文件的大小.每个应用程序使用的其余文件如何:缓存,数据库,下载内容,......? (6认同)
  • 什么是appInfo对象? (4认同)

dro*_*ida 5

以下是@Josef Pfleger的补充答案,以征求意见

"我发现某些设备没有getPackageSizeInfo()然后你得到这个java.lang.NoSuchMethodException:getPackageSizeInfo()"@ ATom 11月29日11:15.

在api 16(Build.VERSION.SDK_INT> 16)之后,该方法

 PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer);
Run Code Online (Sandbox Code Playgroud)

改变成:

PackageManager.getPackageSizeInfo(String packageName, int userHandle, IPackageStatsObserver observer);
Run Code Online (Sandbox Code Playgroud)

并且新添加的参数的解释userHandle是:应该检索其大小信息的用户.

所以我们应该这样做:

 int sysVersion= Build.VERSION.SDK_INT;
    if (pkgName != null) {// packageName

        PackageManager pm = getPackageManager(); 
        try {

            Class<?> clz = pm.getClass();
            if (sysVersion>16) {
                Method myUserId=UserHandle.class.getDeclaredMethod("myUserId");//ignore check this when u set ur min SDK < 17
                int userID = (Integer) myUserId.invoke(pm);
                Method getPackageSizeInfo = clz.getDeclaredMethod(
                        "getPackageSizeInfo", String.class,int.class,
                        IPackageStatsObserver.class);//remember add int.class into the params 
                getPackageSizeInfo.invoke(pm,pkgName, userID, new PkgSizeObserver());
            } else {//for old API
                Method getPackageSizeInfo = clz.getDeclaredMethod(
                        "getPackageSizeInfo", String.class,
                        IPackageStatsObserver.class);
            getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver());
            }
        } catch (Exception ex) {
            Log.e(TAG, "NoSuchMethodException");
            ex.printStackTrace();
            throw ex;} 
Run Code Online (Sandbox Code Playgroud)

该类需要回调如下:

private class PkgSizeObserver extends IPackageStatsObserver.Stub {
    /***
     * @param pStatus
     * @param succeeded
     */
    @Override
    public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
            throws RemoteException {
        cachesize = pStats.cacheSize;//remember to declare these fields 
        datasize = pStats.dataSize; 
        codesize = pStats.codeSize; 
        totalsize = cachesize + datasize + codesize;
        Log.i("123","cachesize--->" + cachesize + " datasize---->"
                + datasize + " codeSize---->" + codesize);
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用此方法来解析long2string,然后你可以看到xx MB而不是long像2342334 :)

private String formateFileSize(long size) {
    return Formatter.formatFileSize(MainActivity.this, size);
}
Run Code Online (Sandbox Code Playgroud)