¿Cómo construyo un ejecutable nativo (línea de comandos) para ejecutarlo en Android?

He tenido éxito con la construcción de una aplicación de Android (GUI) que utiliza una biblioteca nativa (JNI).

Sin embargo, ahora me gustaría crear un ejecutable que se ejecuta desde la línea de comandos (privilegios de root) y no utiliza una GUI en absoluto. ¿Cómo construyo algo así?

4 Solutions collect form web for “¿Cómo construyo un ejecutable nativo (línea de comandos) para ejecutarlo en Android?”

A partir de NDK r8d, esto se puede resolver de una manera mucho más simple.

  1. Cree un proyecto con la siguiente jerarquía de directorios:

    project/ jni/ Android.mk Application.mk *.c, *.cpp, *.h, etc. 
  2. Rellene Android.mk con el siguiente contenido. Lo más importante es la última línea. Compruebe el NDK doc para conocer el significado de las otras variables.

     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. 
  3. Vaya al directorio del project/ , y simplemente escriba

     ndk-build 

    El resultado se colocará en project/libs/<arch>/name-of-your-executable .

http://www.bekatul.info/content/native-c-application-android [broken (9 de noviembre de 2015)]

Para resumir el artículo …

El código de prueba es:

 #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); } 

El Makefile es:

 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) 

El autor almacenó esos archivos en su computadora linux local en:

 /home/dd/android/dev/native/test.c /home/dd/android/dev/native/Makefile 

El autor entonces compilado y probado con:

 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 y NDK utilizados fueron:

 source code: /home/dd/android/dev/native android ndk: /home/dd/android/android-ndk-r5 android sdk: /home/dd/android/android-sdk-linux_86 

Sin embargo, la guía de depuración fue la parte realmente buena! Copiar y pegar …

Establezca la compilación para habilitar depuración:

 DEBUG = -g CFLAGS := $(DEBUG) -fno-short-enums -I$(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include 

Copie el archivo gdbserver ($ (PREBUILD) /../ gdbserver) al emulador, añada el destino en Makefile para hacerlo más fácil:

 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 

Ahora lo depuraremos @ puerto 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) 

Entonces ejecútelo:

 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 

Ahora abra otra consola y ejecute el depurador:

 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) pi $1 = 1 (gdb) n 9 printf("Hello, world (i=%d)!\n", i); (gdb) pi $2 = 3 (gdb) c Continuing. Program exited normally. (gdb) quit 

Bueno, está bien. Y la otra consola le dará salida adicional así:

 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 

He aquí un ejemplo de proyecto que sigue la respuesta de KennyTM. Puede crearlo desde cero o modificar otro proyecto, por ejemplo, hello-jni en las muestras NDK.

Jni / main.c:

 #include <stdio.h> int main() { printf("hello\n"); return 0; } 

Jni / Application.mk:

 #APP_ABI := all APP_ABI := armeabi-v7a 

Jni / Android.mk:

 LOCAL_PATH := $(call my-dir) # first target: the hello-jni example # it shows how to build multiple targets # {{ you may comment it out include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_LDLIBS := -llog -L$(LOCAL_PATH)/lib -lmystuff # link to libmystuff.so include $(BUILD_SHARED_LIBRARY) #}} you may comment it out # second target include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := main.c include $(BUILD_EXECUTABLE) # <-- Use this to build an executable. 

Tengo que notar que no verá ningún registro en la salida stdout, tendrá que usar adb logcat para verlo.

Así que si quieres registrar:

Jni / main.c:

 #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; } 

Y la sección correspondiente en jni / Android.mk se convierte en:

 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. 

Como no tengo 50 reputación, no puedo comentar sobre la respuesta de Someone Somewhere, así que lo hago aquí como una respuesta.

Me gustaría citar un error / misprecision: en lo que concierne a gdbserver, el comando adb

 $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver 

Nunca será capaz de trabajar, por razones obvias, porque "entre" los directorios $ (PREBUILD) y gdbserver, no es el directorio android-brazo. Es mejor establecer

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

Y reemplazar el comando anterior por

 $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILDDEBUG)/gdbserver $(INSTALL_DIR)/gdbserver 

Con esto todo funciona para mí con un dispositivo virtual android. (No hay aparición de error de segmentación.) En mi dispositivo real, tengo una falla de segmentación. Eso fue el

 make run 

parte. Con respecto a la parte de depuración, ya sea en el emulador o en el dispositivo real, siempre tengo un "no puede acceder a la memoria" cuando hago el

 b main 

En modo gdb … ¿Alguna idea? La ayuda sería muy apreciada.

  • Linux Ubuntu Android SDK manager no está iniciando - android: java: no encontrado
  • [Error: Error al encontrar la variable de entorno 'ANDROID_HOME'. Intente configurarlo manualmente
  • Emulador de Android en Yakkety Yak (Ubuntu 16.10)
  • 'Ningún comando' adb 'encontrado' error en Ubuntu
  • El emulador de Android no se inicia, avd
  • ¿Cómo evitar las filtraciones de Eclipse en XServer al editar archivos XML de Android?
  • Registros de sistema de archivos Android
  • Cygdrive Error de terminal: opus / src / opus.o error
  • Search.h-No existe tal archivo o directorio mientras se porta libtiff en Android-tiff 4.0.1
  • ./fastboot: Ningún archivo o directorio
  • Emulador de Android se bloquea en Ubuntu 11.10
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.