Skip to content

Commit

Permalink
System apps can be uninstalled
Browse files Browse the repository at this point in the history
  • Loading branch information
javiersantos committed Jul 17, 2015
1 parent aaf66ae commit ecd0435
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.javiersantos.mlmanager.R;
import com.javiersantos.mlmanager.async.DeleteDataInBackground;
import com.javiersantos.mlmanager.async.ExtractFileInBackground;
import com.javiersantos.mlmanager.async.UninstallInBackground;
import com.javiersantos.mlmanager.utils.AppPreferences;
import com.javiersantos.mlmanager.utils.UtilsRoot;
import com.javiersantos.mlmanager.utils.UtilsApp;
Expand Down Expand Up @@ -127,11 +128,9 @@ private void setScreenElements() {
if (appInfo.isSystem()) {
icon_googleplay.setVisibility(View.GONE);
start.setVisibility(View.GONE);
uninstall.setVisibility(View.GONE);

googleplay.setForeground(null);
start.setForeground(null);
uninstall.setForeground(null);
} else {
googleplay.setOnClickListener(new View.OnClickListener() {
@Override
Expand Down Expand Up @@ -174,6 +173,25 @@ public void onClick(View view) {
});

if(UtilsRoot.isRooted() && MLManagerApplication.isPro()) {
if (appInfo.isSystem()) {
uninstall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MaterialDialog.Builder materialBuilder = UtilsDialog.showUninstall(context)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
MaterialDialog dialogUninstalling = UtilsDialog.showTitleContentWithProgress(context
, getResources().getString(R.string.dialog_uninstalling)
, getResources().getString(R.string.dialog_uninstalling_description));
new UninstallInBackground(context, dialogUninstalling, appInfo).execute();
dialog.dismiss();
}
});
materialBuilder.show();
}
});
}
cache.setVisibility(View.VISIBLE);
cache.setOnClickListener(new View.OnClickListener() {
@Override
Expand All @@ -196,6 +214,9 @@ public void onClick(View view) {
, getResources().getString(R.string.dialog_clear_data_success_description, appInfo.getName())).execute();
}
});
} else if (appInfo.isSystem()) {
uninstall.setVisibility(View.GONE);
uninstall.setForeground(null);
}

