How to use StorageStatsManager.queryStatsForPackage on Android O?

社会主义新天地 提交于 2019-12-01 11:33:51

OK, I've found out how to use the new API. I've prepared a small sample of this, fetching some information about the volume storage and of a specific app (this time of the Play Store, but you can change it if needed) :

public class MainActivity extends AppCompatActivity {

    public static final String PACKAGE_NAME = "com.android.vending";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (!hasUsageStatsPermission(this))
            startActivityForResult(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY), 1);
        else {
            final Context context = this;
            AsyncTask.execute(new Runnable() {
                @TargetApi(VERSION_CODES.O)
                @Override
                public void run() {
                    @SuppressLint("WrongConstant") final StorageStatsManager storageStatsManager = (StorageStatsManager) getSystemService(Context.STORAGE_STATS_SERVICE);
                    final StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
                    final List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
                    final UserHandle user = Process.myUserHandle();
                    for (StorageVolume storageVolume : storageVolumes) {
                        final String uuidStr = storageVolume.getUuid();
                        final UUID uuid = uuidStr == null ? StorageManager.UUID_DEFAULT : UUID.fromString(uuidStr);
                        try {
                            Log.d("AppLog", "storage:" + uuid + " : " + storageVolume.getDescription(context) + " : " + storageVolume.getState());
                            Log.d("AppLog", "getFreeBytes:" + Formatter.formatShortFileSize(context, storageStatsManager.getFreeBytes(uuid)));
                            Log.d("AppLog", "getTotalBytes:" + Formatter.formatShortFileSize(context, storageStatsManager.getTotalBytes(uuid)));
                            Log.d("AppLog", "storage stats for app of package name:" + PACKAGE_NAME + " : ");

                            final StorageStats storageStats = storageStatsManager.queryStatsForPackage(uuid, PACKAGE_NAME, user);
                            Log.d("AppLog", "getAppBytes:" + Formatter.formatShortFileSize(context, storageStats.getAppBytes()) +
                                    " getCacheBytes:" + Formatter.formatShortFileSize(context, storageStats.getCacheBytes()) +
                                    " getDataBytes:" + Formatter.formatShortFileSize(context, storageStats.getDataBytes()));
                        } catch (NameNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });

        }
    }

    @TargetApi(VERSION_CODES.M)
    public static boolean hasUsageStatsPermission(Context context) {
        //http://stackoverflow.com/a/42390614/878126
        if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)
            return false;
        AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        final int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
        boolean granted = false;
        if (mode == AppOpsManager.MODE_DEFAULT)
            granted = (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED);
        else
            granted = (mode == AppOpsManager.MODE_ALLOWED);
        return granted;
    }
}

manifest file should have this:

<uses-permission
    android:name="android.permission.PACKAGE_USAGE_STATS"
    tools:ignore="ProtectedPermissions"/>

Pass null as the VolumeUuid, to get values for the default internal storage, or get specific volumes via the StorageManager system service.

You can get your own UserHandle via Process.myUserHandle(). Other users of the system occur when you give someone a guest login on your device, or when there is an Android for Work profile installed on the device. I don't think there is a simple way to enumerate all the users that have access to the device.

An alternative approach for getting UUID.

To get UUIDs, you can also use StorageManager.getUuidForPath(File path) function. As to the path, use Context.getFilesDir() and Context.getExternalFilesDirs() to get all possibles directories that an app data will be saved to.

Please note that different path may return the same UUID, so you have to use a hash set to collect unique UUIDs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!