Выполнить команду оболочки из Android
Я пытаюсь выполнить эту команду из терминала эмулятора приложения (вы можете найти его в Google Play) в этом приложении я пишу su
и нажмите ввод, поэтому напишите:
screenrecord --time-limit 10 /sdcard/MyVideo.mp4
и нажмите снова, введите и начните запись экрана, используя новую функцию Android Kitkat.
Итак, я пытаюсь выполнить тот же код из Java с помощью этого:
Process su = Runtime.getRuntime().exec("su");
Process execute = Runtime.getRuntime().exec("screenrecord --time-limit 10 /sdcard/MyVideo.mp4");
Но не работайте, потому что файл не создан. очевидно, я работаю на рутированном устройстве с установленным Android KitKat. в чем проблема? как я могу решить? потому что из терминала эмулятор работает а в яве нет?
7 ответов
Вы должны взять стандартный ввод su
Процесс только что запустился и запишите команду там, иначе вы запускаете команды с текущим UID
,
Попробуйте что-то вроде этого:
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);
}
Модификация кода с помощью @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();
}
}
(Вы можете найти лучшее место для outputStream.close ())
Пример использования:
private static void suMkdirs(String path) {
if (!new File(path).isDirectory()) {
sudo("mkdir -p "+path);
}
}
Обновление: чтобы получить результат (вывод на стандартный вывод), используйте:
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");
}
Утилита для тихого закрытия нескольких объектов Closeables ( Socket может не быть Closeable):
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;
Пример для копирования файла:
void copyFile_dd(){
try {
Process su;
su = Runtime.getRuntime().exec("su");
String cmd = "dd if=/mnt/sdcard/test.dat of=/mnt/sdcard/test1.dat \n"+ "exit\n";
su.getOutputStream().write(cmd.getBytes());
if ((su.waitFor() != 0)) {
throw new SecurityException();
}
} catch (Exception e) {
e.printStackTrace();
//throw new SecurityException();
}
}
другое приложение для запуска решения из оболочки Android Linux:
am start -n [your package]/.MainActivity
в соответствии с Запуск приложения из терминала оболочки Android
Поздний ответ, но это будет полезно кому-то. Вы можете использоватьsh
команда вexec()
метод. Вот мой пример:
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) { }
Что я сделал с этим? Сначала я звоню вshell
, затем меняю (устанавливаю) в нем нужные окружения и, наконец, запускаю с ним свой nginx.
Это работает и на нерутированных устройствах.
Привет.
Ответ @18446744073709551615 великолепен, но есть гораздо более простой способ его использовать, если на телефоне Android установлена более новая версия magisk, которую следует использовать.--command
возможность запуска команды один раз, это делает код намного проще и менее подвержен ошибкам
import org.apache.commons.lang3.ArrayUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public static List<String> sudo(String[] cmd) {
List<String> res = new ArrayList<String>();
try {
String[] fullCmd = ArrayUtils.addAll(new String[]{"su", "--command"}, cmd);
Process su = Runtime.getRuntime().exec(fullCmd);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(su.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(su.getErrorStream()));
String s;
while ((s = stdInput.readLine()) != null)
res.add(s);
while ((s = stdError.readLine()) != null)
res.add(s);
} catch (IOException e) {
e.printStackTrace();
}
return res;
}