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.
Related
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)
});
I am trying to write output of atrace to sdcard. I am using
getRuntime().exec()("atrace gfx > /storage/sdcard0/trace.txt")
in the app.App is signed as a system app and the command is working fine from terminal.But no file is created when running it from the app.
I solved it by reading data from inputstream and writing it to a file
try {
Process p = Runtime.getRuntime().exec("atrace -t 5 gfx");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
File myFile = new File("/storage/sdcard0/trac.txt");
FileOutputStream f = null;
try {
f = new FileOutputStream(myFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
PrintWriter pw = new PrintWriter(f);
while (line != null) {
pw.println(line);
//Toast.makeText(getBaseContext(), line, Toast.LENGTH_LONG).show();
line = reader.readLine();
}
pw.flush();
pw.close();
f.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
I am running a server which writes a simple Welcome message to a new Client upon Successful connection!
Now I am sure of it that my android device connects to the server but I am unable to receive the welcome text that the server sends.
I am new to socket programming and I am looking for a unified solution to this.
I will paste my code which has a successful outputStream snippet and gets the android connected to the server. I ll leave the InputStream section black, since I need the solution for that!
private ArrayBlockingQueue<Integer> mQueue = new ArrayBlockingQueue<Integer>(100);
private AtomicBoolean mStop = new AtomicBoolean(false);
private OutputStream mOutputStream = null;
private InputStream mInputStream = null;
private Socket mSocket = null;
private static Thread sNetworkThread = null;
private final Runnable mNetworkRunnable = new Runnable() {
log("starting network thread");
String encoding = "UTF-8";
String output="";
#Override
public void run() {
log("starting network thread");
try {
mSocket = new Socket(ARDUINO_IP_ADDRESS, PORT);
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
} catch (UnknownHostException e1) {
e1.printStackTrace();
mStop.set(true);
} catch (IOException e1) {
e1.printStackTrace();
mStop.set(true);
}
mQueue.clear(); // we only want new values
//Output Stream
try {
while(!mStop.get()){
int val = mQueue.take();
if(val >= 0){
log("sending value "+val);
mOutputStream.write((val+"\n").getBytes());
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
try {
mStop.set(true);
if(mOutputStream != null) mOutputStream.close();
if(mSocket != null) mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//InputStream
try
{
//Call method to read inputStream
output = readFully(mInputStream,encoding);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Server Message"+output, Toast.LENGTH_SHORT).show();
log("returning from network thread");
sNetworkThread = null;
}
};
Well I added two methods to achieve the inputStream by calling it from the thread. The methods are as follows.
public String readFully(InputStream inputStream, String encoding)
throws IOException {
return new String(readFully(inputStream), encoding);
}
private byte[] readFully(InputStream inputStream)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos.toByteArray();
}
** The Server returns a String - "Welcome New User"
Well I hv used putty in RAW mode to coonect to the server and it works fine.
StackTrace Logs:
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/>==< ArduinoYun >==<﹕ starting network thread
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/libc﹕ [NET] getaddrinfo hn 9, servname NULL, ai_family 0+
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/libc﹕ [NET] ht 0x31302e302e302e
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/libc﹕ [NET] getaddrinfo-exit SUCCESS
I need to integrate the inputStream on this thread.
P.S. OutputStream works smoothly from this code!
You need to read one line. Your present code tries to read everything until end of stream, whuch only happens when the peer closes the connection.
public String convertStreamToString(java.io.InputStream is)
{
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try
{
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null)
{
sb.append(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return sb.toString();
}
Above code might help you in converting InputStream into String.
I hope this will help you.
I am trying to implement a simple socket that sends and receives strings from a server.
The following code is freezing the application, not sure if I have done something obviously wrong?
public String internetRoutesRetrieve(String userName) {
String command = null;
String response = null;
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("Hidden IP", HiddenPort);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
command = "SEARCH <" + userName + ">";
dataOutputStream.writeUTF(command);
response = dataInputStream.readUTF();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return response;
}
Thanks
Edit: It seems the program is freezing when I am trying to save the response from the server
see AsyncTask for proper client server communication on Android application.
you'd usualy get android.os.NetworkOnMainThreadException if you don't but I'd give it a try.
as an error report I want to send the device and/or application log to a email account. For that I prepared a button in my view. Can someone help me with that, how can I retrieve the log files?
Thanks
String separator = System.getProperty("line.separator");
try {
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
log.append(separator);
}
} catch (Exception e) {
}
Here's a slightly improved version, adapted from Ramesh (thanks). The main difference is to do your own buffering. It's fast.
private void extractLogToFile()
{
// Make file name.
String fullName = ...;
// Extract to file.
File file = new File (fullName);
InputStreamReader reader = null;
FileWriter writer = null;
try
{
// get input stream
String cmd = "logcat -d -v time";
Process process = Runtime.getRuntime().exec(cmd);
reader = new InputStreamReader (process.getInputStream());
// write output stream
writer = new FileWriter (file);
char[] buffer = new char[10000];
do
{
int n = reader.read (buffer, 0, buffer.length);
if (n == -1)
break;
writer.write (buffer, 0, n);
} while (true);
reader.close();
writer.close();
}
catch (IOException e)
{
if (writer != null)
try {
writer.close();
} catch (IOException e1) {
}
if (reader != null)
try {
reader.close();
} catch (IOException e1) {
}
e.printStackTrace();
return;
}
}