(Android / React Native) Unable to list file system - android

Response always empty executing ls -a command with native modules.
Other commands like getprop or whoami work just fine tho.
Ive tried cd "other/dir" && ls -a, but also didn't work.
Does anyone know what I might be missing here?
Java / Native Module
#ReactMethod
public void executeCommand(final String command, final Callback callback) {
// To avoid UI freezes run in thread
new Thread(new Runnable() {
public void run() {
OutputStream out = null;
InputStream in = null;
try {
// Send script into runtime process
Process child = Runtime.getRuntime().exec(command);
child.waitFor();
// Get input and output streams
out = child.getOutputStream();
in = child.getInputStream();
// Input stream can return anything
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
String line;
String result = "";
while ((line = bufferedReader.readLine()) != null){
result += line+"\n";
}
// Handle input stream returned message
callback.invoke(result);
} catch (Exception e) {
e.printStackTrace();
callback.invoke(e);
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}).start();
}
In the React world
import { NativeModules } from 'react-native';
const { AndroidShell } = NativeModules;
AndroidShell.executeCommand("ls -a", (res: string) => {
console.log(res)
});

Related

Android Studio Shell Command From App To Execute [duplicate]

I'm trying to execute this command from the application emulator terminal (you can find it in google play) in this app i write su and press enter, so write:
screenrecord --time-limit 10 /sdcard/MyVideo.mp4
and press again enter and start the recording of the screen using the new function of android kitkat.
so, i try to execute the same code from java using this:
Process su = Runtime.getRuntime().exec("su");
Process execute = Runtime.getRuntime().exec("screenrecord --time-limit 10 /sdcard/MyVideo.mp4");
But don't work because the file is not created. obviously i'm running on a rooted device with android kitkat installed. where is the problem? how can i solve? because from terminal emulator works and in Java not?
You should grab the standard input of the su process just launched and write down the command there, otherwise you are running the commands with the current UID.
Try something like this:
try{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes("screenrecord --time-limit 10 /sdcard/MyVideo.mp4\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
su.waitFor();
}catch(IOException e){
throw new Exception(e);
}catch(InterruptedException e){
throw new Exception(e);
}
A modification of the code by #CarloCannas:
public static void sudo(String...strings) {
try{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
for (String s : strings) {
outputStream.writeBytes(s+"\n");
outputStream.flush();
}
outputStream.writeBytes("exit\n");
outputStream.flush();
try {
su.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
outputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
(You are welcome to find a better place for outputStream.close())
Usage example:
private static void suMkdirs(String path) {
if (!new File(path).isDirectory()) {
sudo("mkdir -p "+path);
}
}
Update:
To get the result (the output to stdout), use:
public static String sudoForResult(String...strings) {
String res = "";
DataOutputStream outputStream = null;
InputStream response = null;
try{
Process su = Runtime.getRuntime().exec("su");
outputStream = new DataOutputStream(su.getOutputStream());
response = su.getInputStream();
for (String s : strings) {
outputStream.writeBytes(s+"\n");
outputStream.flush();
}
outputStream.writeBytes("exit\n");
outputStream.flush();
try {
su.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
res = readFully(response);
} catch (IOException e){
e.printStackTrace();
} finally {
Closer.closeSilently(outputStream, response);
}
return res;
}
public static String readFully(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = is.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos.toString("UTF-8");
}
The utility to silently close a number of Closeables (Soсket may be no Closeable) is:
public class Closer {
// closeAll()
public static void closeSilently(Object... xs) {
// Note: on Android API levels prior to 19 Socket does not implement Closeable
for (Object x : xs) {
if (x != null) {
try {
Log.d("closing: "+x);
if (x instanceof Closeable) {
((Closeable)x).close();
} else if (x instanceof Socket) {
((Socket)x).close();
} else if (x instanceof DatagramSocket) {
((DatagramSocket)x).close();
} else {
Log.d("cannot close: "+x);
throw new RuntimeException("cannot close "+x);
}
} catch (Throwable e) {
Log.x(e);
}
}
}
}
}
Process p;
StringBuffer output = new StringBuffer();
try {
p = Runtime.getRuntime().exec(params[0]);
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
p.waitFor();
}
}
catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
String response = output.toString();
return response;
Late reply, but it will benefit someone. You can use the sh command in the exec() method.
Here is my example:
try {
File workingDirectory = new File(getApplicationContext().getFilesDir().getPath());
Process shProcess = Runtime.getRuntime().exec("sh", null, workingDirectory);
try{
PrintWriter outputExec = new PrintWriter(new OutputStreamWriter(shProcess.getOutputStream()));
outputExec.println("PATH=$PATH:/data/data/com.bokili.server.nginx/files;export LD_LIBRARY_PATH=/data/data/com.bokili.server.nginx/files;nginx;exit;");
outputExec.flush();
} catch(Exception ignored){ }
shProcess.waitFor();
} catch (IOException ignored) {
} catch (InterruptedException e) {
try{ Thread.currentThread().interrupt(); }catch(Exception ignored){}
} catch (Exception ignored) { }
What have I done with this?
First I call the shell, then I change (set) the necessary environments in it, and finally I start my nginx with it.
This works on unrooted devices too.
Greetings.

I want when Click button in android studio make connection with python

I tried clicking on a button to make connection with python
but it doesn't run except it only run in main
This is the code that run the connection
public class link {
public static void main(String a[]) {
try {
Process p = Runtime.getRuntime().exec(
"python C:/Users/ASUS/Desktop/sendingCode/jaad/app/test.py");
Scanner in = new Scanner(new InputStreamReader(
p.getInputStream()));
String line = "";
while ((line = in.nextLine()) != null) {
// display each output line form python script
System.out.println(line);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Once I put the previous code on button it wont work with me i dont know why
recordBtn=(Button)findViewById(R.id.recordBtn);
recordBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Process p = Runtime.getRuntime().exec(
"python C:/Users/ASUS/Desktop/sendingCode/jaad/app/test.py");
Scanner in = new Scanner(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = in.nextLine()) != null) {
// display each output line form python script
System.out.println(line);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
});

Socket Connection Always Null When Connecting To Remote Server

Good day.Im trying to connect to server with socket.Here is my code on how i do it.
private class SocketConnection extends AsyncTask<String, String, String> {
PrintWriter out;
BufferedReader in;
#Override
protected String doInBackground(String... params) {
connect();
try {
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException ex) {
System.out.append("error").append("socketcoonection").println();
}
String msg = null;
try {
msg = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
while (run) {
System.out.append(msg).append("socketcoonection").println();
out.println();
out.flush();
/*try {
msg = in.readLine();
} catch (IOException ex) {
Logger.getLogger(MainActivity.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
return null;
}
}
and here is the connect() method
public void connect() {
try {
clientSocket = new Socket("vaenterprises.org/test.php", 8080);
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
if (clientSocket != null) {
run = true;
}
}
and this is the server side php code of test.php
echo json_encode("socket working");
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
and the address link is vaenterprises.org/test/php so im trying to connect to it and read the input or output stream or the echo.Whatever i do,i get nullPointerException at System.out.append(msg).append("socketcoonection").println(); and during debug i figured out that its socket which is null...Please tell me what am i doing wrong?

Run bash script from android app

I want to change the value of variable in xml. The value is based on another file which read by editXml.sh. So I need to run the editXml.sh before app is compiled.
I try to run the script in MainActivity with code as follows:
onCreate() {
......
execScript();
}
execScript(){
try{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("sh /.../editXml.sh");
} catch(Throwable t)
{
t.printStackTrace();
}
}
The editXml.sh is in my local, but the code doesn't work when I run app in Android studio.(Works on local) Should I put my script in the app? And which part of the app? Any suggestion?
Try this. I've tested this code and it works.
Let's you script named script.sh.
Put file script.sh to you project's /res/raw folder.
Use code below.
Build apk. Unpack apk (this is usual zip-archive) and make sure file /res/raw/script.sh exists there.
Install apk on device and start it.
public static void executeCommandAndGetOutput(String command){
BufferedReader reader = null;
String result = "";
try {
Process p = Runtime.getRuntime().exec(command);
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null){
result += line + "\n";
}
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(reader != null)
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Log.i("Test", result);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String pathToScript = getDir("my_scripts", 0).getAbsolutePath() + File.separator + "script.sh";
// Unpacking script to local filesystem
InputStream in = getResources().openRawResource(R.raw.script);
FileOutputStream out = null;
try {
out = new FileOutputStream(pathToScript);
byte[] buff = new byte[1024];
int read = 0;
while ((read = in.read(buff)) > 0) {
out.write(buff, 0, read);
}
}
catch(Exception e){
}
finally {
try {
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// Make script executable
executeCommand("chmod 775 " + pathToScript);
// Execute script
executeCommand("sh " + pathToScript);
}
public static String getSystemCommandOutput(String command){
BufferedReader reader = null;
String result = "";
try {
Process p = Runtime.getRuntime().exec(command);
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null){
result += line + "\n";
}
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeQuietly(reader);
}
return result;
}
You can put script at raw resources and then unpack it to Context.getDir(...) folder and run from there with absolute path.
Also you need to run "chmod 775" (chmod +x) for this file before executing.
Example about copying a file from raw: Copying raw file into SDCard? You can copy to app folder (Context.getDir(...)) instead of sdcard
console output:
58:07.979 8935-8935/cc.softwarefactory.lokki.android E/MainActivity﹕ onCreate
12:58:08.234 8935-8935/cc.softwarefactory.lokki.android E/MainActivity﹕ PATH: /data/data/cc.softwarefactory.lokki.android/app_my_scripts/editxml.sh
12:58:08.258 8935-8935/cc.softwarefactory.lokki.android E/MainActivity﹕ result:
12:58:08.287 8935-8935/cc.softwarefactory.lokki.android E/MainActivity﹕ result: not found
I changed
Log.i("Test", result) to Log.e(TAG,"result: " + result);

Check to see whether root was granted?

I have set up my app to execute the su command using this code:
try {
Runtime.getRuntime().exec("su");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
altDialog.setTitle("No Root");
altDialog
.setMessage("I am afraid I have been unable to execute the su binary. Please check your root status.");
altDialog.setCancelable(false);
altDialog.setButton("Exit App",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
Log.e("Android .img Flasher",
"Exiting due to root error");
finish();
}
});
}
This catches if the su command doesn't exist (I believe), but not if root was actually granted.
How would I be able to check if root was actually granted?
On a side note, how would I be able to store the output of a command using the Runtime.getRuntime.exec() command?
You can use the code bellow. I've wrote it for generic command use, but it works with su command as well. It returns if the command succeed as well as the command output (or error).
public static boolean execCmd(String command, ArrayList<String> results){
Process process;
try {
process = Runtime.getRuntime().exec(new String [] {"sh", "-c", command});
} catch (IOException e) {
e.printStackTrace();
return false;
}
int result;
try {
result = process.waitFor();
} catch (InterruptedException e1) {
e1.printStackTrace();
return false;
}
if(result != 0){ //error executing command
Log.d("execCmd", "result code : " + result);
String line;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
try {
while ((line = bufferedReader.readLine()) != null){
if(results != null) results.add(line);
Log.d("execCmd", "Error: " + line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return false;
}
//Command execution is OK
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
try {
while ((line = bufferedReader.readLine()) != null){
if(results != null) results.add(line);
Log.d("execCmd", line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
You call it with two arguments:
command - string with command to execute
results - empty ArrayList to return the command output. If null, output is not returned.
To check sucommand you can do the following:
//Array list where the output will be returned
ArrayList<String> results = new ArrayList<String>();
//Command to be executed
String command = "su -c ls";
boolean result = execCmd(command,results);
//result returns command success
//results returns command output
Regards.
public static boolean isRootAvailable(){
Process p = null;
try{
p = Runtime.getRuntime().exec(new String[] {"su"});
writeCommandToConsole(p,"exit 0");
int result = p.waitFor();
if(result != 0)
throw new Exception("Root check result with exit command " + result);
return true;
} catch (IOException e) {
Log.e(LOG_TAG, "Su executable is not available ", e);
} catch (Exception e) {
Log.e(LOG_TAG, "Root is unavailable ", e);
}finally {
if(p != null)
p.destroy();
}
return false;
}
private static String writeCommandToConsole(Process proc, String command, boolean ignoreError) throws Exception{
byte[] tmpArray = new byte[1024];
proc.getOutputStream().write((command + "\n").getBytes());
proc.getOutputStream().flush();
int bytesRead = 0;
if(proc.getErrorStream().available() > 0){
if((bytesRead = proc.getErrorStream().read(tmpArray)) > 1){
Log.e(LOG_TAG,new String(tmpArray,0,bytesRead));
if(!ignoreError)
throw new Exception(new String(tmpArray,0,bytesRead));
}
}
if(proc.getInputStream().available() > 0){
bytesRead = proc.getInputStream().read(tmpArray);
Log.i(LOG_TAG, new String(tmpArray,0,bytesRead));
}
return new String(tmpArray);
}

Categories

Resources