【问题标题】:How can I check the app is movable to sd or not如何检查应用程序是否可以移动到 sd
【发布时间】:2011-05-26 16:06:08
【问题描述】:

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

【问题讨论】:

    标签: android sd-card movable


    【解决方案1】:

    我的第一个猜测是查看 InstalledAppDetails 活动的 Android 源代码。这是显示“移动到手机”和“移动到 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 是内部类。

    【讨论】:

    • pkgInfo.installLocation 无法解析,即我无法访问 installLocation 值。你能帮帮我吗?
    • 你可以使用反射。该成员在那里,只是不公开可见
    • 你能解释一下我如何使用反射吗?其实我对反射一无所知。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      • 2015-06-06
      • 1970-01-01
      • 2023-03-23
      • 2016-04-15
      相关资源
      最近更新 更多