用NDK开发可执行程序

Android Shell中提供了很多的命令,BusyBox也提供了很多的命令,但是总有不满足我们需求的时候, 比如在PC上广泛使用的tree命令, 就没有Android上可以运行的版本,我们就可以自己通过Android NDK构建。

NDK开发可以运行在Android上的可执行程序,通常都是从已有的源代码, 自己写符合NDK的配置文件,然后使用ndk-build命令进行构建的。

下面,以一个简单的例子说明如何构建可执行文件。

1、创建一个包含jni目录的目录:

mkdir -p ~/androidExe/jni

注意:如果不是jni目录的话,在编译的时候会报错,此处虽然与jni没有半毛钱的关系。

2、在~/androidExe/jni目录中创建xx.c文件,内容如下:

#include<stdio.h>

int main(int argc, char* argv[]) {
    printf("Hello NDK!\n");
    return 0;
}

3、在~/androidExe/jni目录中创建Android.mk文件,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := xx
LOCAL_SRC_FILES := xx.c
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE

include $(BUILD_EXECUTABLE)

准备就绪,工程的结构如下:

4、在~/androidExe目录中执行ndk-build命令:

4、查看构建后的目录,如下:

构建完成后,多出了libsobj两个目录,libs目录下的就是不同CPU架构下的可执行文件,obj目录下生成的是中间产物,方便出现问题以后调试。

5、查看可执行文件的属性:

6、通过adb命令把对应CPU架构的可执行文件放到Android设备的SD卡中:

adb push ~/androidExe/libs/x86/xx /sdcard/xx

7、通过adb命令进入Android设备Shell

adb shell

8、执行命令:

/sdcard/xx

运行效果如下:

还可以通过在App中调用:

package com.leleliu008.androidsdk.exec;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.widget.TextView;

public class ExecActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setTitle("执行可执行文件测试");

		TextView textView = new TextView(this);
		textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
		textView.setTextColor(Color.RED);

		setContentView(textView);

		textView.setText(exec("/data/app/xx"));
	}

	private static String exec(String command) {
		BufferedReader bufferedReader = null;
		try {
			Process process = Runtime.getRuntime().exec(command);
			process.waitFor();
			InputStream is = process.getInputStream();
			bufferedReader = new BufferedReader(new InputStreamReader(is));
			StringBuilder result = new StringBuilder();
			String lineStr = null;
			while ((lineStr = bufferedReader.readLine()) != null) {
				result.append(lineStr + "\n");
			}
			return result.toString();
		} catch (Exception e) {
			Log.e("xx", "onCreate()", e);
			return "error!";
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

运行效果: