gpt4 book ai didi

android - Android上的完全原生应用程序?

转载 作者:行者123 更新时间:2023-12-01 05:36:07 34 4
gpt4 key购买 nike

是否可以开发一个不依赖 Dalvik 运行时和任何 Java 库而运行的 native 应用程序?

基本上,我想制作一个可以通过 shell 运行的 native 二进制文件,该 shell 可以在没有 system_server 的情况下运行。进程运行。理想情况下,我希望能够通过 OpenGL 系统渲染内容来创建自己的 Window Server,而不是依赖 SurfaceFlinger(由于 system_server 未运行,这也将失效)。

我问这个的原因是我想在 C/C++ 中尝试较低级别的 Android 开发,而 Java 根本不需要。所以基本上,我正在尝试开发一个独立的应用程序,它可以通过 OpenGL+Cairo 渲染事物并接收 HID 输入。

PS:我知道NDK是什么,这不是我要找的。我想创建独立的二进制文件,而不是创建在 Dalvik VM 中运行的东西。

最佳答案

在您的设备上运行 native 代码有两种可能性:使用 NDK 或将您的应用程序嵌入到框架中。据我了解,不考虑第一种方法,因此,我认为您可以看看第二种方法。 Here是如何实现第二种方法的示例。

An example of porting existing code to a custom Android device

It is due time for another technical post here on the blog. This post will be about porting existing c-libraries to Android, something I did as part of the dev board demos we are doing here at Enea.

Platform addition or NDK

There are two ways of bringing native code to an Android device, either add it to the platform itself and integrate it with the framework, or include it with an application package. The latter method have evolved a lot and with the release of NDK version 5 even allows you to hook directly into the application lifecycle http://developer.android.com/reference/android/app/NativeActivity.html from the NDK. The NDK is useful for any application where you have need of native performance, have portable C libriaries you want to reuse or just some legacy native code that could be included in your application. The NDK integrates well with the Android SDK and is a great way to include native functionality in your application. It should be the preferred way for any application that needs to be reusable across a lot of Android devices.

The other option is to include your functionality, it may be native or Java, as an API extension for all applications to use. This will only work on devices that implement these extensions and it may be a suitable option for device builders. This is the variant that we aim for here.

Analyze the existing project

Porting native code to Android is not always straight forward, especially if we are talking about C++ code due to the fact that Android uses its own c-runtime with limited support for exceptions among other things. If you want to know more about the details of bionic there is an overview in the NDK docs.

The code I wanted to port for this project was the Enea LINX for Linux framework which is a fast IPC framework. My purpose was to be able to interact with control systems running our OSE real time operating system which also implements this kind of IPC. LINX consists of a couple of kernel driver modules, a user space library and some configuration and control utilities. It is written in C. I had created a small demo with LINX in Android before where I compiled it separately and used static linking but for this project I wanted a complete port to the Android build system. It did not have any issues with bionic compatability so the port should be straight forward.

I just want to add a short disclaimer about LINX. I use it here since it is a good example of integrating a solution into Android from kernel drivers up to the API levels. This particular piece of code does add additional IPC mechanisms to the systems which more or less messes up the security model so do not use it unless you are aware of the implications. The steps needed to port code to Android described in this post are however applicable for any type of driver/framework/library that you may want to include on your product.

Adding kernel driver modules

The first step was to add the kernel modules to the Android build. One way would have built a new kernel and include them directly but for this project I chose to keep them as separate modules. Building for the kernel is not handled by the Android build system meaning that we build them as we would do with any Linux system. The target is an Atmel based development board and in the LINX module build I provide the headers and cross compilation toolchain for that kernel and architecture.

Now for the Android specific parts. We need to add the compiled kernel modules to the platform build system in some way and create an Android.mk file that includes them in the system image when we build. Add a folder in the source tree where your project will go, device or external are suitable candidates. I created a folder called linx that will hold the entire linx port and in that I added a subfolder called modules where I place the prebuilt kernel modules. Now what we need is an Android makefile to copy them to the suitable place in the out folder for system image generation. This will look like:


LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := linx.ko

LOCAL_MODULE_CLASS := SHARED_LIBRARY

# This will copy the file in /system/lib/modules
#
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/modules

LOCAL_SRC_FILES := $(LOCAL_MODULE)

include $(BUILD_PREBUILT)

The standard location for modules on the Android system image is System/lib/modules so that is where we copy them. If we build the platform now the build system will copy our precompiled module linx.ko to the system image that we use for our device. The next step is to make sure that we have the module installed on the system when we run it. This can either be done manually via the shell or via a script that we run during init.

In this case I have created a shell script to be launched from init.rc with the following content:


#linx init
insmod /lib/modules/linx.ko
insmod /lib/modules/linx_tcp_cm.ko
netcfg eth0 up
ifconfig eth0 192.168.1.12
mktcpcon --ipaddr=192.168.1.21 ControlConn
mklink --connection=tcpcm/ControlConn control_link

This includes installing the modules and configuring the network and LINX-link. We launched this from init.rc by adding:


...
#linx init script
service linx-setup /system/etc/linx_setup.sh
oneshot
...

The setup script is added to the system image in the same way by including it as a prebuilt target.


LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := linx_setup.sh

LOCAL_MODULE_CLASS := ETC

LOCAL_MODULE_PATH := $(TARGET_OUT)/etc

LOCAL_SRC_FILES := $(LOCAL_MODULE)

include $(BUILD_PREBUILT)

Creating Android make files for the user space code

Now that we have the drivers in place the next step is to look at porting the user space libraries. The default LINX build system uses standard GNU make files but we need to create new ones adapted to the Android build system. Start out by adding the source files needed to the linx directory created in the Android source tree. This gives the following structure:


Android.mk  
include
liblinx
linx_basic
linxcfg
linx_setup.sh
modules

I have the linx setup script and the main Android.mk file in the top directory and then we have the source files in separate folders and the include files in the include folder. To illustrate how the Android make files for each source component is created we can use liblinx as an example. The Android.mk file looks like:


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := linx.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_MODULE := liblinx
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

We set our sources by specifying LOCAL_SRC_FILES and the name of the library by specifying LOCAL_MODULE. We also need to supply the header files in the include directory by specifying LOCAL_C_INCLUDES. Finally this is a shared library that we are porting so use the BUILD_SHARED_LIBRARY template. This will build the library with the Android build system and add it to the system image as a shared library with the name liblinx.so.

The rest of the code is moved to the Android build system in the same way, by creating Android.mk files and specifying type and any dependencies. As another example we may look at the syntax for building the mktcpcon configuration program. This depends on the library we just created and hence the makefile looks entry looks like:


LOCAL_SRC_FILES := mktcpcon.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_STATIC_LIBRARIES += liblinxcfg
LOCAL_SHARED_LIBRARIES += liblinx
LOCAL_MODULE := mktcpcon
include $(BUILD_EXECUTABLE)

Here we use the BUILD_EXECUTABLE template and we also need to specify static and shared libraries that we link against.

Summary

I hope that provides some insight in how you setup the build for an existing linux project to run on an Android system. The steps to follow are:

  • Build any kernel related things using the correct kernel build system and config for your device
  • Add the kernel modules (and/or kernel) to the platform build system and create Android.mk files for them using the prebuilt template.
  • Create config and intialization services for your drivers if needed and add them to init.
  • Move the rest of your code (user space) to the Android source tree and create Android.mk files for them.
  • If you encounter build errors work them out in the source code and see what incompatabilities your code have with the specifics of the Android C-runtime.

That wraps up my post for today. Having done this we are now able to use our added drivers and API:s from native programs running in the shell. The next step is to create a JNI layer and java library to allow regular Android applications to make use of our platform additions.

I have been away for half a year on paternal leave (nice Swedish benefit) but now it is full time Android hacking again and pushing the team to publish things. Hopefully you will see more activity here including a follow up on this post discussing applications APIs.

关于android - Android上的完全原生应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8625178/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com