Can we run simple shell script in android system using react native? - android

I am writing a simple app using react native to make some file operations done automatically. I have tried packages like strong text react-native-fs, but I found that there are some files/folders that can not be read using
RNFS.ls(PATH).
Trying to list files in that folder will throw an exception.
However, these files can be displayed using ls command in adb shell. So I am wondering if there is a way that we can run shell commands in react native like we make some system calls in java/python?
Thanks

Write your own Native Module.
You can easily run a shell command from Java and call it from React Native using React Native's Native Modules. You can find more information here:
https://facebook.github.io/react-native/docs/0.60/native-modules-android#callbacks
And for your Java command, you'd want to use something like this:
String command = "ls " + path; // Where path is your desired path.
Runtime runtime = Runtime.getRuntime();
Process result = runtime.exec( command );
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( result.getInputStream() ) );
String[] parts = bufferedReader.readLine().split( "\\s+" );

#flyskywhy/react-native-android-shell works well even with root command e.g.
AndroidShell.executeCommand('su -c ifconfig eth0 down; su -c ifconfig eth0 hw ether 19:21:19:49:20:21; su -c ifconfig eth0 up', (result) => {
console.log(result)
});

Related

Android: running app as root (through java.lang.Runtime, 'su -c /bin/sh'): escaping not working properly

So, I need to copy a file to /system, and have to use shell commands, because the application is not running with enough privileges (and is not even installed to /system/apps at that time) - so its impossible to write to /system directly.
String cmd = String.format("\"/bin/sh -c \'cp %s %s'", tempPath, out);
p = Runtime.getRuntime().exec(new String[] { "su", "-c", cmd });
However, SuperSU pop-up informs me, that following application was granted to run as root:
/bin/sh -c _cp %s %s_.
So ' are replaced with _, and eventually command takes no effect.
What is a proper way to run a command having so much quotes ("" and '' for a single argument to su)?
I know of using su's stdin to run commands separated by \n, but it seems to be having its own problems (and was not working too).
If you're calling through SuperSU, there are a ton of pitfalls, and the recommended way is to use libsuperuser. See http://su.chainfire.eu/ for details.

android how to install custom fonts on \system\fonts directory in rooted device

I am going to develop an android app it works as font installer.
the target of my app is rooted device which does not include the desired font, and it goes to install from war\fonts\ to \system\fonts folder.
any help
Try this:
First to test this code you must copy your custom fonts to /sdcard/ I don't know if you are going to put them in assets or download them from internet. Anyways to test, use the following command lines:
cd /<path_to_sdk>/platforms-tools/
./adb root
./adb remount
./adb push sample.ttf /sdcard/
Now the code:
This code only execute a bunch of commands. Note that the important part is that this commands change the default android fonts by your own fonts. Make sure of always make a backup.
Process process;
try {
process = Runtime.getRuntime().exec("mount -o remount /dev/mtdblock4 /system");
process = Runtime.getRuntime().exec("cat /system/fonts/DroidSansFallback.ttf >> /sdcard/DroidSansFallback.ttf");
process = Runtime.getRuntime().exec("cat /sdcard/sample.ttf >> /system/fonts/DroidSansFallback.ttf");
process = Runtime.getRuntime().exec("mount -o ro,remount /dev/mtdblock4 /system");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
Also, you must reboot your device after do this.

Android: send an onClick bash command to /dev/null

I made some buttons in my app that exec a bash cmd.
Here is my string:
final String[] test = {"su","-c","echo test > /system/test.txt"};
This cmd works, in fact, i can see the test.txt file on /system/ with the line test inside.
My question is: When i push on the button for exec that cmd the device create a toast with the string "echo test /system/text.txt".
I'm guessing this is due to "-c", anyway:
final String[] test = {"su","echo test > /system/test.txt"};
won't work, and:
final String[] test = {"su","-c","echo test > /system/test.txt >> /dev/null"};
won't work as well and create a toast showing "echo test /system/test.txt /dev/null"
is there any way i can avoid this "problem"?
Also, can anyone show me a little function that create a toast with a spinning wheel when i onClick to the button that exec it?
Thanks!!!
This extract from su manual should clear your question about -c option:
-c, --command=COMMAND
pass a single COMMAND to the shell with -c
And
final String[] test = {"su","-c","echo test > /system/test.txt >> /dev/null"};
won't work because Android don't have /dev/null device. To get it work you need to have a -c option after su and get a rid of /dev/null. You may use android API to delete this file instead.

How can I execute all the possible unix(shell) commands in android programmatically?

I have this .php file sending commands to my android application:
I have tried working with:
Runtime.getRuntime().exec(commandLine);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
but the commands echo, pwd and some others are not working.
I get the following exception:
java.io.IOException: Error running exec(). Command: [pwd] Working Directory: null Environment: null
As far as I understand this is because there is not any shell environment.
Then I have tried writing in a .sh file the command I want and then execute the command this way:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("sh /runCmds/shTest.sh");
InputStream is = proc.getInputStream();
and got solved the problem with pwd, echo and most of the commands.
But later on I realized that I want to keep the state of the commands I execute.
For example I want to change directory(cd data) and execute the command mkdir Apoel
And here is when I face my problem. What to do?
I came up with another idea:
Make a shell script (.sh) and each time the user wants to execute a command append the new command in it (and run the hole script(.sh) again). But I think is not a very good way to do it!
Is there any easy way to it? Can my application open a terminal easily?
Here is a code I found for a Terminal Emulator, but it is too complicated!
https://github.com/jackpal/Android-Terminal-Emulator
An interactive shell is one which remains running, waiting for new commands which it receives from stdin, while producing it's output to stdout and stderr - as a result, it's environment including any changes is retained for the duration of the session. For the shell to be useful to a user, stdin, stoud, stderr need to be connected through to the user - via the console, a serial line, or xterm, etc.
On Android, typically what you do is hook onto the pipes corresponding to stdin, stdout, stderr for the shell process that you've created, and use them to push in commands provided by your java program and accept output for your program to interpret/display.
The idea of creating a script and running it would only work in the case where all the commands are entered before any of them execute.
First, some background. On any Posix system, in the shell, there are 2 types of commands:
Internal commands (pwd,cd,echo)
external commands (ls,cp,mv, sometimes echo as well)
All the directory context commands (cd,pwd etc) are commands implemented inside the shell and thus require the shell to remain running, if the changes are to hold (for eg. cd /data/local/tmp).
On the other hand, external commands are standalone and can run indepenedently, but acquire their directory context from their parent process (in most cases, the shell).
Now to solve the problem. Yes, using a script is a good idea, but it is painful to implement, as it requires an overhead of file editing. However, we can use the shell to create a script on the fly and execute it using the -c option. For example:
/system/bin/sh -c 'cd /data/local/tmp; touch abc; cp abc def; cd /; rm /data/local/tmp/abc'
In summery:
String sPrefix="/system/bin/sh -c 'cd someplace;";
String sInputCmd=getCommand(); // this is simulating your command input
String sPostfix="'";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix); // sh -c 'cd someplace; echo do something'
InputStream is = proc.getInputStream();
However, this does not give us the capability to set a directory context, so we need to simulate that. Directory contexts can be added by using the Runtime.exec(String command, String[] envp, File dir) method. With this we have the possibility of maintaining directory
context between commands. But how do we actually do that? One solution is to append pwd to the command and take the last line of the output as the new directory context. Thus
String sPath = "/"; // start in root directory
String sPrefix = "/system/bin/sh -c 'cd someplace;";
String sInputCmd; // this is simulating your command input
String sPostfix = ";echo;pwd'";
Runtime rt = Runtime.getRuntime();
while(!(sInputCmd=getCommand()).equals("")) {
File dir= new File(sPath);
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix, NULL, dir);
InputStream is = proc.getInputStream();
// Do processing on input.
sPath= last_line_of_is ;
}
Finally, the last option is to integrate one of the terminal emulators into you app.
[1] http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String,%20java.lang.String%5B%5D,%20java.io.File%29

