即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

安装应用程序大小

栈溢出 yanchenko 24℃ 0评论
本文目录
[隐藏]

1.原始问题:Getting installed app size

I’m trying to figure out how to get the size of an installed app.
What’s already failed:
new File('/data/app/some.apk') – reports incorrect size
PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer) – is @hide and relies on some obscure IPackageStatsObserver for result so I can’t call it via reflection.

2.被采纳答案

Unfortunately there is currently no official way to do that. However, you can call the PackageManager‘s hidden getPackageSize method if you import the PackageStats and IPackageStatsObserver AIDLs into our project and generate the stubs. You can then use reflection to invoke getPackageSize:

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

That’s obviously a big hack and should not be used for public applications.

3.其他高票答案

3.1.第1个答案

You can do it simplier by gettting path to apk file, and checking its lenght:

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

3.2.第2个答案

Here is additional answer @Josef Pfleger ‘s, for comment

“I found that some device doesn’t have getPackageSizeInfo() then you get this java.lang.NoSuchMethodException: getPackageSizeInfo()” @ ATom Nov 29 ’11 at 15:56.

After api 16( Build.VERSION.SDK_INT >16),the method

 PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer);

changed into:

PackageManager.getPackageSizeInfo(String packageName, int userHandle, IPackageStatsObserver observer);

And the explain for the new added param userHandle is :The user whose size information should be retrieved.

So we should do it like this:

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

The class needed to callback like:

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

And use this method to parse long2string,then you can see xx MB instead of long like 2342334 🙂

private String formateFileSize(long size) {
    return Formatter.formatFileSize(MainActivity.this, size);
}

3.3.第3个答案

Remember the needed permission, I solved these issues by adding the following permission to the manifest:

< uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />

Or this wrong: not use getDeclaredMethod(),should be use getMethod().

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

3.4.第4个答案

package inc.xiomi.apkextrator.entity;

import android.annotation.SuppressLint;
import android.content.ComponentName;
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.content.pm.PackageStats;
import android.content.pm.ResolveInfo;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.Locale;
import java.util.concurrent.Semaphore;

public class AppInfo implements Comparable {

    private Context ctx;
    private ResolveInfo ri;
    private ComponentName componentName = null;
    private PackageInfo pi = null;
    private Drawable icon = null;
    String size = null;
    String name = null;
    // Code size will be here
    long codeSize = 0;
    PackageManager packageManager;
    // Semaphore to handle concurrency
   Semaphore codeSizeSemaphore = new Semaphore(1, true);
    public AppInfo(Context ctx, ResolveInfo ri) {
        this.ctx = ctx;
        this.ri = ri;
        packageManager = ctx.getPackageManager();
        this.componentName = new ComponentName(ri.activityInfo.applicationInfo.packageName, ri.activityInfo.name);
        try {
            pi = ctx.getPackageManager().getPackageInfo(getPackageName(), 0);
        } catch (NameNotFoundException e) {
        }
    }

    public String getName() {
        if (name != null) {
            return name;
        } else {
            try {
                return getNameFromResolveInfo(ri);
            } catch (NameNotFoundException e) {
                return getPackageName();
            }
        }
    }
    public String getSize() {
        if (size != null) {
            return size;
        } else {
            try {
                return getSizeFromResolveInfo(ri);
            } catch (Exception e) {
                return getPackageName();
            }
        }
    }
    public String getActivityName() {
        return ri.activityInfo.name;
    }

    public String getPackageName() {
        return ri.activityInfo.packageName;
    }

    public ComponentName getComponentName() {
        return componentName;
    }

    public String getComponentInfo() {
        if (getComponentName() != null) {
            return getComponentName().toString();
        } else {
            return "";
        }
    }

    public ResolveInfo getResolveInfo() {
        return ri;
    }

    public PackageInfo getPackageInfo() {
        return pi;
    }

    public String getVersionName() {
        PackageInfo pi = getPackageInfo();
        if (pi != null) {
            return pi.versionName;
        } else {
            return "";
        }
    }

    public int getVersionCode() {
        PackageInfo pi = getPackageInfo();
        if (pi != null) {
            return pi.versionCode;
        } else {
            return 0;
        }
    }

    public Drawable getIcon() {
        if (icon == null) {
            icon = getResolveInfo().loadIcon(ctx.getPackageManager());
            /*
            Drawable dr = getResolveInfo().loadIcon(ctx.getPackageManager());
            Bitmap bitmap = ((BitmapDrawable) dr).getBitmap();
            icon = new BitmapDrawable(ctx.getResources(), AppHelper.getResizedBitmap(bitmap, 144, 144));
            */
        }
        return icon;
    }

    @SuppressLint("NewApi")
    public long getFirstInstallTime() {
        PackageInfo pi = getPackageInfo();
        if (pi != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            return pi.firstInstallTime;
        } else {
            return 0;
        }
    }

    @SuppressLint("NewApi")
    public long getLastUpdateTime() {
        PackageInfo pi = getPackageInfo();
        if (pi != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            return pi.lastUpdateTime;
        } else {
            return 0;
        }
    }

    @Override
    public int compareTo(Object o) {
        AppInfo f = (AppInfo) o;
        return getName().compareTo(f.getName());
    }

    @Override
    public String toString() {
        return getName();
    }

    /**
     * Helper method to get an applications name!
     *
     * @param ri
     * @return
     * @throws android.content.pm.PackageManager.NameNotFoundException
     */

    public String getNameFromResolveInfo(ResolveInfo ri) throws NameNotFoundException {
        String name = ri.resolvePackageName;
        if (ri.activityInfo != null) {
            Resources res = ctx.getPackageManager().getResourcesForApplication(ri.activityInfo.applicationInfo);
            Resources engRes = getEnglishRessources(res);

            if (ri.activityInfo.labelRes != 0) {
                name = engRes.getString(ri.activityInfo.labelRes);

                if (name == null || name.equals("")) {
                    name = res.getString(ri.activityInfo.labelRes);
                }

            } else {
                name = ri.activityInfo.applicationInfo.loadLabel(ctx.getPackageManager()).toString();
            }
        }
        return name;
    }
    public String getSizeFromResolveInfo(ResolveInfo ri) throws Exception {

            try {
                codeSizeSemaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace(System.err);
            }
            // Collect some other statistics

            // Collect code size
            try {
                Method getPackageSizeInfo = packageManager.getClass().getMethod("getPackageSizeInfo",
                        String.class,
                        android.content.pm.IPackageStatsObserver.class);

                getPackageSizeInfo.invoke(packageManager, ri.activityInfo.packageName,
                        new android.content.pm.IPackageStatsObserver.Stub() {
                            // Examples in the Internet usually have this method as @Override.
                            // I got an error with @Override. Perfectly works without it.
                            public void onGetStatsCompleted(PackageStats pStats, boolean succeedded)
                                    throws RemoteException {
                                codeSize = pStats.codeSize;
                                Log.e("codeSize", codeSize + "");
                                codeSizeSemaphore.release();
                            }
                        });
            } catch (Exception e) {
                e.printStackTrace(System.err);
            }

        return String.valueOf(codeSize);
    }
    public Resources getEnglishRessources(Resources standardResources) {
        AssetManager assets = standardResources.getAssets();
        DisplayMetrics metrics = standardResources.getDisplayMetrics();
        Configuration config = new Configuration(standardResources.getConfiguration());
        config.locale = Locale.US;
        return new Resources(assets, metrics, config);
    }
}

转载请注明:CodingBlog » 安装应用程序大小

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情