1.获取ram大小

两种方法:

第一从是从MemoryInfo中获取:

private void getRamInfo1(){
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);

    ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();

    manager.getMemoryInfo(info);

    long memory = info.availMem;

    long totalMemory = info.totalMem;
    Log.d(TAG, "memory: "+memory+" totalMemory "+totalMemory);
}

第二是从节点中获取:

可以用adb看一下节点中的信息

	MemTotal:        1638688 kB
	MemFree:          544920 kB
	MemAvailable:    1111296 kB
	Buffers:           16996 kB
	Cached:           588952 kB
	SwapCached:            0 kB
	Active:           426960 kB
	Inactive:         457584 kB
	Active(anon):     281376 kB
	Inactive(anon):      960 kB
	Active(file):     145584 kB
	Inactive(file):   456624 kB
	Unevictable:        2436 kB
	Mlocked:            2436 kB
	HighTotal:       1188988 kB
	HighFree:         255772 kB
	LowTotal:         449700 kB
	LowFree:          289148 kB
	SwapTotal:             0 kB
	SwapFree:              0 kB
	Dirty:                28 kB
	Writeback:             0 kB
	AnonPages:        281048 kB
	Mapped:           316056 kB
	Shmem:              1860 kB
	Slab:              74244 kB
	SReclaimable:      21556 kB
	SUnreclaim:        52688 kB
	KernelStack:        8744 kB
	PageTables:        20236 kB
	NFS_Unstable:          0 kB
	Bounce:                0 kB
	WritebackTmp:          0 kB
	CommitLimit:      819344 kB
	Committed_AS:   15876760 kB
	VmallocTotal:     499712 kB
	VmallocUsed:           0 kB
	VmallocChunk:          0 kB
	CmaTotal:              0 kB
	CmaFree:               0 kB

先把所有的信息都保存到一个list里面

 public List<String> getRamInfo2() {
        StringBuffer sb = new StringBuffer();
        List<String> arr = null;
        try {
            BufferedReader burf = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/meminfo")));
            String strInfo = "";
            arr = new ArrayList<>();
            while((strInfo = burf.readLine()) != null){
                Log.d(TAG, "getRamInfo3: "+strInfo);
                arr.add(strInfo);
            }
            burf.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return arr;
 }

再将里面的数值提取出来,把0-9的数字提取出来

 private String getNumInfo(String strInfo){
        StringBuffer sb = new StringBuffer();
        char[] chInfo = strInfo.toCharArray();
        int size = chInfo.length;
        for(int i = 0; i < size; i++){
            if(chInfo[i] <= '9' && chInfo[i] >= '0'){
                sb.append(chInfo[i]);
            }
        }
        return sb.toString();
 }

这两种方式获取到的数值是一样的,但是对比设置,发现可用内存不一样,有很大的差距

用dumpsys meminfo查看一下

Total PSS by category:
    148,769K: .so mmap
     93,651K: Native
     71,767K: .apk mmap
     55,802K: .dex mmap
     49,099K: Dalvik
     41,268K: Unknown
     29,717K: .art mmap
     29,555K: GL mtrack
     27,527K: Other mmap
     20,344K: .oat mmap
     17,288K: .jar mmap
     13,091K: Dalvik Other
     12,095K: .ttf mmap
      3,264K: Stack
      1,894K: Other dev
      1,712K: EGL mtrack
        436K: Ashmem
          0K: Cursor
          0K: Gfx dev
          0K: Other mtrack

Total RAM: 1,638,688K (status moderate)
 Free RAM:   924,257K (   56,621K cached pss +   462,048K cached kernel +   405,588K free)
 Used RAM:   789,278K (  560,658K used pss +   228,620K kernel)
 Lost RAM:   -74,847K
   Tuning: 128 (large 256), oom   184,320K, restore limit    61,440K (high-end-gfx)

发现将(Free RAM)-(Lost RAM)就是系统设置中显示的了。设置中看一下这些值的获取,在ProcessStatsSummary.java

@Override
public void refreshUi() {
    Context context = getContext();

    MemInfo memInfo = mStatsManager.getMemInfo();

    double usedRam = memInfo.realUsedRam;
    double totalRam = memInfo.realTotalRam;
    double freeRam = memInfo.realFreeRam;
    BytesResult usedResult = Formatter.formatBytes(context.getResources(), (long) usedRam,
            Formatter.FLAG_SHORTER);
    String totalString = Formatter.formatShortFileSize(context, (long) totalRam);
    String freeString = Formatter.formatShortFileSize(context, (long) freeRam);
    CharSequence memString;
    CharSequence[] memStatesStr = getResources().getTextArray(R.array.ram_states);
    int memState = mStatsManager.getMemState();
    if (memState >= 0 && memState < memStatesStr.length - 1) {
        memString = memStatesStr[memState];
    } else {
        memString = memStatesStr[memStatesStr.length - 1];
    }
    mSummaryPref.setAmount(usedResult.value);
    mSummaryPref.setUnits(usedResult.units);
    float usedRatio = (float)(usedRam / (freeRam + usedRam));
    mSummaryPref.setRatios(usedRatio, 0, 1 - usedRatio);

    mPerformance.setSummary(memString);
    mTotalMemory.setSummary(totalString);
    mAverageUsed.setSummary(Utils.formatPercentage((long) usedRam, (long) totalRam));
    mFree.setSummary(freeString);
	Log.d("refreshUi"," refreshUi "+freeString+" totalString "+totalString);
    String durationString = getString(sDurationLabels[mDurationIndex]);
    int numApps = mStatsManager.getEntries().size();
    mAppListPreference.setSummary(getResources().getQuantityString(
            R.plurals.memory_usage_apps_summary, numApps, numApps, durationString));
}

所有的信息都是从MemInfo中取得,接着来看 mStatsManager的初始化

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    Bundle args = getArguments();
    mStatsManager = new ProcStatsData(getActivity(), icicle != null
            || (args != null && args.getBoolean(ARG_TRANSFER_STATS, false)));

    mDurationIndex = icicle != null
            ? icicle.getInt(ARG_DURATION_INDEX)
            : args != null ? args.getInt(ARG_DURATION_INDEX) : 0;
    mStatsManager.setDuration(icicle != null
            ? icicle.getLong(DURATION, sDurations[0]) : sDurations[0]);
}

