Using adb shell we can clear application data.
adb shell pm clear com.android.browser
But when executing that command from the application
String deleteCmd = "pm clear com.android.browser";
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(deleteCmd);
} catch (IOException e) {
e.printStackTrace();
}
Issue:
It doesn't clear the user data nor give any exception though I have given the following permission.
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA"/>
Question:
How to clear another app application data using adb shell?
This command worked for me:
adb shell pm clear packageName
Afaik the Browser application data is NOT clearable for other apps, since it is store in private_mode. So executing this command could probalby only work on rooted devices. Otherwise you should try another approach.
The command pm clear com.android.browser requires root permission.
So, run su first.
Here is the sample code:
private static final String CHARSET_NAME = "UTF-8";
String cmd = "pm clear com.android.browser";
ProcessBuilder pb = new ProcessBuilder().redirectErrorStream(true).command("su");
Process p = pb.start();
// We must handle the result stream in another Thread first
StreamReader stdoutReader = new StreamReader(p.getInputStream(), CHARSET_NAME);
stdoutReader.start();
out = p.getOutputStream();
out.write((cmd + "\n").getBytes(CHARSET_NAME));
out.write(("exit" + "\n").getBytes(CHARSET_NAME));
out.flush();
p.waitFor();
String result = stdoutReader.getResult();
The class StreamReader:
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;
class StreamReader extends Thread {
private InputStream is;
private StringBuffer mBuffer;
private String mCharset;
private CountDownLatch mCountDownLatch;
StreamReader(InputStream is, String charset) {
this.is = is;
mCharset = charset;
mBuffer = new StringBuffer("");
mCountDownLatch = new CountDownLatch(1);
}
String getResult() {
try {
mCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return mBuffer.toString();
}
#Override
public void run() {
InputStreamReader isr = null;
try {
isr = new InputStreamReader(is, mCharset);
int c = -1;
while ((c = isr.read()) != -1) {
mBuffer.append((char) c);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (isr != null)
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
mCountDownLatch.countDown();
}
}
}
To clear Application Data Please Try this way.
public void clearApplicationData() {
File cache = getCacheDir();
File appDir = new File(cache.getParent());
if (appDir.exists()) {
String[] children = appDir.list();
for (String s : children) {
if (!s.equals("lib")) {
deleteDir(new File(appDir, s));Log.i("TAG", "**************** File /data/data/APP_PACKAGE/" + s + " DELETED *******************");
}
}
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
To reset/clear application data on Android, you need to check available packages installed on your Android device-
Go to adb shell by running adb shell on terminal
Check available packages by running pm list packages
If package name is available which you want to reset, then run pm clear packageName by replacing packageName with the package name which you want to reset, and same is showing on pm list packages result.
If package name isn't showing, and you will try to reset, you will get Failed status.
On mac you can clear the app data using this command
adb shell pm clear com.example.healitia
To clear the cache for all installed apps:
use adb shell to get into device shell ..
run the following command : cmd package list packages|cut -d":" -f2|while read package ;do pm clear $package;done
// To delete all the folders and files within folders recursively
File sdDir = new File(sdPath);
if(sdDir.exists())
deleteRecursive(sdDir);
// Delete any folder on a device if exists
void deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory())
for (File child : fileOrDirectory.listFiles())
deleteRecursive(child);
fileOrDirectory.delete();
}
Related
I am making an app that can uninstall system apps. After going through all the answers from StackOverFlow, I can say that 99% of them are via ADB and the one which I found useful https://stackoverflow.com/a/34399068/9953518 ,this is now changed from Android O.
According to this article https://medium.com/#quaful/the-changes-of-apk-install-location-since-android-oreo-e646d1b53c4d it is now not possible to navigate to a specific folder of the app and we are bound to use .sourceDir. The problem that I have is after requesting for the root and getting the sourceDir, the .apk file doesn't uninstall and if it does, the complete files are not uninstalled or removed in this case. I am using the code below :
//appsSelected is the array with all the package names of the system apps selected to be uninstalled
case "uninstall":
for (int i = 0; i < appsSelected.size(); ++i) {
final int finalI = i;
Thread worker = new Thread(new Runnable() {
#Override
public void run() {
RootManager.getInstance().obtainPermission();
System.out.println("Public directory is "+ yup(appsSelected.get(finalI)));
runCommand("rm -rf "+ yup(appsSelected.get(finalI)) );
}
});
worker.start();
}
break;
This is the fucntion that returns the filePath:
String yup(String pack){
PackageManager m = getPackageManager();
PackageInfo p = null;
try {
p = m.getPackageInfo(pack, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return p.applicationInfo.sourceDir;
}
Finally the function that runs the commands:
public static void runCommand(String command) {
try {
Process chmod = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(chmod.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
chmod.waitFor();
String outputString = output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
I have the root permission ("su" command) and all the permissions required.
At first, run:
pm uninstall <package_name>
Then,
rm -r <applicationinfo.sourceDir>
Then,
rm -r <applicationinfo.publicSourceDir>
Then reboot the device, and the app should be uninstalled.
N.B: All these command should run as root!
TL:DR; version ;)
my app should run without user interaction (autostart etc works)
it should update itself (via apk) without any user interaction
rooted devices are possible
.
problem:
querying a newer apk from a server works
when starting the apk with a (view?) intent, the "install app" prompt pops and needs a user confirmation
How do I solve this without any user interaction?
http://code.google.com/p/auto-update-apk-client/
This seems to be a solution, but there must be better approach.
I already found this: Install Application programmatically on Android
but that doesn't solve my problem.
Solved it! :D
It just works in rooted devices but works perfectly.
Using the unix cmd "pm" (packageManager) allows you to install apks from sdcard, when executing it as root.
Hope this could help some people in the future.
public static void installNewApk()
{
try
{
Runtime.getRuntime().exec(new String[] {"su", "-c", "pm install -r /mnt/internal/Download/fp.apk"});
}
catch (IOException e)
{
System.out.println(e.toString());
System.out.println("no root");
}
}
Required permissions:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
My suggestion is to use plugin mechanism instad of updating the app. You can dynamically load classes from the Web and run them inside your app without any user interaction. There is a lot of resources spread across the Internet:
How to load a Java class dynamically on android/dalvik?
http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html
If su -c doesn't work, try su 0 (only rooted devices can do su!)
The full answer looks like this:
private void installNewApk()
{
String path = mContext.getFilesDir().getAbsolutePath() + "/" + LOCAL_FILENAME;
mQuickLog.logD("Install at: " + path);
ProcessUtils.runProcessNoException(mQuickLog, "su", "0", "pm", "install", "-r", path);
}
With this class defined:
public class ProcessUtils {
Process process;
int errCode;
public ProcessUtils(String ...command) throws IOException, InterruptedException{
ProcessBuilder pb = new ProcessBuilder(command);
this.process = pb.start();
this.errCode = this.process.waitFor();
}
public int getErrCode() {
return errCode;
}
public String getOutput() throws IOException {
InputStream inputStream = process.getInputStream();
InputStream errStream = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
br = new BufferedReader(new InputStreamReader(errStream));
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
return sb.toString();
}
public static String runProcess(String ...command) throws IOException, InterruptedException {
ProcessUtils p = new ProcessUtils(command);
if (p.getErrCode() != 0) {
// err
}
return p.getOutput();
}
public static void runProcessNoException(String ...command) {
try {
runProcess(command);
} catch (InterruptedException | IOException e) {
// err
}
}
}
To use sudo feature, what should I write in the my application? Should I write something? If yes, can you tell me how I can write sudo application? Do I need to change manifest.xml, or add some Java code?
Assuming the device is rooted and your app has been granted superuser permissions, you can use the following method to run commands as root:
public static void runAsRoot(String[] cmds){
Process p;
try {
p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
BufferedReader bf = new BufferedReader(new InputStreamReader(p.getInputStream()));
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd+"\n");
String test;
while((test = bf.readLine()) != null)
{
Log.i(TAG, test);
}
}
//os.writeBytes("exit\n");
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
Just pass it a list of commands in a String array.
Hy, while building an android application for 2.3.3 I got the following error:
I tried to access the files:
private static final String src_msg = "/data/data/com.whatsapp/databases/msgstore.db";
private static final String src_wa = "/data/data/com.whatsapp/databases/wa.db";
I do su before:
Process process = Runtime.getRuntime().exec("su");
I tried to copy the files to sdcard via cp command -> no success
I tried to check if the files exists via new File(src_msg).exists() -> no success
I use the following permissions in manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
what else is missing here? the popup to allow root comes up and has been accepted.
Try that: (Thanks to ramdroid )
private boolean run(boolean runAsRoot, String cmd) {
String shell = runAsRoot ? "su" : "sh";
int exitCode = 255;
Process p;
try {
p = Runtime.getRuntime().exec(shell);
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes(cmd + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
exitCode = p.waitFor();
} catch (IOException e1) {
Log.e("Exception", e1.toString());
} catch (InterruptedException e) {
Log.e("Exception", e.toString());
}
return (exitCode != 255);
}
public boolean copyFile() {
return run(true, "busybox cp /data/FILE TO COPY space DRECTORY TO COPY");
}
Change only YOUR_DIRECTORY and DIRECTORY TO COPYto the needed ones.
This question has been asked here before but the solutions provided are not working..I am trying to display the contents of /data/dalvik-cache folder. I know that to do this we need to become su. I even did that but still i am unable to execute a shell command..
package org.linuxconfidg.Example2;
import android.app.Activity;
import android.widget.*;
import android.os.Bundle;
import java.io.*;
public class Example2Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String lsreturn=myFunLs();
TextView tv=new TextView(this);
tv.setText("Hello Sindhu !! Try to get it \n"+lsreturn);
setContentView(tv);
}
public String myFunLs()
{
try {
// Executes the command.
Process process;
process = Runtime.getRuntime().exec("/system/bin/su");
process = Runtime.getRuntime().exec("/system/bin/ls /data/dalvik-cache > /data/local");
pr
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Can anyone please help me out in finding out how to run linux commands in android application. I am testing this app in my emulator which is defaultly rooted
You can't simply run 'su' on the emulator, there's no root access by default. You'll need to install the 'su' program as well as the SuperUser.apk, and you'll have to do this each time you start the emulator unless using snapshots.
More information and links to the files you need can be found here on SO as well as this blog post by Russell Davis
I think the problem comes from the fact that you are using TWO different process instances.
You have to be on the su process to carry on sending commands:
You can check the question "Read command output inside su process"
for an answer.
Then I tried & managed to make working code (I'm sure it works!)
public void runAsRoot(String[] cmds) throws Exception {
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
InputStream is = p.getInputStream();
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd+"\n");
int readed = 0;
byte[] buff = new byte[4096];
// if cmd requires an output
// due to the blocking behaviour of read(...)
boolean cmdRequiresAnOutput = true;
if (cmdRequiresAnOutput) {
while( is.available() <= 0) {
try { Thread.sleep(200); } catch(Exception ex) {}
}
while( is.available() > 0) {
readed = is.read(buff);
if ( readed <= 0 ) break;
String seg = new String(buff,0,readed);
console.println("#> "+seg);
}
}
}
os.writeBytes("exit\n");
os.flush();
}
In the below example, I try to execute "/system/bin/screencap" to capture android screen.
via adb:
> adb shell
# /system/bin/screencap -p /sdcard/myscreenshot.png
via Android app:
sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + path).getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
Hope this helps.