Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何构建在Android上运行的本机(命令行)可执行文件?_Android_Linux - Fatal编程技术网

如何构建在Android上运行的本机(命令行)可执行文件?

如何构建在Android上运行的本机(命令行)可执行文件?,android,linux,Android,Linux,我成功地构建了一个使用本机(JNI)库的Android应用程序(GUI) 但是,现在我想创建一个从命令行(root权限)运行的可执行文件,它根本不使用GUI。我如何构建这样的东西?http://www.bekatul.info/content/native-c-application-android [broken(2015年11月9日)] 总结这篇文章 测试代码为: #include <stdio.h>//for printf #include <stdlib.h>

我成功地构建了一个使用本机(JNI)库的Android应用程序(GUI)

但是,现在我想创建一个从命令行(root权限)运行的可执行文件,它根本不使用GUI。我如何构建这样的东西?

http://www.bekatul.info/content/native-c-application-android [broken(2015年11月9日)]

总结这篇文章

测试代码为:

#include  <stdio.h>//for printf
#include  <stdlib.h>//for exit

int main(int argc, char **argv)
{
        int i = 1;
        i+=2;

        printf("Hello, world (i=%d)!\n", i);

        return 0;
        exit(0);
}
APP := test
ROOT := /home/dd/android
INSTALL_DIR := /data/tmp
NDK_PLATFORM_VER := 8

ANDROID_NDK_ROOT := $(ROOT)/android-ndk-r5
ANDROID_NDK_HOST := linux-x86
ANDROID_SDK_ROOT := $(ROOT)/android-sdk-linux_86
PREBUILD := $(ANDROID_NDK_ROOT)/toolchains/arm-eabi-4.4.0/prebuilt/$(ANDROID_NDK_HOST)

BIN := $(PREBUILD)/bin/
LIB := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
INCLUDE := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include

CC := $(BIN)/arm-eabi-gcc
GDB_CLIENT := $(BIN)/arm-eabi-gdb

LIBCRT := $(LIB)/crtbegin_dynamic.o

LINKER := /system/bin/linker

DEBUG := -g

CFLAGS := $(DEBUG) -fno-short-enums -I$(INCLUDE)
CFLAGS += -Wl,-rpath-link=$(LIB),-dynamic-linker=$(LINKER) -L$(LIB)
CFLAGS += -nostdlib -lc

all: $(APP)

$(APP): $(APP).c
        $(CC) -o $@ $< $(CFLAGS) $(LIBCRT)

install: $(APP)
        $(ANDROID_SDK_ROOT)/platform-tools/adb push $(APP) $(INSTALL_DIR)/$(APP) 
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)

shell:
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell

run:
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/$(APP)

debug-install:
        $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver

debug-go:
        $(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP)

debug:
        $(GDB_CLIENT) $(APP)

clean:
        @rm -f $(APP).o $(APP)
/home/dd/android/dev/native/test.c
/home/dd/android/dev/native/Makefile
source code: /home/dd/android/dev/native
android ndk: /home/dd/android/android-ndk-r5
android sdk: /home/dd/android/android-sdk-linux_86
然后,作者使用以下工具对其进行编译和测试:

dd@abil:~/android/dev/native$ make clean; make; make install; make run
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gcc -c  -fno-short-enums -I/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include test.c -o test.o 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-g++ -Wl,--entry=main,-dynamic-linker=/system/bin/linker,-rpath-link=/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -L/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -nostdlib -lc -o test test.o
/home/dd/android/android-sdk-linux_86/platform-tools/adb push test /data/tmp/test 
45 KB/s (2545 bytes in 0.054s)
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/test
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell /data/tmp/test
Hello, world (i=3)!
使用的SDK和NDK为:

#include  <stdio.h>//for printf
#include  <stdlib.h>//for exit

int main(int argc, char **argv)
{
        int i = 1;
        i+=2;

        printf("Hello, world (i=%d)!\n", i);

        return 0;
        exit(0);
}
APP := test
ROOT := /home/dd/android
INSTALL_DIR := /data/tmp
NDK_PLATFORM_VER := 8

