开发者

How can I check the app is movable to sd or not

开发者 https://www.devze.com 2023-03-09 00:50 出处:网络
I want to know how to check whether the app is movable to sd or not through code. I know how to get the installed applications list and is it on sd card or not.

I want to know how to check whether the app is movable to sd or not through code. I know how to get the installed applications list and is it on sd card or not.

If ApplicationInfo flags contains ApplicationInfo.FLAG_EXTERNAL_STORAGE then it is on sd card but how can I check wh开发者_C百科ether the app is movable to sd or not.


My first guess is too look into Android Source code for InstalledAppDetails activity. This is activity which shows "Move to phone" and "Move to SD card" buttons. It has interesting function called initMoveButton:

private void initMoveButton() {
    String pkgName = mAppInfo.packageName;
    boolean dataOnly = false;
    ApplicationInfo info1 = null;
    PackageInfo pkgInfo = null;

    try {
        info1 = mPm.getApplicationInfo(pkgName, 0);
        pkgInfo = mPm.getPackageInfo(mAppInfo.packageName,
                PackageManager.GET_UNINSTALLED_PACKAGES);
    } catch (NameNotFoundException e) {
    }
    dataOnly = (info1 == null) && (mAppInfo != null);
    boolean moveDisable = true;
    if (dataOnly) {
        mMoveAppButton.setText(R.string.move_app);
    } else if ((mAppInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
        mMoveAppButton.setText(R.string.move_app_to_internal);
        // Always let apps move to internal storage from sdcard.
        moveDisable = false;
    } else {
        mMoveAppButton.setText(R.string.move_app_to_sdcard);
        if ((mAppInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0 &&
                (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 &&
                pkgInfo != null) {
            if (pkgInfo.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL ||
                    pkgInfo.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
                moveDisable = false;
            } else if (pkgInfo.installLocation == PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
                IPackageManager ipm  = IPackageManager.Stub.asInterface(
                        ServiceManager.getService("package"));
                int loc;
                try {
                    loc = ipm.getInstallLocation();
                } catch (RemoteException e) {
                    Log.e(TAG, "Is Pakage Manager running?");
                    return;
                }
                if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
                    // For apps with no preference and the default value set
                    // to install on sdcard.
                    moveDisable = false;
                }
            }
        }
    }
    if (moveDisable) {
        mMoveAppButton.setEnabled(false);
    } else {
        mMoveAppButton.setOnClickListener(this);
        mMoveAppButton.setEnabled(true);
    }
}

Though not all classes used in this functions are available through public API. Specifically PackageHelper is internal class.


You can get all aplications filter by user and try if packetInfo set filter 'INSTALL_LOCATION_INTERNAL_ONLY'

    List<ApplicationInfo> packagesAll = pm.getInstalledApplications(PackageManager.GET_META_DATA);

    List<ApplicationInfo> packagesByUser = Stream.of(packagesAll)
        .filter((p -> (p.flags & ApplicationInfo.FLAG_SYSTEM) == 0))
        .filter((this::tryMoveSDPackage))
        .map(ApplicationInfo::new)
        .collect(Collectors.toList());

private boolean tryMoveSDPackage(ApplicationInfo applicationInfo) {
    try {
        PackageInfo packageInfo = getPackageManager().getPackageInfo(applicationInfo.packageName, 0);
        if (packageInfo.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
            //Log.i(TAG, "INSTALL_LOCATION_AUTO");
            return true;
        } else if (packageInfo.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
            //Log.d(TAG, "INSTALL_LOCATION_PREFER_EXTERNAL");
            return true;
        } else {
            //Log.w(TAG, "INSTALL_LOCATION_INTERNAL_ONLY");
            return false;
        }

    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消