如何为 Android shell 构建可执行文件

How to build an executable for Android shell

有时我需要 运行 我的设备上的命令或脚本,但它们不可用或不存在。

我们可以向 Android 设备的 shell 添加一些额外的命令吗? 除了那些已经可用的命令?

例如,在我的设备上添加screenrecord命令(我的设备Android API低于19),这是不可用的。

我知道如何使用 adb shell

获取设备上的可用命令列表
adb shell ls /system/bin 

但我想添加更多自定义命令和脚本,以做一些特殊的工作。

有什么办法吗?还是不可能?

答案提供了通过 Eclipse(过时的)和 Android Studio(4.1+ 到本文)。最后一个包括 ndk-buildCMake.


我。准备源代码

例如考虑 mycommand.c:

#include <stdio.h>

int main()
{
    printf("My Command!\n");
    return 0;
}

二.构建可执行文件

Eclipse(可能已过时)

假设 NDK 位置设置在 Eclipse 中,创建一个新的 Android Application Project 并执行以下步骤。

  1. 添加本机支持。右键单击 Project Explorer 中的项目 > Android Tools > Add Native Support > Finish

  2. 添加源代码,即将mycommand.c放在project_root/jni文件夹下

  3. 编辑project_root/jni下的Android.mk如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE     := mycommand
    LOCAL_SRC_FILES  := mycommand.c
    
    include $(BUILD_EXECUTABLE)
    
  4. project_root/jni文件夹下创建Application.mk*:

    APP_ABI := all
    
  5. 构建可执行文件并在project_root/libs/<abi>/mycommand.

    下找到

* all 支持的 CPU 架构的二进制文件在此处生成。使用 adb shell cat /proc/cpuinfo 找出 CPU 架构并根据 Supported ABIs.

设置 APP_ABI

Android Studio 和 ndk-build

步骤如下

  1. mycommand.cAndroid.mk(与上面Eclipse部分相同)添加到/app/src/main/cpp文件夹。

  2. 编辑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"
            }
        }
    }
    
  3. 构建项目,找到/app/.externalNativeBuild/ndkBuild/debug/obj/local/<abi>/mycommand

    下的可执行文件

Android Studio 和 CMake

  1. 使用 Native C++ 模板创建项目。

  2. mycommand.c 添加到 /app/src/main/cpp 文件夹并 编辑 CMakeLists.txt:

    cmake_minimum_required(VERSION x.x.x)
    
    add_executable(mycommand
                   mycommand.c )
    
  3. 编辑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"
            }
        }
    }
    
  4. 构建项目,找到/app/build/intermediates/cmake/debug/obj/<abi>/mycommand

    下的可执行文件

三。将二进制文件推送到设备

mycommand 二进制文件从它所在的位置推送到您的设备中。请记住,SD 卡上的文件默认情况下不可执行,因此应将二进制文件推送到设备的内部存储中。根据设备是否已获得 root 权限,您有以下选项:

  • 非root设备上,您可以将二进制文件推送到/data/local/tmp:

     adb push mycommand /data/local/tmp
    
  • root设备上,你可以将二进制文件推送到SD卡,然后将其复制到/system/bin(以读写方式重新挂载分区后模式)以及其他可执行文件:

     adb push mycommand /path/to/sdcard
     adb shell
     su
     mount -o rw,remount /system
     cp /path/to/sdcard/mycommand /system/bin
    

四.设置可执行权限(可选

将二进制文件的权限设置为可执行(/data/local/tmp 的情况下可能不需要这样做)。 chmod 555(r-xr-xr-x) 下面使用:

adb shell chmod 555 /path/to/mycommand

伏。 运行命令

现在您可以 shell 进入您的设备(使用 adb shell)并执行命令。

  • 非root设备上使用命令的绝对路径:

     $ /data/local/tmp/mycommand
     My Command!
    
  • root设备上,如果二进制文件已经复制到/system/bin,你可以通过文件名调用它:

     $ mycommand
     My Command!
    

如果您遇到此错误:

错误:当您使用 CMake

创建可执行文件时,仅支持位置独立可执行文件 (PIE)

将这些行添加到应用程序 gradle

default config
{
..........
..........
externalNativeBuild
{
 cmake 
  { 
   targets "my_command"
   abiFilters "armeabi-v7a"
   arguments "-DANDROID_PIE=ON" //important
  }
 }
...........
}

如果您在此位置没有 Android 和 ndk-build 的二进制文件,它们位于

app\build\intermediates\ndkBuild\debug\obj\local\arm64-v8a\objs-debug\test1

对于 arm64-v8a 和其他平台对应。