在ProcStatsData.java中

public void refreshStats(boolean forceLoad) {
    if (mStats == null || forceLoad) {
        load();
    }

    pkgEntries = new ArrayList<>();

    long now = SystemClock.uptimeMillis();

    memTotalTime = DumpUtils.dumpSingleTime(null, null, mStats.mMemFactorDurations,
            mStats.mMemFactor, mStats.mStartTime, now);

    ProcessStats.TotalMemoryUseCollection totalMem = new ProcessStats.TotalMemoryUseCollection(
            ProcessStats.ALL_SCREEN_ADJ, mMemStates);
    mStats.computeTotalMemoryUse(totalMem, now);
	
	for (int i = 0; i < mMemStates.length; i++) {
        Log.d(TAG, "refreshStats: "+mMemStates[i]);
    }
	//这里的totalMem时最关键的
    mMemInfo = new MemInfo(mContext, totalMem, memTotalTime);

    ProcessDataCollection bgTotals = new ProcessDataCollection(
            ProcessStats.ALL_SCREEN_ADJ, mMemStates, mStates);
    ProcessDataCollection runTotals = new ProcessDataCollection(
            ProcessStats.ALL_SCREEN_ADJ, mMemStates, ProcessStats.NON_CACHED_PROC_STATES);

    createPkgMap(getProcs(bgTotals, runTotals), bgTotals, runTotals);
    if (totalMem.sysMemZRamWeight > 0 && !totalMem.hasSwappedOutPss) {
        distributeZRam(totalMem.sysMemZRamWeight);
    }

    ProcStatsPackageEntry osPkg = createOsEntry(bgTotals, runTotals, totalMem,
            mMemInfo.baseCacheRam);
    pkgEntries.add(osPkg);
}

接着看代码,在ProcessStats.java中computeTotalMemoryUse方法

