I'm trying to use linux command in my app. But I failed to get root permission.
Could you please let me know how to get root permission?
String[] cmd = {"su"};
String result_process2 = runProcess2(cmd);
public String runProcess2(String[] cmd) {
try {
Process process = Runtime.getRuntime().exec(cmd);
It looks like doesn't work.
One thing weird is
I found su in /system/xbin, but when I check this directory through ls in app, su file didn't exist there.
Command is
String ls = "ls -al /system/xbin/";
String resultls = runProcess((String)ls);
public String runProcess(String arg) {
try {
Process process = Runtime.getRuntime().exec(arg);
Do you know why I couldn't see su file in /system/xbin/ even though it can be found through adb shell in my laptop?
A standard Android device does not have access to root privileges. In order to attain this you will have to root the device. See this link for more information.
As for why you can find the file through the ADB shell and not from within the app is probably that you don't have read access for the file outside the ADB shell.
Can anyone say, whether adb commands can be executed through my android application. If it is possible to execute, how it can be implemented?
You can do it with this:
Process process = Runtime.getRuntime().exec("your command");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
Don't forget to surround it with a try and catch statement.
Edit:
#Phix is right, ProcessBuilder would be better to use.
Normal Android apps have different privileges to processes started via adb, e.g., processes started via adb are allowed to the capture the screen whereas normal apps aren't. So, you can execute commands from your app via Runtime.getRuntime().exec(), but they won't have the same privileges as if you had executed from an adb shell.
i came across this post looking for a different query, but i have worked specifically with input on android before, so I'd just like to put some clarity on the matter.
The reason why
Runtime.getRuntime().exec("adb shell input keyevent 120");
Is not working, is because you are not removing
adb shell
The ADB part is only for use on your computer, if you have incorrectly installed ADB, the command would actually be a path to the adb.exe file on your computer, like this
C:\XXXX\ADB Files\adb.exe shell
or
C:\XXXX\ADB Files\adb shell
The shell part tells the ADB program on your computer to access the devices shell, so your device will not know what shell is either...
Using sh /path/to/commandList.sh will execute the commads listed in commandList.sh as it is a shell script (a .batch file on windows is similar )
The command you want to use is
Runtime.getRuntime().exec("input keyevent 120");
However this will cause Environment null and working directory null, you can bypass this by writing the commands to a shell script ( .sh file ) and then running the script with
Runtime.getRuntime().exec("sh path/to/shellScript.sh");
Sometimes the sh is not needed, but i use it just incase.
I hope this clears at least something up :)
adb shell invoked in Runtime.getRuntime().exec is not running under shell user. It provide shell but with same process owner user (like u0_a44). That's the reason all command did not work.
This is what I do in Kotlin, I also get command responses too
fun runShellCommand(command: String) {
// Run the command
val process = Runtime.getRuntime().exec(command)
val bufferedReader = BufferedReader(
InputStreamReader(process.inputStream)
)
// Grab the results
val log = StringBuilder()
var line: String?
line = bufferedReader.readLine()
while (line != null) {
log.append(line + "\n")
line = bufferedReader.readLine()
}
val Reader = BufferedReader(
InputStreamReader(process.errorStream)
)
// if we had an error during ex we get here
val error_log = StringBuilder()
var error_line: String?
error_line = Reader.readLine()
while (error_line != null) {
error_log.append(error_line + "\n")
error_line = Reader.readLine()
}
if (error_log.toString() != "")
Log.info("ADB_COMMAND", "command : $command $log error $error_log")
else
Log.info("ADB_COMMAND", "command : $command $log")
}
Executing
Runtime.getRuntime().exec("adb shell input keyevent 120");
I got the following error:
java.io.IOException: Cannot run program "adb": error=13, Permission denied.
Executing
Runtime.getRuntime().exec("adb shell input keyevent 120");
There is no error but at the same time, my request is not processed to take the screenshot.
I found out this was working in earlier versions of android but later it was removed. Though I'm not able to provide the source here why it is not working.
Hope this helps someone like me who is trying to use this approach to take the screenshot when the app is not in the foreground.
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
string cmd = "/system/bin/input keyevent 23\n";
os.writeBytes(cmd);
the phone must be rooted. here I have executed adb command "input keyevent 23".
remember when you execute adb command through su you does not need to add "adb shell input keyevent 23"
I need to run an .sh file that starts a process in background as root from an APK, but couldn't do it. Even when I use su it gives the APP level permissions. Here is my .sh fule contents
#!/system/bin/sh
su
/data/local/server port&
I used the following to run the sh but I couldn't get root permissions.
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("su");
proc = rt.exec("sh /sdcard/server.sh");
}catch(Exception e) {
e.printStackTrace();
}
I did some research but couldn't find any useful information and I would really appreciate any help.
Thanks.
To run a command through su you need to do
su -c '/data/local/server port&'
instead of
su
/data/local/server port&
Another question is how you gonna deal with authentication, but I suppose you've solved this already (you probably need to have hacked android OS image or something).
I am working in android application. I want to copy data from 1 file to other file.I have executed below command for it, but not able to copy data from file1 -> file 2.
// Executes the command.
String CAT_COMMAND = "cat /sdcard/file1 > /sdcard/file2";
Process process = Runtime.getRuntime().exec(CAT_COMMAND);
I have used ADB SHELL command at DOS , executed CAT command which works fine.
But code execution is not working into the real devices.
please help me out why does it is not copying data from file1->file2.??
provide resolution for writing/copying data using CAT command.
Thanks
can you try with the complete path /mnt/sdcard .(or) Try to get the right path by Environment.getExternalStorageDirectory()
I would like to pull the log file from a device to my PC. How can I do that?
Logcollector is a good option but you need to install it first.
When I want to get the logfile to send by mail, I usually do the following:
connect the device to the pc.
Check that I already setup my os for that particular device.
Open a terminal
Run adb shell logcat > log.txt
I hope this code will help someone. It took me 2 days to figure out how to log from device, and then filter it:
public File extractLogToFileAndWeb(){
//set a file
Date datum = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ITALY);
String fullName = df.format(datum)+"appLog.log";
File file = new File (Environment.getExternalStorageDirectory(), fullName);
//clears a file
if(file.exists()){
file.delete();
}
//write log to file
int pid = android.os.Process.myPid();
try {
String command = String.format("logcat -d -v threadtime *:*");
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder result = new StringBuilder();
String currentLine = null;
while ((currentLine = reader.readLine()) != null) {
if (currentLine != null && currentLine.contains(String.valueOf(pid))) {
result.append(currentLine);
result.append("\n");
}
}
FileWriter out = new FileWriter(file);
out.write(result.toString());
out.close();
//Runtime.getRuntime().exec("logcat -d -v time -f "+file.getAbsolutePath());
} catch (IOException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
//clear the log
try {
Runtime.getRuntime().exec("logcat -c");
} catch (IOException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
return file;
}
as pointed by #mehdok
add the permission to the manifest for reading logs
<uses-permission android:name="android.permission.READ_LOGS" />
I would use something of this sort :
$adb logcat -d > logcat.txt
The -d option dumps the entire circular buffer into the text file and if you are looking for a particular action/intent try
$adb logcat -d | grep 'com.whatever.you.are.looking.for' -B 100 -A 100 > shorterlog.txt
Hope this helps :)
For those not interested in USB debugging or using adb there is an easier solution. In Android 6 (Not sure about prior version) there is an option under developer tools: Take Bug Report
Clicking this option will prepare a bug report and prompt you to save it to drive or have it sent in email.
I found this to be the easiest way to get logs. I don't like to turn on USB debugging.
EDIT:
The internal log is a circular buffer in memory. There are actually a few such circular buffers for each of: radio, events, main. The default is main.
To obtain a copy of a buffer, one technique involves executing a command on the device and obtaining the output as a string variable.
SendLog is an open source App which does just this: http://www.l6n.org/android/sendlog.shtml
The key is to run logcat on the device in the embedded OS. It's not as hard as it sounds, just check out the open source app in the link.
Often I get the error "logcat read: Invalid argument". I had to clear the log, before reading from the log.
I do like this:
prompt> cd ~/Desktop
prompt> adb logcat -c
prompt> adb logcat | tee log.txt
I know it's an old question, but I believe still valid even in 2018.
There is an option to Take a bug report hidden in Developer options in every android device.
NOTE: This would dump whole system log
How to enable developer options? see: https://developer.android.com/studio/debug/dev-options
What works for me:
Restart your device (in order to create minimum garbage logs for developer to analyze)
Reproduce your bug
Go to Settings -> Developer options -> Take a bug report
Wait for Android system to collect the logs (watch the progressbar in notification)
Once it completes, tap the notification to share it (you can use gmail or whetever else)
how to read this?
open bugreport-1960-01-01-hh-mm-ss.txt
you probably want to look for something like this:
------ SYSTEM LOG (logcat -v threadtime -v printable -d *:v) ------
--------- beginning of crash
06-13 14:37:36.542 19294 19294 E AndroidRuntime: FATAL EXCEPTION: main
or:
------ SYSTEM LOG (logcat -v threadtime -v printable -d *:v) ------
--------- beginning of main
A simple way is to make your own log collector methods or even just an existing log collector app from the market.
For my apps I made a report functionality which sends the logs to my email (or even to another place - once you get the log you can do whether you want with it).
Here is a simple example about how to get the log file from a device:
http://code.google.com/p/android-log-collector/
Simple just run the following command to get the output to your terminal:
adb shell logcat
Two steps:
Generate the log
Load Gmail to send the log
.
Generate the log
File generateLog() {
File logFolder = new File(Environment.getExternalStorageDirectory(), "MyFolder");
if (!logFolder.exists()) {
logFolder.mkdir();
}
String filename = "myapp_log_" + new Date().getTime() + ".log";
File logFile = new File(logFolder, filename);
try {
String[] cmd = new String[] { "logcat", "-f", logFile.getAbsolutePath(), "-v", "time", "ActivityManager:W", "myapp:D" };
Runtime.getRuntime().exec(cmd);
Toaster.shortDebug("Log generated to: " + filename);
return logFile;
}
catch (IOException ioEx) {
ioEx.printStackTrace();
}
return null;
}
Load Gmail to send the log
File logFile = generateLog();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(logFile));
intent.setType("multipart/");
startActivity(intent);
References for #1
https://stackoverflow.com/a/34883741/2162226
https://stackoverflow.com/a/3359857/2162226
~~
For #2 - there are many different answers out there for how to load the log file to view and send. Finally, the solution here actually worked to both:
load Gmail as an option
attaches the file successfully
Big thanks to https://stackoverflow.com/a/22367055/2162226 for the correctly working answer
Thanks to user1354692 I could made it more easy, with only one line! the one he has commented:
try {
File file = new File(Environment.getExternalStorageDirectory(), String.valueOf(System.currentTimeMillis()));
Runtime.getRuntime().exec("logcat -d -v time -f " + file.getAbsolutePath());}catch (IOException e){}
I have created a small library (.aar) to retrieve the logs by email. You can use it with Gmail accounts. It is pretty simple but works. You can get a copy from here
The site is in Spanish, but there is a PDF with an english version of the product description.
I hope it can help.
First make sure adb command is executable by setting PATH to android sdk platform-tools:
export PATH=/Users/espireinfolabs/Desktop/soft/android-sdk-mac_x86/platform-tools:$PATH
then run:
adb shell logcat > log.txt
OR first move to adb platform-tools:
cd /Users/user/Android/Tools/android-sdk-macosx/platform-tools
then run
./adb shell logcat > log.txt
I would use something like:
$ adb logcat --pid=$(adb shell pidof com.example.yourpackage)
which you can then redirect to a file
$ adb logcat --pid=$(adb shell pidof com.example.yourpackage) > log.txt
or if you also want to see it at stdout as well:
$ adb logcat --pid=$(adb shell pidof com.example.yourpackage) | tee log.txt