Remove root installer
This commit is contained in:
parent
51b2aeda1a
commit
a7aa554f66
@ -25,8 +25,6 @@
|
|||||||
<string name="notify_on">Notify when updates are available</string>
|
<string name="notify_on">Notify when updates are available</string>
|
||||||
<string name="update_history">Update history</string>
|
<string name="update_history">Update history</string>
|
||||||
<string name="update_history_summ">Days to consider apps new or recent: %s</string>
|
<string name="update_history_summ">Days to consider apps new or recent: %s</string>
|
||||||
<string name="root_installer">Install using root access</string>
|
|
||||||
<string name="root_installer_on">Request root access to install, update, and remove packages</string>
|
|
||||||
<string name="system_installer">Install using system-permissions</string>
|
<string name="system_installer">Install using system-permissions</string>
|
||||||
<string name="system_installer_on">Use system permissions to install, update, and remove packages</string>
|
<string name="system_installer_on">Use system permissions to install, update, and remove packages</string>
|
||||||
<string name="uninstall_system">Uninstall F-Droid</string>
|
<string name="uninstall_system">Uninstall F-Droid</string>
|
||||||
|
@ -84,10 +84,6 @@
|
|||||||
<CheckBoxPreference android:title="@string/expert"
|
<CheckBoxPreference android:title="@string/expert"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="expert" />
|
android:key="expert" />
|
||||||
<CheckBoxPreference android:title="@string/root_installer"
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="rootInstaller"
|
|
||||||
android:dependency="expert" />
|
|
||||||
<CheckBoxPreference android:title="@string/system_installer"
|
<CheckBoxPreference android:title="@string/system_installer"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="systemInstaller"
|
android:key="systemInstaller"
|
||||||
|
@ -50,7 +50,6 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
public static final String PREF_CACHE_APK = "cacheDownloaded";
|
public static final String PREF_CACHE_APK = "cacheDownloaded";
|
||||||
public static final String PREF_EXPERT = "expert";
|
public static final String PREF_EXPERT = "expert";
|
||||||
public static final String PREF_UPD_LAST = "lastUpdateCheck";
|
public static final String PREF_UPD_LAST = "lastUpdateCheck";
|
||||||
public static final String PREF_ROOT_INSTALLER = "rootInstaller";
|
|
||||||
public static final String PREF_SYSTEM_INSTALLER = "systemInstaller";
|
public static final String PREF_SYSTEM_INSTALLER = "systemInstaller";
|
||||||
public static final String PREF_UNINSTALL_SYSTEM_APP = "uninstallSystemApp";
|
public static final String PREF_UNINSTALL_SYSTEM_APP = "uninstallSystemApp";
|
||||||
public static final String PREF_LOCAL_REPO_BONJOUR = "localRepoBonjour";
|
public static final String PREF_LOCAL_REPO_BONJOUR = "localRepoBonjour";
|
||||||
@ -67,7 +66,6 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
private static final boolean DEFAULT_COMPACT_LAYOUT = false;
|
private static final boolean DEFAULT_COMPACT_LAYOUT = false;
|
||||||
private static final boolean DEFAULT_ROOTED = true;
|
private static final boolean DEFAULT_ROOTED = true;
|
||||||
private static final int DEFAULT_UPD_HISTORY = 14;
|
private static final int DEFAULT_UPD_HISTORY = 14;
|
||||||
private static final boolean DEFAULT_ROOT_INSTALLER = false;
|
|
||||||
private static final boolean DEFAULT_SYSTEM_INSTALLER = false;
|
private static final boolean DEFAULT_SYSTEM_INSTALLER = false;
|
||||||
private static final boolean DEFAULT_LOCAL_REPO_BONJOUR = true;
|
private static final boolean DEFAULT_LOCAL_REPO_BONJOUR = true;
|
||||||
private static final boolean DEFAULT_CACHE_APK = false;
|
private static final boolean DEFAULT_CACHE_APK = false;
|
||||||
@ -107,10 +105,6 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
|||||||
initialized.put(key, false);
|
initialized.put(key, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRootInstallerEnabled() {
|
|
||||||
return preferences.getBoolean(PREF_ROOT_INSTALLER, DEFAULT_ROOT_INSTALLER);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSystemInstallerEnabled() {
|
public boolean isSystemInstallerEnabled() {
|
||||||
return preferences.getBoolean(PREF_SYSTEM_INSTALLER, DEFAULT_SYSTEM_INSTALLER);
|
return preferences.getBoolean(PREF_SYSTEM_INSTALLER, DEFAULT_SYSTEM_INSTALLER);
|
||||||
}
|
}
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.installer;
|
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.view.ContextThemeWrapper;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
|
||||||
import org.fdroid.fdroid.R;
|
|
||||||
|
|
||||||
import eu.chainfire.libsuperuser.Shell;
|
|
||||||
|
|
||||||
public class CheckRootAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
|
||||||
ProgressDialog mDialog;
|
|
||||||
final Context mContext;
|
|
||||||
final CheckRootCallback mCallback;
|
|
||||||
|
|
||||||
public interface CheckRootCallback {
|
|
||||||
void onRootCheck(boolean rootGranted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CheckRootAsyncTask(Context context, CheckRootCallback callback) {
|
|
||||||
super();
|
|
||||||
this.mContext = context;
|
|
||||||
this.mCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
super.onPreExecute();
|
|
||||||
|
|
||||||
// if the dialog is displayed from the application class, design is missing
|
|
||||||
// hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
|
|
||||||
ContextThemeWrapper theme = new ContextThemeWrapper(mContext, FDroidApp.getCurThemeResId());
|
|
||||||
|
|
||||||
mDialog = new ProgressDialog(theme);
|
|
||||||
mDialog.setMessage(mContext.getString(R.string.requesting_root_access_body));
|
|
||||||
mDialog.setIndeterminate(true);
|
|
||||||
mDialog.setCancelable(false);
|
|
||||||
mDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
return Shell.SU.available();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
super.onPostExecute(result);
|
|
||||||
|
|
||||||
mDialog.dismiss();
|
|
||||||
|
|
||||||
mCallback.onRootCheck(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -95,28 +95,10 @@ abstract public class Installer {
|
|||||||
/**
|
/**
|
||||||
* Creates a new Installer for installing/deleting processes starting from
|
* Creates a new Installer for installing/deleting processes starting from
|
||||||
* an Activity
|
* an Activity
|
||||||
*
|
|
||||||
* @param activity
|
|
||||||
* @param pm
|
|
||||||
* @param callback
|
|
||||||
* @return
|
|
||||||
* @throws AndroidNotCompatibleException
|
|
||||||
*/
|
*/
|
||||||
public static Installer getActivityInstaller(Activity activity, PackageManager pm,
|
public static Installer getActivityInstaller(Activity activity, PackageManager pm,
|
||||||
InstallerCallback callback) {
|
InstallerCallback callback) {
|
||||||
|
|
||||||
// if root installer has been activated in preferences -> RootInstaller
|
|
||||||
boolean isRootInstallerEnabled = Preferences.get().isRootInstallerEnabled();
|
|
||||||
if (isRootInstallerEnabled) {
|
|
||||||
Log.d(TAG, "root installer preference enabled -> RootInstaller");
|
|
||||||
|
|
||||||
try {
|
|
||||||
return new RootInstaller(activity, pm, callback);
|
|
||||||
} catch (AndroidNotCompatibleException e) {
|
|
||||||
Log.e(TAG, "Android not compatible with RootInstaller!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// system permissions and pref enabled -> SystemInstaller
|
// system permissions and pref enabled -> SystemInstaller
|
||||||
boolean isSystemInstallerEnabled = Preferences.get().isSystemInstallerEnabled();
|
boolean isSystemInstallerEnabled = Preferences.get().isSystemInstallerEnabled();
|
||||||
if (isSystemInstallerEnabled) {
|
if (isSystemInstallerEnabled) {
|
||||||
@ -161,16 +143,6 @@ abstract public class Installer {
|
|||||||
public static Installer getUnattendedInstaller(Context context, PackageManager pm,
|
public static Installer getUnattendedInstaller(Context context, PackageManager pm,
|
||||||
InstallerCallback callback) throws AndroidNotCompatibleException {
|
InstallerCallback callback) throws AndroidNotCompatibleException {
|
||||||
|
|
||||||
// if root installer has been activated in preferences -> RootInstaller
|
|
||||||
boolean useRootInstaller = Preferences.get().isRootInstallerEnabled();
|
|
||||||
if (useRootInstaller) {
|
|
||||||
try {
|
|
||||||
return new RootInstaller(context, pm, callback);
|
|
||||||
} catch (AndroidNotCompatibleException e) {
|
|
||||||
Log.e(TAG, "Android not compatible with RootInstaller!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasSystemPermissions(context, pm)) {
|
if (hasSystemPermissions(context, pm)) {
|
||||||
// we have system permissions!
|
// we have system permissions!
|
||||||
return new SystemInstaller(context, pm, callback);
|
return new SystemInstaller(context, pm, callback);
|
||||||
|
@ -1,266 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 3
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.fdroid.fdroid.installer;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import eu.chainfire.libsuperuser.Shell;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Installer using a root shell and "pm install", "pm uninstall" commands
|
|
||||||
*/
|
|
||||||
public class RootInstaller extends Installer {
|
|
||||||
|
|
||||||
private static final String TAG = "RootInstaller";
|
|
||||||
|
|
||||||
Shell.Interactive rootSession;
|
|
||||||
|
|
||||||
public RootInstaller(Context context, PackageManager pm, InstallerCallback callback)
|
|
||||||
throws AndroidNotCompatibleException {
|
|
||||||
super(context, pm, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Shell.Builder createShellBuilder() {
|
|
||||||
return new Shell.Builder()
|
|
||||||
.useSU()
|
|
||||||
.setWantSTDERR(true)
|
|
||||||
.setWatchdogTimeout(30)
|
|
||||||
.setMinimalLogging(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void installPackageInternal(final File apkFile) throws AndroidNotCompatibleException {
|
|
||||||
rootSession = createShellBuilder().open(new Shell.OnCommandResultListener() {
|
|
||||||
|
|
||||||
// Callback to report whether the shell was successfully
|
|
||||||
// started up
|
|
||||||
@Override
|
|
||||||
public void onCommandResult(int commandCode, int exitCode, List<String> output) {
|
|
||||||
if (exitCode != Shell.OnCommandResultListener.SHELL_RUNNING) {
|
|
||||||
// NOTE: Additional exit codes:
|
|
||||||
// Shell.OnCommandResultListener.SHELL_WRONG_UID
|
|
||||||
// Shell.OnCommandResultListener.SHELL_EXEC_FAILED
|
|
||||||
|
|
||||||
Log.e(TAG, "Error opening root shell with exitCode " + exitCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
} else {
|
|
||||||
addInstallCommand(apkFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void installPackageInternal(final List<File> apkFiles)
|
|
||||||
throws AndroidNotCompatibleException {
|
|
||||||
rootSession = createShellBuilder().open(new Shell.OnCommandResultListener() {
|
|
||||||
|
|
||||||
// Callback to report whether the shell was successfully
|
|
||||||
// started up
|
|
||||||
@Override
|
|
||||||
public void onCommandResult(int commandCode, int exitCode, List<String> output) {
|
|
||||||
if (exitCode != Shell.OnCommandResultListener.SHELL_RUNNING) {
|
|
||||||
// NOTE: Additional exit codes:
|
|
||||||
// Shell.OnCommandResultListener.SHELL_WRONG_UID
|
|
||||||
// Shell.OnCommandResultListener.SHELL_EXEC_FAILED
|
|
||||||
|
|
||||||
Log.e(TAG, "Error opening root shell with exitCode " + exitCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
} else {
|
|
||||||
addInstallCommand(apkFiles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deletePackageInternal(final String packageName)
|
|
||||||
throws AndroidNotCompatibleException {
|
|
||||||
rootSession = createShellBuilder().open(new Shell.OnCommandResultListener() {
|
|
||||||
|
|
||||||
// Callback to report whether the shell was successfully
|
|
||||||
// started up
|
|
||||||
@Override
|
|
||||||
public void onCommandResult(int commandCode, int exitCode, List<String> output) {
|
|
||||||
if (exitCode != Shell.OnCommandResultListener.SHELL_RUNNING) {
|
|
||||||
// NOTE: Additional exit codes:
|
|
||||||
// Shell.OnCommandResultListener.SHELL_WRONG_UID
|
|
||||||
// Shell.OnCommandResultListener.SHELL_EXEC_FAILED
|
|
||||||
|
|
||||||
Log.e(TAG, "Error opening root shell with exitCode " + exitCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
} else {
|
|
||||||
addDeleteCommand(packageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handleOnActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
// no need to handle onActivityResult
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addInstallCommand(File apkFile) {
|
|
||||||
// Like package names, apk files should also only contain letters, numbers, dots, or underscore,
|
|
||||||
// e.g., org.fdroid.fdroid_9.apk
|
|
||||||
if (!isValidPackageName(apkFile.getName())) {
|
|
||||||
Log.e(TAG, "File name is not valid (contains characters other than letters, numbers, dots, or underscore): "
|
|
||||||
+ apkFile.getName());
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rootSession.addCommand("pm install -dr \"" + apkFile.getAbsolutePath() + "\"", 0,
|
|
||||||
new Shell.OnCommandResultListener() {
|
|
||||||
public void onCommandResult(int commandCode, int exitCode, List<String> output) {
|
|
||||||
// close su shell
|
|
||||||
rootSession.close();
|
|
||||||
|
|
||||||
if (exitCode < 0) {
|
|
||||||
Log.e(TAG, "Install failed with exit code " + exitCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
} else {
|
|
||||||
mCallback.onSuccess(InstallerCallback.OPERATION_INSTALL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addInstallCommand(List<File> apkFiles) {
|
|
||||||
List<String> commands = new ArrayList<>();
|
|
||||||
String pm = "pm install -dr ";
|
|
||||||
for (File apkFile : apkFiles) {
|
|
||||||
// see addInstallCommand()
|
|
||||||
if (!isValidPackageName(apkFile.getName())) {
|
|
||||||
Log.e(TAG, "File name is not valid (contains characters other than letters, numbers, dots, or underscore): "
|
|
||||||
+ apkFile.getName());
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
commands.add(pm + "\"" + apkFile.getAbsolutePath() + "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
rootSession.addCommand(commands, 0,
|
|
||||||
new Shell.OnCommandResultListener() {
|
|
||||||
public void onCommandResult(int commandCode, int exitCode,
|
|
||||||
List<String> output) {
|
|
||||||
// close su shell
|
|
||||||
rootSession.close();
|
|
||||||
|
|
||||||
if (exitCode < 0) {
|
|
||||||
Log.e(TAG, "Install failed with exit code " + exitCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
} else {
|
|
||||||
mCallback.onSuccess(InstallerCallback.OPERATION_INSTALL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addDeleteCommand(String packageName) {
|
|
||||||
if (!isValidPackageName(packageName)) {
|
|
||||||
Log.e(TAG, "Package name is not valid (contains characters other than letters, numbers, dots, or underscore): "
|
|
||||||
+ packageName);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rootSession.addCommand("pm uninstall \"" + packageName + "\"", 0,
|
|
||||||
new Shell.OnCommandResultListener() {
|
|
||||||
public void onCommandResult(int commandCode, int exitCode, List<String> output) {
|
|
||||||
// close su shell
|
|
||||||
rootSession.close();
|
|
||||||
|
|
||||||
if (exitCode < 0) {
|
|
||||||
Log.e(TAG, "Delete failed with exit code " + exitCode);
|
|
||||||
mCallback.onError(InstallerCallback.OPERATION_DELETE,
|
|
||||||
InstallerCallback.ERROR_CODE_OTHER);
|
|
||||||
} else {
|
|
||||||
mCallback.onSuccess(InstallerCallback.OPERATION_DELETE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportsUnattendedOperations() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Pattern PACKAGE_NAME_BLACKLIST = Pattern.compile("[^a-zA-Z0-9\\.\\_]");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Package names should only contain letters, numbers, dots, and underscores!
|
|
||||||
* Prevent injection attacks with app names like ";touch $'\057data\057injected'"
|
|
||||||
*
|
|
||||||
* @param packageName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isValidPackageName(String packageName) {
|
|
||||||
Matcher matcher = PACKAGE_NAME_BLACKLIST.matcher(packageName);
|
|
||||||
return !matcher.find();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] [--algo
|
|
||||||
* <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] [--originating-uri
|
|
||||||
* <URI>] [--referrer <URI>] PATH
|
|
||||||
* <p/>
|
|
||||||
* pm install: installs a package to the system.
|
|
||||||
* <p/>
|
|
||||||
* Options:<br/>
|
|
||||||
* -l: install the package with FORWARD_LOCK.<br/>
|
|
||||||
* -r: reinstall an existing app, keeping its data.<br/>
|
|
||||||
* -t: allow test .apks to be installed.<br/>
|
|
||||||
* -i: specify the installer package name.<br/>
|
|
||||||
* -s: install package on sdcard.<br/>
|
|
||||||
* -f: install package on internal flash.<br/>
|
|
||||||
* -d: allow version code downgrade.<br/>
|
|
||||||
* <p/>
|
|
||||||
* pm uninstall [-k] PACKAGE
|
|
||||||
* <p/>
|
|
||||||
* pm uninstall: removes a package from the system.
|
|
||||||
* <p/>
|
|
||||||
* Options:<br/>
|
|
||||||
* -k: keep the data and cache directories around after package removal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ import org.fdroid.fdroid.Preferences;
|
|||||||
import org.fdroid.fdroid.PreferencesActivity;
|
import org.fdroid.fdroid.PreferencesActivity;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.installer.CheckRootAsyncTask;
|
|
||||||
import org.fdroid.fdroid.installer.InstallIntoSystemDialogActivity;
|
import org.fdroid.fdroid.installer.InstallIntoSystemDialogActivity;
|
||||||
import org.fdroid.fdroid.installer.Installer;
|
import org.fdroid.fdroid.installer.Installer;
|
||||||
|
|
||||||
@ -45,7 +44,6 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
Preferences.PREF_LANGUAGE,
|
Preferences.PREF_LANGUAGE,
|
||||||
Preferences.PREF_CACHE_APK,
|
Preferences.PREF_CACHE_APK,
|
||||||
Preferences.PREF_EXPERT,
|
Preferences.PREF_EXPERT,
|
||||||
Preferences.PREF_ROOT_INSTALLER,
|
|
||||||
Preferences.PREF_SYSTEM_INSTALLER,
|
Preferences.PREF_SYSTEM_INSTALLER,
|
||||||
Preferences.PREF_ENABLE_PROXY,
|
Preferences.PREF_ENABLE_PROXY,
|
||||||
Preferences.PREF_PROXY_HOST,
|
Preferences.PREF_PROXY_HOST,
|
||||||
@ -162,10 +160,6 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
checkSummary(key, R.string.expert_on);
|
checkSummary(key, R.string.expert_on);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Preferences.PREF_ROOT_INSTALLER:
|
|
||||||
checkSummary(key, R.string.root_installer_on);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Preferences.PREF_SYSTEM_INSTALLER:
|
case Preferences.PREF_SYSTEM_INSTALLER:
|
||||||
checkSummary(key, R.string.system_installer_on);
|
checkSummary(key, R.string.system_installer_on);
|
||||||
break;
|
break;
|
||||||
@ -196,61 +190,6 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes RootInstaller preference. This method ensures that the preference can only be checked and persisted
|
|
||||||
* when the user grants root access for F-Droid.
|
|
||||||
*/
|
|
||||||
protected void initRootInstallerPreference() {
|
|
||||||
CheckBoxPreference pref = (CheckBoxPreference) findPreference(Preferences.PREF_ROOT_INSTALLER);
|
|
||||||
|
|
||||||
// we are handling persistence ourself!
|
|
||||||
pref.setPersistent(false);
|
|
||||||
|
|
||||||
pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
final CheckBoxPreference pref = (CheckBoxPreference) preference;
|
|
||||||
|
|
||||||
if (pref.isChecked()) {
|
|
||||||
CheckRootAsyncTask checkTask = new CheckRootAsyncTask(getActivity(), new CheckRootAsyncTask.CheckRootCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRootCheck(boolean rootGranted) {
|
|
||||||
if (rootGranted) {
|
|
||||||
// root access granted
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, true);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(true);
|
|
||||||
} else {
|
|
||||||
// root access denied
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, false);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(false);
|
|
||||||
|
|
||||||
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
|
|
||||||
alertBuilder.setTitle(R.string.root_access_denied_title);
|
|
||||||
alertBuilder.setMessage(getActivity().getString(R.string.root_access_denied_body));
|
|
||||||
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
|
||||||
alertBuilder.create().show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
checkTask.execute();
|
|
||||||
} else {
|
|
||||||
SharedPreferences.Editor editor = pref.getSharedPreferences().edit();
|
|
||||||
editor.putBoolean(Preferences.PREF_ROOT_INSTALLER, false);
|
|
||||||
editor.commit();
|
|
||||||
pref.setChecked(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes SystemInstaller preference, which can only be enabled when F-Droid is installed as a system-app
|
* Initializes SystemInstaller preference, which can only be enabled when F-Droid is installed as a system-app
|
||||||
*/
|
*/
|
||||||
@ -352,7 +291,6 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
updateSummary(key, false);
|
updateSummary(key, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
initRootInstallerPreference();
|
|
||||||
initSystemInstallerPreference();
|
initSystemInstallerPreference();
|
||||||
initUninstallSystemAppPreference();
|
initUninstallSystemAppPreference();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user