Using Google Breakpad for Android NDK?

Is anyone using Google Breakpad for Android native code (NDK) ?
If so, could you elaborate on how to get it up and running (the client side that is).
The docs are very limited and don't mention Android at all. The build system contains android information though which make me think it shouldn't be a problem.
Sorry about that, I did the initial port but I didn't really document anything. However, one of the Chrome engineers did some work on the port and wrote a really nice README:
https://chromium.googlesource.com/breakpad/breakpad/+/master/README.ANDROID
There's also an NDK-compatible Android.mk file in there now, so if you're using the standard NDK build system it should be simple to incorporate Breakpad.
I also found a good example project for that.
As it is in the project you can set up Google Breakpad like:
extern "C" {
void Java_com_pluusystem_breakpadjavacall_MainActivity_initNative(JNIEnv* env, jobject obj, jstring filepath)
{
const char *path = env->GetStringUTFChars(filepath, 0);
google_breakpad::MinidumpDescriptor descriptor(path);
exceptionHandler = new google_breakpad::ExceptionHandler(descriptor, NULL, DumpCallback, NULL, true, -1);
}
}
in the cpp side and like:
// Save Dump Path
initNative(getExternalCacheDir().getAbsolutePath());
in the java side.
After that implementing the bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) function you will be able to do something before the app crashes.
I have experienced and also found this issue which confirms me, that in this function you can't do java callbacks under ART just under DVM (before android 5 - Lollipop).
My example repo for Flutter Android/iOS: https://github.com/Sunbreak/flutter-breakpad.trial
Android
Build libbreakpad_client.a on Linux (e.g. https://multipass.run/)
$NDK is local path of your Android NDK directory
$CLI_BREAKPAD is local clone of https://github.com/Sunbreak/cli-breakpad.trial
cd $BREAKPAD/src/android
cp -r google_breakpad jni
$NDK/ndk-build
Install libbreakpad_client.a of all architectures
mkdir -p ./android/app/src/main/cmakeLibs
cp -r $BREAKPAD/src/android/obj/local/* ./android/app/src/main/cmakeLibs/
run on macOS/Linux
# Device/emulator connected
$ android_abi=`adb shell getprop ro.product.cpu.abi`
$ flutter run
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
I/flutter_breakpad(31631): JNI_OnLoad
D/flutter_breakpad(31631): Dump path: /data/data/com.example.flutter_breakpad/files/f5258c0e-eff3-433a-7ea47880-c756fc17.dmp
$ adb shell "run-as com.example.flutter_breakpad sh -c 'cat /data/data/com.example.flutter_breakpad/files/f5258c0e-eff3-433a-7ea47880-c756fc17.dmp'" >| libflutter-breakpad.so.dmp
run on Linux (e.g. https://multipass.run/)
$ $CLI_BREAKPAD/breakpad/linux/$(arch)/dump_syms build/app/intermediates/cmake/debug/obj/${android_abi}/libflutter-breakpad.so > libflutter-breakpad.so.sym
$ uuid=`awk 'FNR==1{print \$4}' libflutter-breakpad.so.sym`
$ mkdir -p symbols/libflutter-breakpad.so/$uuid/
$ mv ./libflutter-breakpad.so.sym symbols/libflutter-breakpad.so/$uuid/
$ $CLI_BREAKPAD/breakpad/linux/$(arch)/minidump_stackwalk libflutter-breakpad.so.dmp symbols/ > libflutter-breakpad.so.log

Categories

Resources