//计算内存使用量
public void computeTotalMemoryUse(TotalMemoryUseCollection data, long now) {
        data.totalTime = 0;
        for (int i=0; i<STATE_COUNT; i++) {
            data.processStateWeight[i] = 0;
            data.processStatePss[i] = 0;
            data.processStateTime[i] = 0;
            data.processStateSamples[i] = 0;
        }
        for (int i=0; i<SYS_MEM_USAGE_COUNT; i++) {
            data.sysMemUsage[i] = 0;
        }
        data.sysMemCachedWeight = 0;
        data.sysMemFreeWeight = 0;
        data.sysMemZRamWeight = 0;
        data.sysMemKernelWeight = 0;
        data.sysMemNativeWeight = 0;
        data.sysMemSamples = 0;
		//这句最为关键
        final long[] totalMemUsage = mSysMemUsage.getTotalMemUsage();
        for (int is=0; is<data.screenStates.length; is++) {
            for (int im=0; im<data.memStates.length; im++) {
                int memBucket = data.screenStates[is] + data.memStates[im];
                int stateBucket = memBucket * STATE_COUNT;
                long memTime = mMemFactorDurations[memBucket];
                if (mMemFactor == memBucket) {
                    memTime += now - mStartTime;
                }
                data.totalTime += memTime;
                final int sysKey = mSysMemUsage.getKey((byte)stateBucket);
                long[] longs = totalMemUsage;
                int idx = 0;
                if (sysKey != SparseMappingTable.INVALID_KEY) {
                    final long[] tmpLongs = mSysMemUsage.getArrayForKey(sysKey);
                    final int tmpIndex = SparseMappingTable.getIndexFromKey(sysKey);
                    if (tmpLongs[tmpIndex+SYS_MEM_USAGE_SAMPLE_COUNT] >= 3) {
                        SysMemUsageTable.mergeSysMemUsage(data.sysMemUsage, 0, longs, idx);
                        longs = tmpLongs;
                        idx = tmpIndex;
                    }
                }
                data.sysMemCachedWeight += longs[idx+SYS_MEM_USAGE_CACHED_AVERAGE]
                        * (double)memTime;
                data.sysMemFreeWeight += longs[idx+SYS_MEM_USAGE_FREE_AVERAGE]
                        * (double)memTime;
                data.sysMemZRamWeight += longs[idx + SYS_MEM_USAGE_ZRAM_AVERAGE]
                        * (double) memTime;
                data.sysMemKernelWeight += longs[idx+SYS_MEM_USAGE_KERNEL_AVERAGE]
                        * (double)memTime;
                data.sysMemNativeWeight += longs[idx+SYS_MEM_USAGE_NATIVE_AVERAGE]
                        * (double)memTime;
                data.sysMemSamples += longs[idx+SYS_MEM_USAGE_SAMPLE_COUNT];
             }
        }
        data.hasSwappedOutPss = mHasSwappedOutPss;
        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
        for (int iproc=0; iproc<procMap.size(); iproc++) {
            SparseArray<ProcessState> uids = procMap.valueAt(iproc);
            for (int iu=0; iu<uids.size(); iu++) {
                final ProcessState proc = uids.valueAt(iu);
                proc.aggregatePss(data, now);
            }
        }
    }

接着看getTotalMemUsage方法

public long[] getTotalMemUsage() {
    long[] total = new long[SYS_MEM_USAGE_COUNT];
    final int N = getKeyCount();
    for (int i=0; i<N; i++) {
        final int key = getKeyAt(i);
		//这个addData就是添加进去的数据
        final long[] addData = getArrayForKey(key);
        final int addOff = SparseMappingTable.getIndexFromKey(key);
        SysMemUsageTable.mergeSysMemUsage(total, 0, addData, addOff);
    }
    return total;
}

接着是getArrayForKey方法

/**
 * Return the raw storage long[] for the given key.
 */
public long[] getArrayForKey(int key) {
    assertConsistency();
	//从mLong中获取数据
    return mParent.mLongs.get(getArrayFromKey(key));
}

mLongs的值时如何add进去的?从Parcel中读取出来的

/**
 * Read the data arrays from the parcel.
 */
public void readFromParcel(Parcel in) {
    mSequence = in.readInt();
    mNextIndex = in.readInt();
	Log.d(TAG, "readFromParcel: ",new RuntimeException().fillInStackTrace());
    mLongs.clear();
    final int N = in.readInt();
    for (int i=0; i<N; i++) {
        final int size = in.readInt();
        final long[] array = new long[size];
        readCompactedLongArray(in, array, size);
		//添加到mLongs中
        mLongs.add(array);
    }
    // Verify that last array's length is consistent with writeToParcel
    if (N > 0 && mLongs.get(N - 1).length != mNextIndex) {
        EventLog.writeEvent(0x534e4554, "73252178", -1, "");
        throw new IllegalStateException("Expected array of length " + mNextIndex + " but was "
                + mLongs.get(N - 1).length);
    }
}

再看看写的方法

/**
 * Write the data arrays to the parcel.
 */
public void writeToParcel(Parcel out) {
    out.writeInt(mSequence);
    out.writeInt(mNextIndex);
    final int N = mLongs.size();
    out.writeInt(N);
    for (int i=0; i<N-1; i++) {
        final long[] array = mLongs.get(i);
        out.writeInt(array.length);
        writeCompactedLongArray(out, array, array.length);
    }
    // save less for the last one. upon re-loading they'll just start a new array.
    final long[] lastLongs = mLongs.get(N-1);
    out.writeInt(mNextIndex);
    writeCompactedLongArray(out, lastLongs, mNextIndex);
}

也就是说系统设置的中显示的已使用内存时通过writeToParcel写到Parcel中,然后再通过readFromParcel从Parcel读取出来的。

2.获取rom大小

主要时利用反射调用,可以获取到总内存大小,已使用的内存