// FAB (Share)
Expand Down Expand Up @@ -257,7 +278,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Log.i("App", "OK");
finish();
startActivity(new Intent(this, MainActivity.class));
startActivity(new Intent(context, MainActivity.class));
} else if (resultCode == RESULT_CANCELED) {
Log.i("App", "CANCEL");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public DeleteDataInBackground(Context context, MaterialDialog dialog, String dir

@Override
protected Boolean doInBackground(Void... voids) {
boolean status = UtilsRoot.removeWithRootPermission(directory);
return status;
return UtilsRoot.removeWithRootPermission(directory);
}

@Override
Expand All @@ -37,7 +36,7 @@ protected void onPostExecute(Boolean status) {
if (status) {
UtilsDialog.showSnackbar(activity, successDescription, null, null, 2).show();
} else {
UtilsDialog.showTitleContent(context, context.getResources().getString(R.string.dialog_cache_and_data_error), context.getResources().getString(R.string.dialog_cache_and_data_error_description));
UtilsDialog.showTitleContent(context, context.getResources().getString(R.string.dialog_root_required), context.getResources().getString(R.string.dialog_root_required_description));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.javiersantos.mlmanager.async;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;

import com.afollestad.materialdialogs.MaterialDialog;
import com.javiersantos.mlmanager.AppInfo;
import com.javiersantos.mlmanager.R;
import com.javiersantos.mlmanager.activities.MainActivity;
import com.javiersantos.mlmanager.utils.UtilsDialog;
import com.javiersantos.mlmanager.utils.UtilsRoot;

public class UninstallInBackground extends AsyncTask<Void, String, Boolean> {
private Context context;
private Activity activity;
private MaterialDialog dialog;
private AppInfo appInfo;

public UninstallInBackground(Context context, MaterialDialog dialog, AppInfo appInfo) {
this.context = context;
this.activity = (Activity) context;
this.dialog = dialog;
this.appInfo = appInfo;
}

@Override
protected Boolean doInBackground(Void... voids) {
return UtilsRoot.uninstallWithRootPermission(appInfo.getSource());
}

@Override
protected void onPostExecute(Boolean status) {
super.onPostExecute(status);
dialog.dismiss();
if (status) {
activity.finish();
context.startActivity(new Intent(context, MainActivity.class));
} else {
UtilsDialog.showTitleContent(context, context.getResources().getString(R.string.dialog_root_required), context.getResources().getString(R.string.dialog_root_required_description));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ public class UtilsDialog {
public static MaterialDialog showTitleContent(Context context, String title, String content) {
MaterialDialog.Builder materialBuilder = new MaterialDialog.Builder(context)
.title(title)
.content(content).positiveText(context.getResources().getString(R.string.button_ok)).cancelable(true).callback(new MaterialDialog.ButtonCallback() {
.content(content)
.positiveText(context.getResources().getString(R.string.button_ok))
.cancelable(true)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
dialog.dismiss();
Expand All @@ -33,6 +36,22 @@ public static MaterialDialog showTitleContentWithProgress(Context context, Strin
return materialBuilder.show();
}

public static MaterialDialog.Builder showUninstall(Context context) {
MaterialDialog.Builder materialBuilder = new MaterialDialog.Builder(context)
.title(context.getResources().getString(R.string.dialog_uninstall_root))
.content(context.getResources().getString(R.string.dialog_uninstall_root_description))
.positiveText(context.getResources().getString(R.string.button_uninstall))
.negativeText(context.getResources().getString(R.string.button_cancel))
.cancelable(false)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onNegative(MaterialDialog dialog) {
dialog.dismiss();
}
});
return materialBuilder;
}

// 1: APK Extracted
// 2: Snackbar without Button
// 3: App unhide
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/com/javiersantos/mlmanager/utils/UtilsRoot.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,24 @@ public static boolean hideWithRootPermission(String apk, Boolean hidden) {
return status;
}

public static boolean uninstallWithRootPermission(String source) {
boolean status = false;
try {
String[] command = new String[]{"su", "-c", "rm -r " + source + "\n"};

Process process = Runtime.getRuntime().exec(command);
process.waitFor();
int i = process.exitValue();
if (i == 0) {
status = true;
}
} catch (Exception e) {
e.printStackTrace();
}

return status;
}

public static boolean rebootSystem() {
boolean status = false;
try {
Expand Down
9 changes: 7 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
<string name="dialog_extract_fail_description">Unable to extract this APK. Please, try to restart your device.</string>
<string name="dialog_uninstall">Uninstall</string>
<string name="dialog_uninstall_description">Uninstall this app right now</string>
<string name="dialog_uninstalling">Uninstalling %s APK&#8230;</string>
<string name="dialog_uninstalling_description">ML Manager is uninstalling this app. Please wait.</string>
<string name="dialog_cache">Remove cache</string>
<string name="dialog_cache_description">Remove the cache for this app</string>
<string name="dialog_cache_success">Cache deleted</string>
Expand All @@ -51,10 +53,12 @@
<string name="dialog_clear_data_deleting_description">Please wait while all files are being deleted.</string>
<string name="dialog_clear_data_success">Data deleted</string>
<string name="dialog_clear_data_success_description">All data for %s has been removed</string>
<string name="dialog_cache_and_data_error">Root required</string>
<string name="dialog_cache_and_data_error_description">To delete data your device must be rooted with root permission given. If you have denied access once: Go to SuperUser app to give access to ML Manager.</string>
<string name="dialog_root_required">Root required</string>
<string name="dialog_root_required_description">Your device must be rooted with root permission given. If you have denied access once: Go to SuperUser app to give access to ML Manager.</string>
<string name="dialog_reboot">Reboot is necessary to display the changes. Do you want to reboot now?</string>
<string name="dialog_cannot_open">%s can\'t be opened because it\'s hidden. Try to unhide before opening this app.</string>
<string name="dialog_uninstall_root">Are you sure you want to uninstall?</string>
<string name="dialog_uninstall_root_description">You are just one step of removing a system app. Do not delete it if you are unsure, it could cause malfunction of the device.</string>

<!-- Buttons -->
<string name="button_cancel">Cancel</string>
Expand All @@ -63,6 +67,7 @@
<string name="button_share">Share APK</string>
<string name="button_undo">Undo</string>
<string name="button_reboot">Reboot</string>
<string name="button_uninstall">Uninstall</string>

<!-- Settings -->
<string name="settings_delete_all">Delete all extracted APKs</string>
Expand Down

0 comments on commit ecd0435

Please sign in to comment.