android 格式化sd卡后,显示容量为0

问题现象:

问题原因:  sd卡格式化后,对应手机中的挂载位置发生了变更,而对应的显示数据未进行更新。所以再去原来的位置获取  容量数据时就会获取不到。

来看下代码吧。

此界面的xml文件为:packages/apps/Settings/res/xml/storage_dashboard_fragment.xml

管理类为:packages/apps/Settings/src/com/android/settings/deviceinfo/StorageDashboardFragment.java

显示   已使用容量   的控件管理类为:frameworks/base/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java

   public void setUsageSummary(CharSequence usageSummary) {
        Log.e("xz", "setUsageSummary: usageSummary = " + usageSummary, new Throwable());
        if (TextUtils.equals(mUsageSummary, usageSummary)) {
            return;
        }
        mUsageSummary = usageSummary;
        notifyChanged();
    }

已使用容量取决于  mUsageSummary   的值。

为他赋值的地方在packages/apps/Settings/src/com/android/settings/deviceinfo/storage/StorageUsageProgressBarPreferenceController.java 中。

@Override
    public void updateState(Preference preference) {
        Log.e("xz", " updateState: ", new Throwable());
        if (!mIsUpdateStateFromSelectedStorageEntry) {
            // Returns here to avoid jank by unnecessary UI update.
            return;
        }
        mIsUpdateStateFromSelectedStorageEntry = false;
        mUsageProgressBarPreference.setUsageSummary(StorageUtils.getStorageSummary(
                mContext, R.string.storage_usage_summary, mUsedBytes));
        mUsageProgressBarPreference.setTotalSummary(StorageUtils.getStorageSummary(
                mContext, R.string.storage_total_summary, mTotalBytes));
        mUsageProgressBarPreference.setPercent(mUsedBytes, mTotalBytes);
    }

mUsageProgressBarPreference.setUsageSummary(StorageUtils.getStorageSummary(
mContext, R.string.storage_usage_summary, mUsedBytes));

可以看到与mUsedBytes  有关。看看哪里为mUsedBytes赋值

StorageUsageProgressBarPreferenceController.java

private void getStorageStatsAndUpdateUi() {
        Log.d(TAG, "xz getStorageStatsAndUpdateUi: ");
        // Use cached data for both total size and used size.
        if (mStorageEntry != null && mStorageEntry.isMounted() && mStorageEntry.isPrivate()) {
            StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize();
            mTotalBytes = cachedData.totalSize;
            mUsedBytes = cachedData.totalUsedSize;
            mIsUpdateStateFromSelectedStorageEntry = true;
            updateState(mUsageProgressBarPreference);
        }
        Log.d(TAG, "xz getStorageStatsAndUpdateUi  1 : mUsedBytes = " + mUsedBytes + " mTotalBytes = " + mTotalBytes);
        // Get the latest data from StorageStatsManager.
        ThreadUtils.postOnBackgroundThread(() -> {
            try {
                if (mStorageEntry == null || !mStorageEntry.isMounted()) {
                    throw new IOException();
                }
                Log.d(TAG, "xz getStorageStatsAndUpdateUi: isPrivate = " + mStorageEntry.isPrivate() + " isMounted = " + mStorageEntry.isMounted());
                if (mStorageEntry.isPrivate()) {
                    // StorageStatsManager can only query private storages.
                    mTotalBytes = mStorageStatsManager.getTotalBytes(mStorageEntry.getFsUuid());
                    mUsedBytes = mTotalBytes
                            - mStorageStatsManager.getFreeBytes(mStorageEntry.getFsUuid());
                } else {
                    Log.d(TAG, "xz getStorageStatsAndUpdateUi:  mStorageEntry = " + mStorageEntry + " getPath = " + mStorageEntry.getPath());
                    final File rootFile = mStorageEntry.getPath();
                    if (rootFile == null) {
                        Log.d(TAG, "xz Mounted public storage has null root path: " + mStorageEntry);
                        throw new IOException();
                    }
                    mTotalBytes = rootFile.getTotalSpace();
                    mUsedBytes = mTotalBytes - rootFile.getFreeSpace();
                }
                Log.d(TAG, "xz getStorageStatsAndUpdateUi  2 : mUsedBytes = " + mUsedBytes + " mTotalBytes = " + mTotalBytes);
            } catch (IOException e) {
                Log.d(TAG, "xz getStorageStatsAndUpdateUi: e" + e);
                // The storage device isn't present.
                mTotalBytes = 0;
                mUsedBytes = 0;
            }

            if (mUsageProgressBarPreference == null) {
                return;
            }
            mIsUpdateStateFromSelectedStorageEntry = true;
            ThreadUtils.postOnMainThread(() -> updateState(mUsageProgressBarPreference));
        });
    }

可以注意这句 : 

mTotalBytes = rootFile.getTotalSpace();
mUsedBytes = mTotalBytes - rootFile.getFreeSpace();

mStorageEntry.isPrivate()  的判断  是为了区分手机内部存储  和  外部sd 卡