public void getRomInfo() {
        StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
        try {
            Method getVolumes = StorageManager.class.getDeclaredMethod("getVolumes");
            List<Object> getVolumeInfo = (List<Object>) getVolumes.invoke(storageManager);

            long total = 0L, used = 0L;
            int version = Build.VERSION.SDK_INT;
            for (Object obj : getVolumeInfo) {

                Field getType = obj.getClass().getField("type");
                int type = getType.getInt(obj);

                Log.d(TAG, "type: " + type);
                if (type == 1) {//TYPE_PRIVATE

                    long totalSize = 0L;

                    //获取内置内存总大小
                    if (version >= Build.VERSION_CODES.O) {
                       
                        Method getFsUuid = obj.getClass().getDeclaredMethod("getFsUuid");
                        String fsUuid = (String) getFsUuid.invoke(obj);
						反射调用getTotalBytes方法
                        totalSize = getTotalSize(fsUuid);
						//反射调用getFreeBytes方法
                        long free = getFreeBytes(fsUuid);
                        Log.d(TAG, "query:totalSize " + totalSize + " free " + (totalSize - free));

                    } else if (version >= Build.VERSION_CODES.N_MR1) {//7.1.1
                        //5.0 6.0 7.0没有
                        Method getPrimaryStorageSize = StorageManager.class.getMethod("getPrimaryStorageSize");
                        totalSize = (long) getPrimaryStorageSize.invoke(storageManager);
                    }
                    long systemSize = 0L;
                    Method isMountedReadable = obj.getClass().getDeclaredMethod("isMountedReadable");
                    boolean readable = (boolean) isMountedReadable.invoke(obj);
                    if (readable) {
                        Method file = obj.getClass().getDeclaredMethod("getPath");
                        File f = (File) file.invoke(obj);

                        Log.d(TAG, "query: " + f.getAbsolutePath());
                        if (totalSize == 0) {
							//获取data分区的大小
                            totalSize = f.getTotalSpace();
                        }
                        String _msg = "剩余总内存:getTotalSpace " + f.getTotalSpace() + "         " + getUnit(f.getTotalSpace()) + "\n可用内存:" + getUnit(f.getFreeSpace()) + "\n已用内存:" + getUnit(f.getTotalSpace() - f.getFreeSpace());
                        Log.d(TAG, _msg);
                        systemSize = totalSize - f.getTotalSpace();
                        used += totalSize - f.getFreeSpace();
                        total += totalSize;
                    }
                    Log.d(TAG, "totalSize = " + getUnit(totalSize) + " ,used(with system) = " + getUnit(used) + " ,free = " + getUnit(totalSize - used));

                } else if (type == 0) {//TYPE_PUBLIC
                    //外置存储
                    Method isMountedReadable = obj.getClass().getDeclaredMethod("isMountedReadable");
                    boolean readable = (boolean) isMountedReadable.invoke(obj);
                    if (readable) {
                        Method file = obj.getClass().getDeclaredMethod("getPath");
                        File f = (File) file.invoke(obj);
                      /*  used += f.getTotalSpace() - f.getFreeSpace();
                        total += f.getTotalSpace();*/
                        long test1 = f.getTotalSpace() - f.getFreeSpace();
                        long test2 = f.getTotalSpace();
                        Log.d(TAG, "query: TYPE_PUBLIC test1 " + test1 + " total test2 " + test2);
                    }

                } else if (type == 2) {//TYPE_EMULATED

                }
            }
            Log.d(TAG, "总内存 total = " + total + "       " + getUnit(total) + " ,已用 used(with system) = " + used + "      " + getUnit(used) + "\n可用 available = " + (total - used) + "     " + getUnit(total - used));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


/**
 * API 26 android O
 * 获取总共容量大小,包括系统大小
 */
@RequiresApi(api = Build.VERSION_CODES.O)
public long getTotalSize(String fsUuid) {
    try {
        UUID id;
        if (fsUuid == null) {
            id = StorageManager.UUID_DEFAULT;
        } else {
            id = UUID.fromString(fsUuid);
        }
        StorageStatsManager stats = getSystemService(StorageStatsManager.class);
        return stats.getTotalBytes(id);
    } catch (NoSuchFieldError | NoClassDefFoundError | NullPointerException | IOException e) {
        e.printStackTrace();
        return -1;
    }
}

@RequiresApi(api = Build.VERSION_CODES.O)
public long getFreeBytes(String fsUuid) {
    try {
        UUID id;
        if (fsUuid == null) {
            id = StorageManager.UUID_DEFAULT;
        } else {
            id = UUID.fromString(fsUuid);
        }
        StorageStatsManager stats = getSystemService(StorageStatsManager.class);
        return stats.getFreeBytes(id);
    } catch (NoSuchFieldError | NoClassDefFoundError | NullPointerException | IOException e) {
        e.printStackTrace();
        return -1;
    }
}

  /**
 * 单位转换
 */
private String getUnit(float size) {
    int index = 0;
    while (size > 1000 && index < 4) {
        size = size / 1000;
        index++;
    }
    return String.format(Locale.getDefault(), " %.2f %s", size, units[index]);
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