ANDROID_NDK_ROOT := $(ROOT)/android-ndk-r5
ANDROID_NDK_HOST := linux-x86
ANDROID_SDK_ROOT := $(ROOT)/android-sdk-linux_86
PREBUILD := $(ANDROID_NDK_ROOT)/toolchains/arm-eabi-4.4.0/prebuilt/$(ANDROID_NDK_HOST)

BIN := $(PREBUILD)/bin/
LIB := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
INCLUDE := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include

CC := $(BIN)/arm-eabi-gcc
GDB_CLIENT := $(BIN)/arm-eabi-gdb

LIBCRT := $(LIB)/crtbegin_dynamic.o

LINKER := /system/bin/linker

DEBUG := -g

CFLAGS := $(DEBUG) -fno-short-enums -I$(INCLUDE)
CFLAGS += -Wl,-rpath-link=$(LIB),-dynamic-linker=$(LINKER) -L$(LIB)
CFLAGS += -nostdlib -lc

all: $(APP)

$(APP): $(APP).c
        $(CC) -o $@ $< $(CFLAGS) $(LIBCRT)

install: $(APP)
        $(ANDROID_SDK_ROOT)/platform-tools/adb push $(APP) $(INSTALL_DIR)/$(APP) 
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)

shell:
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell

run:
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/$(APP)

debug-install:
        $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver

debug-go:
        $(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP)

debug:
        $(GDB_CLIENT) $(APP)

clean:
        @rm -f $(APP).o $(APP)
/home/dd/android/dev/native/test.c
/home/dd/android/dev/native/Makefile
source code: /home/dd/android/dev/native
android ndk: /home/dd/android/android-ndk-r5
android sdk: /home/dd/android/android-sdk-linux_86
然而,《调试指南》是非常好的一部分!复制并粘贴…

设置编译以启用调试:

