Sometimes I need to run a command or script on my device, but they are not available or don't exist.
Can we add some additional commands to Android
device's shell
,
except those commands that are already available on it?
For example, add screenrecord
command to my device (my device has Android
API lower than 19), which this is unavailable on it.
I know how to get the list of available commands on the device with adb shell
adb shell ls /system/bin
but I want to add more custom commands and scripts, to do some special and work.
Is there any way to do it? Or it's impossible?
Android Debug Bridge (adb) is a versatile command-line tool that lets you communicate with a device. The adb command facilitates a variety of device actions, such as installing and debugging apps, and it provides access to a Unix shell that you can use to run a variety of commands on a device.
During VTS testing, shell commands are used to execute a target-side test binary, to get/set properties, environment variables, and system information, and to start/stop the Android framework.
adb stands for the “Android Debug Bridge,” which is a command line utility that is the debug multitool for Android. Typically it's installed via Android Studio when you install the Android SDK under platform-tools , but it takes some amount of setup for your operating system to know to look there.
The answer provides a sequence of steps for building an executable for Android shell
through both Eclipse
(outdated) and Android Studio
(4.1+ by the time of this writing). The last includes ndk-build
and CMake
.
As an example consider mycommand.c
:
#include <stdio.h>
int main()
{
printf("My Command!\n");
return 0;
}
In assumption that NDK
location is set in Eclipse
, create a new Android Application Project
and do the following steps.
Add native support. Right click on the project in Project Explorer
> Android Tools
> Add Native Support
> Finish
Add source code, i.e. put mycommand.c
under project_root
/jni
folder.
Edit Android.mk
under project_root
/jni
as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mycommand
LOCAL_SRC_FILES := mycommand.c
include $(BUILD_EXECUTABLE)
Create Application.mk
* under the project_root
/jni
folder:
APP_ABI := all
Build executable and find it under project_root/libs/<abi>/mycommand
.
*Binaries for all
supported CPU architectures are generated here. Use adb shell cat /proc/cpuinfo
to find out the CPU architecture and set APP_ABI
as per Supported ABIs.
The steps are as follows.
Add mycommand.c
, Android.mk
(same as in the Eclipse
section above) to the /app/src/main/cpp
folder.
Edit build.gradle
:
android {
...
defaultConfig {
...
externalNativeBuild {
ndkBuild {
targets "mycommand"
// use a specific ABI filter if needed
// abiFilters "armeabi-v7a"
}
}
}
externalNativeBuild {
ndkBuild {
path "src/main/cpp/Android.mk"
}
}
}
Build project and find the executable under /app/.externalNativeBuild/ndkBuild/debug/obj/local/<abi>/mycommand
Create a project using the Native C++ template.
Add mycommand.c
to the /app/src/main/cpp
folder and edit CMakeLists.txt
:
cmake_minimum_required(VERSION x.x.x)
add_executable(mycommand
mycommand.c )
Edit build.gradle
:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
targets "mycommand"
// use a specific ABI filter if needed
// abiFilters "armeabi-v7a"
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
Build project and find the executable under /app/build/intermediates/cmake/debug/obj/<abi>/mycommand
Push mycommand
binary from where it is located into your device. Keep in mind that files on SD card aren't executable by default, so the binary should be pushed into the device's internal storage. Depending of whether device is rooted or not you have the following options:
On non-rooted device you can push the binary to /data/local/tmp
:
adb push mycommand /data/local/tmp
On rooted device you can push the binary to SD card and then copy it to /system/bin
(after remounting the partition in read-write mode) along with the other executable files:
adb push mycommand /path/to/sdcard
adb shell
su
mount -o rw,remount /system
cp /path/to/sdcard/mycommand /system/bin
Set the permission of the binary to be executable (this might not be needed in case of /data/local/tmp
). Below chmod 555
(r-xr-xr-x) is used:
adb shell chmod 555 /path/to/mycommand
Now you can shell into your device (with adb shell
) and execute the command.
On non-rooted device use the absolute path to the command:
$ /data/local/tmp/mycommand
My Command!
On rooted device, in case the binary has been copied to /system/bin
, you can call it by the file name:
$ mycommand
My Command!
If in case you are getting this error:
error: only position independent executables (PIE) are supported when you created the executable using CMake,
add these lines to app gradle
default config
{
..........
..........
externalNativeBuild
{
cmake
{
targets "my_command"
abiFilters "armeabi-v7a"
arguments "-DANDROID_PIE=ON" //important
}
}
...........
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With