如何检查应用程序是否可移动到 SD

发布于 2024-11-10 02:02:59 字数 163 浏览 2 评论 0原文

我想知道如何通过代码检查应用程序是否可以移动到SD。我知道如何获取已安装的应用程序列表以及它是否在 SD 卡上。
如果 ApplicationInfo 标志包含 ApplicationInfo.FLAG_EXTERNAL_STORAGE 那么它位于 SD 卡上,但如何检查应用程序是否可移动到 SD 卡。

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 whether the app is movable to sd or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我是男神闪亮亮 2024-11-17 02:02:59

我的第一个猜测是查看 InstalledAppDetails 活动。此活动显示“移至手机”和“移至 SD 卡”按钮。它有一个有趣的函数,名为 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);
    }
}

尽管并非此函数中使用的所有类都可以通过公共 API 获得。具体来说,PackageHelper是内部类。

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.

浪菊怪哟 2024-11-17 02:02:59

您可以按用户获取所有应用程序过滤器,并尝试 packetInfo 设置过滤器“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;
    }
}

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文