sd卡的  mUsedBytes 就是这里赋值的。

可以看到 数据取决于mStorageEntry.getPath()。

 /** Set StorageEntry to display. */
    public void setSelectedStorageEntry(StorageEntry storageEntry) {
        Log.d(TAG, "xz setSelectedStorageEntry: ");
        mStorageEntry = storageEntry;
        getStorageStatsAndUpdateUi();
    }

而mStorageEntry  是在这个方法中赋值的。再去看看哪里调用的这个方法。

StorageDashboardFragment.java

private void refreshUi() {
        Log.d(TAG, "xz refreshUi: mStorageEntries = ");
        mStorageSelectionController.setStorageEntries(mStorageEntries);
        mStorageSelectionController.setSelectedStorageEntry(mSelectedStorageEntry);
        mStorageUsageProgressBarController.setSelectedStorageEntry(mSelectedStorageEntry);

        mOptionMenuController.setSelectedStorageEntry(mSelectedStorageEntry);
        getActivity().invalidateOptionsMenu();

        // To prevent flicker, hides non-current users preference.
        // onReceivedSizes will set it visible for private storage.
        setNonCurrentUsersVisible(false);

        if (!mSelectedStorageEntry.isMounted()) {
            // Set null volume to hide category stats.
            mPreferenceController.setVolume(null);
            return;
        }

        if (mStorageCacheHelper.hasCachedSizeInfo() && mSelectedStorageEntry.isPrivate()) {
            StorageCacheHelper.StorageCache cachedData = mStorageCacheHelper.retrieveCachedSize();
            mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
            mPreferenceController.setUsedSize(cachedData.totalUsedSize);
            mPreferenceController.setTotalSize(cachedData.totalSize);
        }

        if (mSelectedStorageEntry.isPrivate()) {
            mStorageInfo = null;
            mAppsResult = null;
            // Hide the loading spinner if there is cached data.
            if (mStorageCacheHelper.hasCachedSizeInfo()) {
                //TODO(b/220259287): apply cache mechanism to non-current user
                mPreferenceController.onLoadFinished(mAppsResult, mUserId);
            } else {
                maybeSetLoading(isQuotaSupported());
                // To prevent flicker, sets null volume to hide category preferences.
                // onReceivedSizes will setVolume with the volume of selected storage.
                mPreferenceController.setVolume(null);
            }
            // Stats data is only available on private volumes.
            getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
            getLoaderManager()
                 .restartLoader(VOLUME_SIZE_JOB_ID, Bundle.EMPTY, new VolumeSizeCallbacks());
            getLoaderManager().restartLoader(ICON_JOB_ID, Bundle.EMPTY, new IconLoaderCallbacks());
        } else {
            mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
        }
    }

mStorageSelectionController.setSelectedStorageEntry(mSelectedStorageEntry);

这个refresUi   就是界面创建  和  选择查看存储对象时会调用的刷新ui的方法。

其中就会往StorageUsageProgressBarPreferenceController 中赋值  mSelectedStorageEntry

每次在sd卡格式化时 主界面会 onPause  。 格式化完后会  onResume 。

@Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
        if (mIsLoadedFromCache) {
            mIsLoadedFromCache = false;
        } else {
            mStorageEntries.clear();
            mStorageEntries.addAll(
                    StorageUtils.getAllStorageEntries(getContext(), mStorageManager));

            refreshUi();
        }
        Log.d(TAG, "onResume: mStorageEntries = " + mStorageEntries.toString());
        mStorageManager.registerListener(mStorageEventListener);
    }

onResume 时会重新从StorageManager  系统服务中  获取  手机中挂载的存储空间。

mStorageEntries  就是 手机中存储的  集合  ,此数据是正确的。

这里会调用  refreshUi()   。  然后去set   mSelectedStorageEntry。

mStorageSelectionController.setSelectedStorageEntry(mSelectedStorageEntry);

但是onResume  中并没有去更新mSelectedStorageEntry。所以set的mSelectedStorageEntry 的数据是错误的。还是原来那个旧的挂载位置。导致获取的容量数据也是错误的。

所以解决方案就是在onResume 中  去更新一下mSelectedStorageEntry  的值。

 @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
        if (mIsLoadedFromCache) {
            mIsLoadedFromCache = false;
        } else {
            mStorageEntries.clear();
            mStorageEntries.addAll(
                    StorageUtils.getAllStorageEntries(getContext(), mStorageManager));
            // add by xz start
            if (mSelectedStorageEntry != null && mSelectedStorageEntry.isPublic()){
                for (StorageEntry storageEntry : mStorageEntries) {
                    if (storageEntry.isPublic()){
                        mSelectedStorageEntry = storageEntry;
                    }
                }
            }
            // add by xz end
            refreshUi();
        }
        Log.d(TAG, "onResume: mStorageEntries = " + mStorageEntries.toString());
        mStorageManager.registerListener(mStorageEventListener);
    }

谢谢大家的浏览。有空的就点个赞吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值