精华内容
下载资源
问答
  • Android获取应用占用空间

    千次阅读 2016-07-22 23:06:21
    最近项目中需要获取手机中各个应用的占用空间,但是百度上的提供的各种方法均不能获取到应用大小,可能由于版本迭代部分方法不能使用,经过改正后,此方法可以正确获取应用大小。获取应用的大小需要对Java反射,...

     
    最近项目中需要获取手机中各个应用的占用的空间,但是百度上的提供的各种方法均不能获取到应用大小,可能由于版本迭代部分方法不能使用,经过改正后,此方法可以正确获取应用大小。获取应用的大小需要对Java反射,AIDL有一定了解。

    获取应用大小需要一下权限

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

    1. 建立aidl文件

    我们需要建立2个AIDL文件,以下两个aidl文件必须放在android.content.pm包下边(Android要求使用同一个AIDL接口时的包结构需完全相同),使用studio的同学oneway可能会报错,不要理会它。开发工具用studio,在写完以下两个文件后重新编译一次工程(Build->MakeProject)。

    文件1:PackageStats.aidl
    package android.content.pm;
    
    parcelable PackageStats;
    
    package android.content.pm;
    
    文件2:IPackageStatsObserver.aidl
    import android.content.pm.PackageStats;
    
    oneway interface IPackageStatsObserver {
        void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
    }
    

    以下是包结构图,一定要相同:

    aidl结构

    2. 重写IPackageStatesObserver.Sub

    重写IPackageStatesObserver.Sub,无论是否成功获取到应用占用空间的信息都会回调其中onGetStatsCompleted方法

    public class PackageStatsObserver extends IPackageStatsObserver.Stub {
    
         * @param pStats  应用占用空间封装的类
         * @param succeeded 是否成功获取包信息
         */
        @Override
        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
                throws RemoteException {
    
            long cacheSize = pStats.cacheSize; //缓存大小
            long dataSize = pStats.dataSize;  //数据大小
            long codeSize = pStats.codeSize;  //应用程序大小
            Log.d("abc", "onGetStatsCompleted: " + cacheSize + ":" + dataSize + ":" + codeSize);
        }
    }
    

    3. 通过反射机制执行方法

    PackageManager packageManager = getPackageManager();
    //通过反射机制获得方法,
    //网络上大部分getDeclareMethod的参数为"getPackageSizeInfo", String.class,int.class, IPackageStatsObserver.class
    Method getPackageSizeInfo = packageManager.getClass().getDeclaredMethod(
        "getPackageSizeInfo", String.class,int.class, IPackageStatsObserver.class);
    
    //调用方法,待调用流程完成后会回调PkgSizeObserver类的方法
    getPackageSizeInfo.invoke(packageManager, pkgName,0, new PkgSizeObserver());
    

    为了方便大家理解清楚,我绘制了以下流程图

    这里写图片描述
    getDeclareMethod中的参数int.class是我经过实验后加进去的,之前无法获取应用的正确应用信息原因就是缺少第二个参数,经过以上几个步骤就可以成功的返回应用占用空间大小的信息了。

    由于网络上的大部分方式都不能正确的获取应用占用的空间,因此写出了本人的分析过程。

    4. 分析过程

    如果已经正确获取了应用大小信息,将getDeclareMethod方法中的in.class以及invoke中的0删除,此时恢复到了网络流传的版本。然后运行程序,此时会控制台会打印以下错误:

    java.lang.NoSuchMethodException: getPackageSizeInfo[class java.lang.String, interface android.content.pm.IPackageStatsObserver]
    

    通过以上异常可以知道 getPackageSizeInfo(String,IPackageStatsObserver)这个方法不存在,接下来我们看一下方法中是否存在名字为getPackageSizeInfo的方法呢?我们插入一下代码:

    protected void onCreate(Bundle savedInstanceState) {
            ...
        try{    
            Method[] methods = packageManager.getClass().getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                if (methods[i].getName().contains("getPackageSizeInfo")) {
                    Log.d(TAG,"存在getPackageSizeInfo");
                }
            }
        }
         Method getPackageSizeInfo = packageManager.getClass().getDeclaredMethod(
            "getPackageSizeInfo", String.class,int.class, IPackageStatsObserver.class);
         ...
    

    执行了以上代码后控制台输出了:存在getPackageSizeInfo,证明存在getPackageSizeInfo方法,而且是有且仅有一个getPackageSizeInfo方法,此处可以断定,一定是参数写错了,因此我们获取这这方法的参数

    ...
    if (methods[i].getName().contains("getPackageSizeInfo")) {
        Method method = methods[i];
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (int j = 0; j < parameterTypes.length; j++) {
            Log.d("abc",parameterTypes[j].getCanonicalName());
        }
    }
    ...
    

    控制台输出了如下结果:

    java.lang.String
    int
    android.content.pm.IPackageStatsObserver
    

    很明显,在之前传递的参数有误,正确的参数为getPackageSizeInfo(String,int,IPackageStatsObserver)

    因此正确的反射方式为之前提到的方式,如下:

    Method getPackageSizeInfo = packageManager.getClass().getDeclaredMethod(
        "getPackageSizeInfo", String.class,int.class, IPackageStatsObserver.class);
    
    getPackageSizeInfo.invoke(packageManager, pkgName,0, new PkgSizeObserver());
    
    展开全文
  • Android ApplicationInfo 应用程序信息 1、简述 1 ApplicationInfo 2、 ApplicationInfo 获取对应应用程序的信息

    志在巅峰的攀登者,不会陶醉在沿途的某个脚印之中,在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天、每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不妨来瞅瞅码农的轨迹。

    如果你有兴趣 你可以关注一下公众号 biglead 来获取最新的学习资料。


    Android ApplicationInfo 应用程序信息

    • 1 ApplicationInfo是android.content.pm包下的一个实体类,用于封装应用的信息,flags是其中的一个成员变量public int flags = 0;用于保存应用的标志信息。

    • 2 ApplicationInfo 通过它可以得到一个应用基本信息。
      这些信息是从AndroidManifest.xml的< application >标签获取的

    • 3 ApplicationInfo对象里保存的信息都是标签里的属性值

    • 4 ApplicationInfo与ResolveInfo比较:前者能够得到Icon、Label、meta-data、description。后者只能得到Icon、Label

    2、获取ApplicationInfo
    2.1 、获取手机上安装所有程序对应的 ApplicationInfo
    
    /**
    * 获取手机上安装的所有的程序对应的 ApplicationInfo
    * 它是通过解析AndroidManifest.xml的< application>标签中得到的,所以它能得到所有的app
    *
    * 获取手机上的所有的安装的应用程序信息
    *  参数为 标识   一般为 PackageManager.GET_UNINSTALLED_PACKAGES
    */
    List<ApplicationInfo> list = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
    
    
    2.2 、获取指定包名对应的 ApplicationInfo
    
     /**
    * 获取指定应用程序  ApplicationInfo
    *  参数一对应应用程序的包名
    *  参数二 应用程序对应的标识  通常为 0
    */
    
    ApplicationInfo applicationInfo = packageManager.getApplicationInfo("com.androidlongs.contactsapplication", 0);
    
    
    3、通过ApplicationInfo来获取应用程序的 基本信息
    3.1 、获取应用程序对应的包名、应用名称
    
    //获取应用图标
    Drawable drawable = applicationInfo.loadIcon(packageManager);
    
    //获取应用程序的 包名
    String appPackageName = applicationInfo.packageName;
    
    //获取应用名
    //参数 packageManager  是应用管理者对象 
    String appName =applicationInfo.loadLabel(packageManager).toString();
    
    
    
    3.2 、获取应用程序对应数据的目录以及占用的空间大小
    //获取应用存放数据目录
    String dir = applicationInfo.sourceDir;
    Log.d("app  ","应用存放数据目录 " +dir);
     
     //获取应用数据大小
    ong length = new File(dir).length();
    
    //转换为 M
    float size = length*1f/1024/1024;
    Log.d("app  ","应用数据大小 " +length+"\t"+size);
    
    
    3.3 、判断是否安装在外置储存空间存
    //判断是否安装在外存
    int flags = applicationInfo.flags;
    if((flags&ApplicationInfo.FLAG_EXTERNAL_STORAGE)==ApplicationInfo.FLAG_EXTERNAL_STORAGE){
        Log.d("app  "," 安装在 外置存储空间 ");
    }else {
        Log.d("app  "," 安装在 内置存储空间 ");
    }
    
    3.4 、判断应用程序是否是系统应用
    
    //判断是否是系统应用
    if((flags&ApplicationInfo.FLAG_SYSTEM)==ApplicationInfo.FLAG_SYSTEM){
        Log.d("app  ","  是系统应用  ");
    }else{
        Log.d("app  ","  不是系统应用  ");
    }
    
    
    3.5 、manageSpaceActivityName
    /**
      * 从”android:manageSpaceActivity“属性得到
      * 用于指定一个Activity来管理数据,
      * 它最终会出现在设置->应用程序管理中,
      * 默认为按钮为”清除数据”,指定此属性后,该按钮可点击跳转到该Activity, 让用户选择性清除哪些数据。若不设置则为null.
     */
    String activityName = applicationInfo.manageSpaceActivityName;
    Log.i("applicationInfo", "activityName: " + activityName);
    
    
    
    
    3.6 、获取应用程序运行的进程
    /**
     * 从”android:process“属性得到,注明应用运行的进程名。或不设置则默认为应用包名。
     */
    String processName = applicationInfo.processName;
    Log.i("applicationInfo", "processName: " + processName);
    
    
    3.7 、其他配置信息简述
    // 配置文件中的android:backupAgent属性值,用于备份
    	String backupAgentName = applicationInfo.backupAgentName;
    	Log.i("applicationInfo", "backupAgentName: " + backupAgentName);
    	// 获取继承Application类的对象,维护全局的Application状态
    	//但一般都不用继承的方式,可以通过Context.getApplicationContext()方法得到
    	String className = applicationInfo.className;
    	Log.i("applicationInfo", "className: " + className);
    
    
    
    
    	/**
    	 * 可选项,访问当前应用所有组件需要声明的权限,从”android:permission“属性得到。
    	  */
    	String permisson = applicationInfo.permission;
    	Log.i("applicationInfo", "permisson: " + permisson);
    	// 创建对象时,传入的是GET_SHARED_LIBRARY_FILES该属性才有值
    	String[] files = applicationInfo.sharedLibraryFiles;
    	Log.i("applicationInfo", "files: " + files);
    	// 存放数据的路径  应用数据目录。
    	String dataPath = applicationInfo.dataDir;
    	Log.i("applicationInfo", "dataPath: " + dataPath);
    	// 本地路径  JNI本地库存放路径。
    	String nativePath = applicationInfo.nativeLibraryDir;
    	Log.i("applicationInfo", "nativePath:" + nativePath);
    	// 公共资源路径
    	String punlicSourcePath = applicationInfo.publicSourceDir;
    	Log.i("applicationInfo", "punlicSourcePath: " + punlicSourcePath);
    	// 资源路径  应用APK的全路径
    	String sourcePath = applicationInfo.sourceDir;
    	Log.i("applicationInfo", "sourcePath: " + sourcePath);
    
    	/**
    	 * 当前应用所有Activity的默认task密切性。
    	 * 可以参考ActivityInfo的taskAffinity,从”android:taskAffinity“属性得到。
    	 * 具体taskAffinity是怎么影响到Activity在task的启动, 后面会在Activity启动模式中细讲
    	 */
    	String taskAffinity = applicationInfo.taskAffinity;
    	Log.i("applicationInfo", "taskAffinity: " + taskAffinity);
    	// 如果是false,代表application里的所有组件都禁用
    	boolean enable = applicationInfo.enabled;
    	Log.i("applicationInfo", "enable: " + enable);
    	// 表述资源文件的标识
    	int descriRes = applicationInfo.descriptionRes;
    	Log.i("applicationInfo", "descriRes: " + descriRes);
    	int flag = applicationInfo.flags;
    	Log.i("applicationInfo", "flag: " + flag);
    	// 指定smallest screen width的值,超过这个值,就要开启屏幕兼容
    	int compatibleWidth = applicationInfo.compatibleWidthLimitDp;//android:compatibleWidthLimitDp属性
    	Log.i("applicationInfo", "compatibleWidth: " + compatibleWidth);
    	// 同上,只是这时候用户无法禁止屏幕兼容模式,说明是强制启动屏幕兼容
    	int largestWidth = applicationInfo.largestWidthLimitDp;//android:largestWidthLimitDp属性
    	Log.i("applicationInfo", "largestWidth: " + largestWidth);
    	// 所需屏幕空间的最短尺寸,
    	int samllestWidth = applicationInfo.requiresSmallestWidthDp;//android:requiresSmallestWidthDp属性
    	Log.i("applicationInfo", "samllestWidth: " + samllestWidth);
    	// 应用所需的最小sdk版本
    	int sdkVersion = applicationInfo.targetSdkVersion;
    	Log.i("applicationInfo", "sdkVersion: " + sdkVersion);
    	int theme = applicationInfo.theme;
    	Log.i("applicationInfo", "theme: " + theme);//android:theme=
    	int uid = applicationInfo.uid;
    	Log.i("applicationInfo", "uid: " + uid);
    	// 配置文件中的uiOptions属性的值
    	int uiOptions = applicationInfo.uiOptions;
    	Log.i("applicationInfo", "uiOptions: " + uiOptions);
    
    

    完毕
    在这里插入图片描述

    展开全文
  • Android通过IPackageStatsObserver.aidl 、PackageStats.aidl两个AIDL文件获取第三方应用占用大小,包括缓存、数据、应用大小,经验证和手机设置里面显示的大小完全一致。。。。。。如果还需要其他比如清除缓存之...
  • 使用 Electron 获取应用和用户系统信息 此系列文章的应用示例已发布于 GitHub: electron-api-demos-Zh_CN. 可以 Clone 或下载后运行查看. 欢迎 Star . 使用几个 Node.js 和 Electron 模块, 您可以收集有关用户系统,...

    使用 Electron 获取应用和用户系统信息

    此系列文章的应用示例已发布于 GitHub: electron-api-demos-Zh_CN. 可以 Clone 或下载后运行查看. 欢迎 Star .

    使用几个 Node.js 和 Electron 模块, 您可以收集有关用户系统, 应用程序或屏幕的信息.

    相关文档的链接位于下面的示例中.

    获取应用信息

    支持: Win, macOS, Linux | 进程: Both

    主进程的 app 模块可用于获取应用程序在用户计算机上的位置.

    在这个示例中, 要从渲染器进程获取信息, 我们使用 ipc 模块向主进程发送一条消息, 来请求应用程序的路径.

    查看更多 应用模块文档.

    渲染器进程

    const ipc = require('electron').ipcRenderer
    
    const appInfoBtn = document.getElementById('app-info')
    
    appInfoBtn.addEventListener('click', function () {
      ipc.send('get-app-path')
    })
    
    ipc.on('got-app-path', function (event, path) {
      const message = `当前应用程序位于: ${path}`
      document.getElementById('got-app-info').innerHTML = message
    })
    

    主进程

    const app = require('electron').app
    const ipc = require('electron').ipcMain
    
    ipc.on('get-app-path', function (event) {
      event.sender.send('got-app-path', app.getAppPath())
    })
    

    获取版本信息

    支持: Win, macOS, Linux | 进程: Both

    process 模块内置在 Node.js 中(因此您可以在主进程和渲染器进程中使用此模块), 而在 Electron 应用程序中, 此对象还有一些更有用的属性.

    下面的示例将获取应用程序正在使用的 Electron 版本.

    查看更多 进程文档.

    渲染器进程

    const versionInfoBtn = document.getElementById('version-info')
    
    const electronVersion = process.versions.electron
    
    versionInfoBtn.addEventListener('click', function () {
      const message = `当前应用正在使用的 Electron 版本: ${electronVersion}`
      document.getElementById('got-version-info').innerHTML = message
    })
    

    高级技巧

    查找 Chromium, Node.js 和 V8 的版本.

    Electron 还在 process.versions 对象中包括 Chromium, Node.js 和 V8 的版本. 您可以通过在 Electron 应用中打开开发人员工具并键入 process.versions 来快速查看.

    // 返回正在使用的 Chromium 版本
    process.versions.chrome
    // 返回正在使用的 V8 版本
    process.versions.v8
    // 返回正在使用的 Node 版本
    process.versions.node

    获取系统信息

    支持: Win, macOS, Linux | 进程: Both

    Node.js 的 os 模块提供了有关用户操作系统的有效信息. 它内置在 Node.js 中, 可以在主进程和渲染器进程中使用.

    在下面的示例中, 我们通过模块返回主目录的位置.

    在浏览器中查看 完整 os 文档

    渲染器进程

    const os = require('os')
    const homeDir = os.homedir()
    
    const sysInfoBtn = document.getElementById('sys-info')
    
    sysInfoBtn.addEventListener('click', function () {
      const message = `当前系统主目录是: ${homeDir}`
      document.getElementById('got-sys-info').innerHTML = message
    })
    

    获取屏幕信息

    支持: Win, macOS, Linux | 进程: Both

    Electron 的 screen 模块可以获取有关屏幕大小, 显示, 光标位置等信息. 在下面的示例中, 我们将获取所使用的显示器的尺寸.

    在浏览器中查看 完整 screen 文档

    渲染器进程

    const electronScreen = require('electron').screen
    
    const screenInfoBtn = document.getElementById('screen-info')
    const size = electronScreen.getPrimaryDisplay().size
    
    screenInfoBtn.addEventListener('click', function () {
      const message = `当前屏幕是: ${size.width}px x ${size.height}px`
      document.getElementById('got-screen-info').innerHTML = message
    })
    

    高级技巧

    尺寸差异.

    示例中的 .size 方法返回屏幕的原始尺寸, 但由于系统菜单栏, 这可能不是您的应用程序的实际可用空间.

    要获取可用屏幕空间的大小, 请使用 .workAreaSize 方法. 而使用 .workArea 方法将返回坐标以及可用屏幕空间的尺寸.

    如果这边文章对您有帮助, 感谢 下方点赞 或 Star GitHub: electron-api-demos-Zh_CN 支持, 谢谢.

    展开全文
  • 一、前言 二、效果预览 三、实现步骤 (1)开启权限 (2)AIDL文件导入 ...最近仿微信存储空间做了个demo,其中最麻烦的地方就是获取APP应用大小了。做完之后自己总结把获取方式封装成了工具,方便...

    一、前言

    二、效果预览

    三、实现步骤

    (1)开启权限

    (2)AIDL文件导入

    (3)引用工具类

    (4)使用方式

    四、功能分解

    (1)单例模式

    (2)设置监听数据获取回调

    (3)开始获取数据

    五、Demo地址

    六、参考文档

    七、内容推荐


    一、前言

    最近仿微信存储空间做了个demo,其中最麻烦的地方就是获取APP应用大小了。做完之后自己总结把获取方式封装成了工具,方便以后再次使用。期望大家喜欢。如果感觉还不错的话,不妨顶一个,收藏一下...。如果有什么不妥的地方也可以留言指出,相互学习,共同进步

    二、效果预览

    先看看Demo、不满意请使劲怼作者、不要怼我哈

    三、实现步骤

    1. 开启权限
    2. AIDL文件导入
    3. 引用工具类
    4. 使用方式

    (1)开启权限

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

    (2)AIDL文件导入

    Android8.0之前没有对应的API提供,需要引入两个AIDL文件。

    IPackageStatsObserver.aidl

    package android.content.pm;
    import android.content.pm.PackageStats;
    interface IPackageStatsObserver {
        oneway void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
    }
    

    PackageStats.aidl

    package android.content.pm;
    
    parcelable PackageStats;

    导入AIDL文件后需要编译一下,系统自动生成java文件,不清楚AIDL是什么的可以百度一下..

    这里就不解释了。长话短说也解释不清楚,让大家自己学习,还可能获得更多成就感

    (3)引用工具类

    AppSizeUtils.class

    import android.app.usage.StorageStats;
    import android.app.usage.StorageStatsManager;
    import android.content.Context;
    import android.content.pm.IPackageStatsObserver;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageStats;
    import android.os.Build;
    import android.os.storage.StorageManager;
    import android.os.storage.StorageVolume;
    import android.support.annotation.RequiresApi;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.List;
    import java.util.UUID;
    
    /**
     * TODO 获取APP应用  缓存大小 数据大小 应用大小
     */
    
    public class AppSizeUtils {
        private static AppSizeUtils mApiUrl;
    
        private AppSizeUtils() {
        }
    
        public static AppSizeUtils getInstance() {
            if (mApiUrl == null) {
                synchronized (AppSizeUtils.class) {
                    if (mApiUrl == null) {
                        mApiUrl = new AppSizeUtils();
                    }
                }
            }
            return mApiUrl;
        }
    
        /**
         * TODO 获取应用总大小
         */
        public void init(Context context) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                getAppSizeO(context);
            } else {
                getAppsize(context);
            }
        }
    
        /**
         * 获取应用的大小
         */
        @RequiresApi(api = Build.VERSION_CODES.O)
        public void getAppSizeO(Context context) {
            StorageStatsManager storageStatsManager = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);
            StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            //获取所有应用的StorageVolume列表
            List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
            for (StorageVolume item : storageVolumes) {
                String uuidStr = item.getUuid();
                UUID uuid;
                if (uuidStr == null) {
                    uuid = StorageManager.UUID_DEFAULT;
                } else {
                    uuid = UUID.fromString(uuidStr);
                }
                int uid = getUid(context, context.getPackageName());
                //通过包名获取uid
                StorageStats storageStats = null;
                try {
                    storageStats = storageStatsManager.queryStatsForUid(uuid, uid);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (onBackListent != null) {
                    onBackListent.backData(storageStats.getCacheBytes(), storageStats.getDataBytes(), storageStats.getAppBytes());
                }
    
            }
        }
    
        /**
         * 根据应用包名获取对应uid
         */
        public int getUid(Context context, String pakName) {
            try {
                return context.getPackageManager().getApplicationInfo(pakName, PackageManager.GET_META_DATA).uid;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            return -1;
        }
    
        /**
         * 获取应用大小8.0以下
         */
        public void getAppsize(Context context) {
            try {
                Method method = PackageManager.class.getMethod("getPackageSizeInfo", new Class[]{String.class, IPackageStatsObserver.class});
                // 调用 getPackageSizeInfo 方法,需要两个参数:1、需要检测的应用包名;2、回调
                method.invoke(context.getPackageManager(), context.getPackageName(), new IPackageStatsObserver.Stub() {
                    @Override
                    public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) {
                        if (onBackListent != null) {
                            onBackListent.backData(pStats.cacheSize, pStats.dataSize, pStats.codeSize);
                        }
    
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public OnBackListent onBackListent;
    
        public interface OnBackListent {
            void backData(long cacheSize, long dataSize, long codeSize);
        }
    
        public AppSizeUtils setDatasListent(OnBackListent listent) {
            onBackListent = listent;
            return this;
        }
    }

    (4)使用方式

            AppSizeUtils.getInstance().setDatasListent(new AppSizeUtils.OnBackListent() {
                @Override
                public void backData(long cacheSize, long dataSize, long codeSize) {
                    Log.e(TAG, "缓存大小: "+cacheSize + " 数据大小: " + dataSize + " 应用大小: " + codeSize );
    
                }
            }).init(MyApplication.getContext());
        /**
    	 * 将文件大小显示为GB,MB等形式
    	 */
    	public static String size(long size)
    	{
    		if (size / (1024 * 1024 * 1024) > 0)
    		{
    			float tmpSize = (float) (size) / (float) (1024 * 1024 * 1024);
    			DecimalFormat df = new DecimalFormat("#.##");
    			return "" + df.format(tmpSize) + "GB";
    		}
    		else if (size / (1024 * 1024) > 0)
    		{
    			float tmpSize = (float) (size) / (float) (1024 * 1024);
    			DecimalFormat df = new DecimalFormat("#.##");
    			return "" + df.format(tmpSize) + "MB";
    		}
    		else if (size / 1024 > 0)
    		{
    			return "" + (size / (1024)) + "KB";
    		}
    		else
    			return "" + size + "B";
    	}

    顺便提供一下转化方法,省的自己写麻烦..

    这里就不贴Demo源码了,主要功能代码已经贴出来。大家可以根据需求随便更改,想要源码的也可以在底部链接下载。。

    四、功能分解

    (1)单例模式

    private static AppSizeUtils mApiUrl;
        private AppSizeUtils() { }
        public static AppSizeUtils getInstance() {
            if (mApiUrl == null) {
                synchronized (AppSizeUtils.class) {
                    if (mApiUrl == null) {
                        mApiUrl = new AppSizeUtils();
                    }
                }
            }
            return mApiUrl;
        }

    这个就不解释了,不了解的可以看看《JAVA 设计模式——单例模式》

    (2)设置监听数据获取回调

    为什么要写这个回调呢?

    在获取App大小的时候有延迟(有耗时操作),所以不能立马得到数据。所以当时写了个广播用来通知什么时候获取到数据,不过那样的话写起来有点麻烦,所以写了个回调。

        public OnBackListent onBackListent;
    
        public interface OnBackListent {
            void backData(long cacheSize, long dataSize, long codeSize);
        }
    
        public AppSizeUtils setDatasListent(OnBackListent listent) {
            onBackListent = listent;
            return this;
        }

    具体调用方法时机看下面↓↓↓

    (3)开始获取数据

    只需调用init(Context context)

        /**
         * TODO 获取应用总大小
         */
        public void init(Context context) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
               getAppSizeO(context, context.getPackageName());
            } else {
                getAppsize(context);
            }
        }

    因为android8.0之后有提供新的API用来获取应用大小

    所以8.0之前和8.0之后获取方式不一样

    Android8.0之前

    /**
         * 获取应用大小8.0以下 
         */
        public void getAppsize(Context context) {
            try {
                Method method = PackageManager.class.getMethod("getPackageSizeInfo", new Class[]{String.class, IPackageStatsObserver.class});
                // 调用 getPackageSizeInfo 方法,需要两个参数:1、需要检测的应用包名;2、回调
                method.invoke(context.getPackageManager(), context.getPackageName(), new IPackageStatsObserver.Stub() {
                    @Override
                    public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) {
                        //数据获取时机 使用回调
                        onBackListent.backData(pStats.cacheSize, pStats.dataSize, pStats.codeSize);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    Android8.0之后

    /**
         * 8.0获取应用的大小
         */
        @RequiresApi(api = Build.VERSION_CODES.O)
        public void getAppSizeO(Context context) {
            StorageStatsManager storageStatsManager = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);
            StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            //获取所有应用的StorageVolume列表
            List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
            for (StorageVolume item : storageVolumes) {
                String uuidStr = item.getUuid();
                UUID uuid;
                if (uuidStr == null) {
                    uuid = StorageManager.UUID_DEFAULT;
                } else {
                    uuid = UUID.fromString(uuidStr);
                }
                int uid = getUid(context, context.getPackageName());
                //通过包名获取uid
                StorageStats storageStats = null;
                try {
                    storageStats = storageStatsManager.queryStatsForUid(uuid, uid);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                onBackListent.backData(storageStats.getCacheBytes(), storageStats.getDataBytes(), storageStats.getAppBytes());
            }
        }

    文采不好,就不多废话了。不过写了这么多,大家记得捧捧场哈

    五、Demo地址

    https://github.com/DayorNight/BLCS

    六、参考文档

    https://blog.csdn.net/qinjuning/article/details/6892054

    七、内容推荐

    简书:https://www.jianshu.com/p/d97c0de8bc18

    《Android Rxjava+Retrofit网络请求框架封装(一)》

    《 Android 仿微信多语言切换》

    《Android 仿微信全局字体大小调整》

    《Android JUnit单元测试》

    《Android Log日志封装》

    如果你觉得我写的不错或者对您有所帮助的话

    不妨顶一个【微笑】,别忘了点赞、收藏、加关注哈

    看在我花了这么多时间整理写成文章分享给大家的份上,记得手下留情哈

    您的每个举动都是对我莫大的支持

    展开全文
  • 今天碰到个问题,想获取某个已安装的包的大小... 再后来,我想起系统的设置里面有一个应用程序管理,它里面列出了所有程序的占用空间大小、数据大小和缓存大小。恩,这个就是突破口。以前写过一篇获取其他包的Context
  • Android 获取手机存储总大小,系统占用空间

    万次阅读 多人点赞 2018-12-08 22:00:02
    一、Android 存储介绍及通常查询大小 手机存储有两种,内置内存和外置内存(SD),目前可...言归正传,获取存储空间,很简单,使用中的 android.os.StatFs,传入需查阅的内存路径即可查询总内存大小,剩余可用空间,...
  • Android项目:手机安全卫士(15)—— 获取手机安装应用与存储空间1 介绍今天来讲讲手机安全卫士的第三个功能:软件管理,其实也不应该叫管理,称为软件应用信息查看更正确一点,就是显示手机已安装的应用,并显示...
  • 一个 iPhone 应用程序,用于获取 iPhone 在空间中的方向(“态度”)。 姿态在屏幕上显示为四元数。 您可以输入要将四元数发送到的服务器的 IP 地址和端口号。 模型3d 一个 Mac 应用程序,它将以 3D 方式显示 i
  • ArcMap使用指南——获取矢量点空间位置对应的栅格数据单元值简介数据步骤 简介 平时的应用中,我们在ArcMap中打开了两个图层,其中一个为矢量点图层,一个为栅格图层,二者具有相同的空间范围,我们有时候需要知道每...
  • 该文章是“个人电脑历史记录清除软件”项目的系统应用系列文章. 前面已经讲述了如何清除IE浏览器的历史记录、获取Windows最近访问文件记录、清除回收站等功能.现在我需要完成的是删除USB设备上的U盘、手机、移动硬盘...
  • 最近在做appStore时,涉及到一个第三方app下载视频后将车机存储撑爆的问题,从而影响到我们车机自带的app...缓存获取获取各个应用程序的缓存大小,可以通过使用PackageManager.getPackageSizeInfo方法来获取,但是它
  • 今天小编就为大家分享一篇Android 获取应用缓存大小与清除缓存的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • Android获取应用所占内存大小

    千次阅读 2015-04-22 10:29:40
     // 占用的内存   int[] pids = new int[] {pid};   Debug.MemoryInfo[] memoryInfo = mActivityManager.getProcessMemoryInfo(pids);   int memorySize = memoryInfo[0].dalvikPrivateDirty;    ...
  • //获取可以被应用程序使用的可用空间块的数量 getFreeBlocksLong(); //获取全部包括不能被应用程序使用空间块的数量 getBlockCountLong();//获取全部空间块的数量 getBlockSizeLong();//获
  • 1. 获取应用数据/缓存大小 其中pm为实例化的PackageManager,因为需要遍历所有的已安装的应用。因此需要开启子线程进行处理。 还有需要注意的是,在Android4.2之前getPackageSizeInfo方法参数是没有第二个int类型...
  • 获取Android应用专属缓存存储目录

    万次阅读 2016-07-19 15:00:17
    获取Android应用专属缓存存储目录
  • 引言:在Java应用中,对于内存的占用是一个让人头疼的问题,那在我们怀疑内存占用出现问题时,如何找到我们想要的答案,比如哪个占用了最多的内存,本文讲尝试给出一个思路。
  • 用列表方式展示手机中的所有应用,展示应用名称,应用包名和是否为系统应用,开发者可以根据自己需要,进行修改,过滤
  • // 获取当前任务所占用的内存(单位:MB) - (double)usedMemory { task_basic_info_data_t taskInfo; mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT; kern_return_t kernReturn = task_info...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 703,337
精华内容 281,334
关键字:

获取应用占用空间