美文网首页
Flutter 学习 之 获取 APP 所在安卓手机中占用的存储

Flutter 学习 之 获取 APP 所在安卓手机中占用的存储

作者: 半城半离人 | 来源:发表于2022-04-27 20:45 被阅读0次

    翻了好多插件好像也没一个获取手机内存和app相关数据的插件, 那没办法只能从原生获取了

    1. 与原生交互首先创建MethodChannel 如果之前有创建直接发送方法

    如果没写过可以查看 https://flutter.cn/docs/development/platform-integration/platform-channels?tab=android-channel-java-tab
    或者 https://flutter.cn/docs/development/packages-and-plugins/developing-packages
    再或者 https://www.jianshu.com/p/afeb4bac1fc8

    2.Android 端代码的实现

    2.1. Android添加从dart来的方法

    在methodCall中添加你的方法名称 记得和Dart中要保持一致的名字

        @Override
        public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
    
            switch (call.method) {
                case CommStr.METHOD_APP_DISK_INFO:
                    Map<String, Map<String, String>> appDiskInfo = getAppDiskInfo();
                    result.success(appDiskInfo);
                    break;
                case CommStr.METHOD_BACK_TO_DESKTOP:
                    activity.moveTaskToBack(false);
                    result.success(true);
                    break;
                default:
                    result.notImplemented();
                    break;
            }
        }
    

    2.2. Android O 以上获取的实现的方法

        //获取当前应用的存储信息
        Map<String, Map<String, String>> getAppDiskInfo() {
            Map<String, Map<String, String>> result = new HashMap<>();
            try {//获取存储管理器
                String packageName = activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0).packageName;
                StorageManager storageManager = (StorageManager) activity.getSystemService(Context.STORAGE_SERVICE);
                //储存统计管理器
                final StorageStatsManager storageStatsManager = (StorageStatsManager) activity.getSystemService(Context.STORAGE_STATS_SERVICE);
             
                final List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
                //获取当前用户
                final UserHandle user = android.os.Process.myUserHandle();
                //遍历 有多少个储存器 内部 外部 sd卡
                for (StorageVolume storageVolume : storageVolumes) {
                    //检测到他是挂载状态的 并且是主要的那个一个
                    if ("mounted".equals(storageVolume.getState()) && storageVolume.isPrimary()) {
                      ///获取他的UUID 官方说他的UUID是一样的不能作为唯一凭证什么的...
                        final String uuidStr = storageVolume.getUuid();
                        final UUID uuid = uuidStr == null ? StorageManager.UUID_DEFAULT : UUID.fromString(uuidStr);
                        final StorageStats storageStats = storageStatsManager.queryStatsForPackage(uuid, packageName, user);
                        Map<String, String> resultItem = new HashMap<>();
                        带Str的都是通过代码转好后的 会显示整数 带单位的文字 不过好像是按进率1000算的 按需回传不是必须的
                        resultItem.put("FreeBytesStr", formatFileSize(storageStatsManager.getFreeBytes(uuid)));
                        resultItem.put("TotalBytesStr", formatFileSize(storageStatsManager.getTotalBytes(uuid)));
                        resultItem.put("AppBytesStr", formatFileSize(storageStats.getAppBytes()));
                        resultItem.put("CacheBytesStr", formatFileSize(storageStats.getCacheBytes()));
                        resultItem.put("DataBytesStr", formatFileSize(storageStats.getDataBytes()));
                      这里添加的都是long类型的数字不过转String传回给dart
                      /// 当前磁盘空闲的字节
                        resultItem.put("FreeBytes", String.valueOf(storageStatsManager.getFreeBytes(uuid)));
                         /// 当前磁盘总共的字节
                        resultItem.put("TotalBytes", String.valueOf(storageStatsManager.getTotalBytes(uuid)));
                        /// App 包括安装包什么乱起八糟的大小 具体看官方文档介绍
                        resultItem.put("AppBytes", String.valueOf(storageStats.getAppBytes()));
                        /// 软件的缓存 (内部缓存 外部缓存 加code_cache 一起返回的)
                        resultItem.put("CacheBytes", String.valueOf(storageStats.getCacheBytes()));
                      ////用户的数据 
                        resultItem.put("DataBytes", String.valueOf(storageStats.getDataBytes()));
                    ////磁盘名字 外加上面这些东起一起丢回去
                        result.put(storageVolume.getDescription(activity.getContext()), resultItem);
                    }
                }
            } catch (Exception ignored) {
                Log.e(getClass().getSimpleName(), "出错了", ignored);
            }
            return result;
        }
    
        // 将数字转换成文字
        //[number]数字 转换完的是没有小数的 且内存大小按1000计算
        String formatFileSize(long number) {
            return Formatter.formatShortFileSize(activity.getContext(), number);
        }
    

    3. dart中的操作

    3.1 发送MedthChannel

    class CustomChannelUtil {
      static const MethodChannel _channel =
          MethodChannel(SystemConfig.customChannelName);
       ///获取磁盘信息
      static Future<Map?> get appDiskInfo async {
        final Map? deskInfo = await _channel.invokeMethod(SystemConfig.methodAppDiskInfo);
        return deskInfo;
      }
      static Future<bool?> get backToDesktop async{
        final bool? result = await _channel.invokeMethod(SystemConfig.methodBackToDesktop);
        return result;
      }
    }
    

    3.2 dart端解析

    注意虽然Android那边写的是Map<String,Map<String,String>> 但是dart这边要用Map<Object?,Object?> 接收或者直接写Map;

          Map? result = await CustomChannelUtil.appDiskInfo;
          if (result != null && result.isNotEmpty) {
            deskInfo = result;
            cacheTitle = result.keys.first;
            Map item = result.values.first;
            totalBytes = double.parse(item["TotalBytes"]);
            freeBytes = double.parse(item["FreeBytes"]);
            appTotalBytes = double.parse(item["AppTotalBytes"]);
            appCacheBytes = double.parse(item["CacheBytes"]);
            appBytes = double.parse(item["AppBytes"]);
            appDataBytes = double.parse(item["DataBytes"]);
    

    3.3 Android自带的并不好用 所以我自己写了一个 字节转换工具

    • 可以将文件大小转成合适的单位
    • 可以将文件大小强制转换成指定单位 (如果差距过大可能显示 0 )
    • 可以选择保留几位小数
    • 可以选择按1000算还是1024算
      /// 将文件大小 格式化
      /// [fileSize] 文件大小
      /// [position] 保留几位小数
      /// [scale] 比例 1000/1024
      /// [specified] 0-5 指定的单位 0是B 1是KB 2是mb 3是GB 4是TB 5是PB
      static String formatFileSize(fileSize,
          {position = 2, scale = 1024, specified = -1}) {
        double num = 0;
         List sizeUnit = ["B", "KB", "MB", "GB", "TB", "PB"];
        if (fileSize is String) {
          num = double.parse(fileSize);
        } else if (fileSize is int || fileSize is double) {
          num = fileSize;
        }
        //获取他的单位
        if (num > 0) {
          int unit = log(num) ~/ log(scale);
          if (specified >= 0 && specified < sizeUnit.length) {
            unit = specified;
          }
          double size = num / pow(scale, unit);
          String numStr = formatNum(num: size, position: position);
          return numStr + " " + sizeUnit[unit];
        }
        return "0 B";
      }
    
      ///格式化数字 如果小数后面为0则不显示小数点
      ///[num]要格式化的数字 double 类型
      /// [position] 保留几位小数 int类型
      static formatNum({required double num, required int position}) {
        String numStr = num.toString();
        int dotIndex = numStr.indexOf(".");
        ///当前数字有小数且需要小数位数小于需要的 直接返回当前数字
        if (num % 1 != 0 && (numStr.length - 1 - dotIndex < position)) {
          return numStr;
        }
        int numbs = pow(10, position).toInt();
        //模运算 取余数
        double remainder = num * numbs % numbs;
        //小数点后位数如果小于0则表示只保留整数,余数小于1不会进位防止出现200.01保留一位小数出现200.0的情况
        if (position > 0 && remainder >= 0.5) {
          return num.toStringAsFixed(position);
        }
        return num.toStringAsFixed(0);
      }
    

    相关文章

      网友评论

          本文标题:Flutter 学习 之 获取 APP 所在安卓手机中占用的存储

          本文链接:https://www.haomeiwen.com/subject/afoxyrtx.html