DEBUG = -g
CFLAGS := $(DEBUG) -fno-short-enums -I$(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
将gdbserver文件($(预构建)/../gdbserver)复制到emulator,然后在Makefile中添加目标,以简化操作:

debug-install:
        $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver
现在我们将在端口1234处调试它:

debug-go:
        $(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234
        $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP)
然后执行它:

dd@abil:~/android/dev/native$ make clean; make; make install; make debug-install; make debug-go
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gcc -c  -g -fno-short-enums -I/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include test.c -o test.o 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-g++ -Wl,--entry=main,-dynamic-linker=/system/bin/linker,-rpath-link=/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -L/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -nostdlib -lc -o test test.o
/home/dd/android/android-sdk-linux_86/platform-tools/adb push test /data/tmp/test 
71 KB/s (3761 bytes in 0.051s)
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/test
/home/dd/android/android-sdk-linux_86/platform-tools/adb push /home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/../gdbserver /data/tmp/gdbserver
895 KB/s (118600 bytes in 0.129s)
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/gdbserver
/home/dd/android/android-sdk-linux_86/platform-tools/adb forward tcp:1234: tcp:1234
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell /data/tmp/gdbserver :1234 /data/tmp/test
Process /data/tmp/test created; pid = 472
Listening on port 1234
现在打开其他控制台并执行调试器:

dd@abil:~/android/dev/native$ make debug
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gdb test
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-elf-linux"...
(gdb) target remote :1234
Remote debugging using :1234
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0xb0001000 in ?? ()
(gdb) b main
Breakpoint 1 at 0x82fc: file test.c, line 6.
(gdb) c
Continuing.
Error while mapping shared library sections:
/system/bin/linker: No such file or directory.
Error while mapping shared library sections:
libc.so: Success.

Breakpoint 1, main (argc=33512, argv=0x0) at test.c:6
6               int i = 1;
(gdb) n
7               i+=2;
(gdb) p i
$1 = 1
(gdb) n
9               printf("Hello, world (i=%d)!\n", i);
(gdb) p i
$2 = 3
(gdb) c
Continuing.

Program exited normally.
(gdb) quit
嗯,没关系。另一个控制台将提供如下附加输出:

Remote debugging from host 127.0.0.1
gdb: Unable to get location for thread creation breakpoint: requested event is not supported
Hello, world (i=3)!

Child exited with retcode = 0 

Child exited with status 0
GDBserver exiting

对于NDK r8d,这可以用更简单的方法解决

  • 创建具有以下目录层次结构的项目:

    项目/
    jni/
    Android.mk
    Application.mk
    *.c、*.cpp、*.h等。
    
  • 用以下内容填写Android.mk。最重要的是最后一行。检查NDK文档中其他变量的含义

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := name-of-your-executable
    LOCAL_SRC_FILES := a.cpp b.cpp c.cpp etc.cpp
    LOCAL_CPPFLAGS := -std=gnu++0x -Wall -fPIE         # whatever g++ flags you like
    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -fPIE -pie   # whatever ld flags you like
    
    include $(BUILD_EXECUTABLE)    # <-- Use this to build an executable.
    
    结果将放在可执行文件的
    项目/libs//名称中

  • 使我朝着正确的方向前进,但它包含一个错误/精度错误

    就gdbserver而言,adb命令

    $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver
    
    将永远无法工作,原因很明显,因为在目录$(PREBUILD)和gdbserver之间,有一个android arm目录。最好是定下来

    PREBUILDDEBUG=$(ANDROID_NDK_ROOT)/prebuilt/android-arm
    
    并以

    $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILDDEBUG)/gdbserver $(INSTALL_DIR)/gdbserver
    
    有了这个,我的android虚拟设备就万事俱备了。(表面上没有分段故障。)在我的真实设备上,我确实有分段故障。这就是问题所在

    make run
    
    部分。关于调试部分,无论是在模拟器上还是在实际设备上,当我进行调试时,总是会得到一个“无法访问内存”

    b main
    

    在gdb模式下。我不知道为什么。

    下面是一个遵循肯尼特答案的示例项目。您可以从头开始创建它,也可以在NDK示例中修改另一个项目,例如,
    hello jni

    jni/main.c:

    jni/Android.mk:

    jni/Android.mk中相应的部分变成:

    LOCAL\u路径:=$(调用我的目录)
    #...
    包括$(清除变量)
    本地模块:=您好
    本地\u SRC\u文件:=main.c
    LOCAL_LDLIBS:=-llog#无需为liblog.so指定路径
    
    include$(BUILD_EXECUTABLE)#网页似乎已备份-这是一篇相当大的文章,因此我没有在此处回显它。要在设备上运行该程序:(假设您的路径上有“adb”,并且您的设备是“adb devices”显示的设备,并且是arm设备,可执行文件的名称是mypgm):“adb push libs/armeabi/mypgm/data/tmp/mypgm”然后是“adb shell chmod 777/data/tmp/mypgm”,并运行“adb shell/data/tmp/mypgm”。把它放在你想要的地方-我在这个例子中使用了/data/tmp。我的应用程序是否可以接受命令行参数,例如,如果我的应用程序将文件名和文件位置作为命令行参数。像LD_LIBRARY_PATH这样的环境变量在Android中也起作用。get_env()有效吗?@kanna:(1)使用通常的
    main(argc,argv)
    方法。(2) 你可以试试。但是它是
    getenv()
    。在这种情况下,$(CLEAR_VARS)代表什么?@Shubashree它是在CFLAGS中解释的。A-entry=main允许我避免出现分段错误,顺便说一句。感谢您的回复。这个主题相当复杂,所以每一点有用的信息都很重要。
    #include <stdio.h>
    #include <android/log.h>
    int main() {
        printf("hello\n");
        __android_log_print(ANDROID_LOG_DEBUG  , "~~~~~~", "log %i", 0); // the 3rd arg is a printf-style format string
        return 0;
    }
    
    LOCAL_PATH := $(call my-dir)
    
    #...
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := hello
    LOCAL_SRC_FILES := main.c
    LOCAL_LDLIBS := -llog   # no need to specify path for liblog.so
    
    include $(BUILD_EXECUTABLE)    # <-- Use this to build an executable.