Как я могу проверить, приложение может быть перемещено на SD или нет - PullRequest
0 голосов
/ 26 мая 2011

Я хочу знать, как проверить, может ли приложение перемещаться на SD или нет с помощью кода. Я знаю, как получить список установленных приложений и есть ли он на SD-карте или нет.
Если флаги ApplicationInfo содержат ApplicationInfo.FLAG_EXTERNAL_STORAGE, то они находятся на SD-карте, но как я могу проверить, может ли приложение перемещаться на SD или нет.

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

Мое первое предположение - слишком заглянуть в исходный код Android для активности 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 является внутренним классом.

0 голосов
/ 22 января 2019

Вы можете получить фильтр всех приложений по пользователю и попробовать, если 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;
    }
}
...