使用NDK生成native C/C++的可执行程序(一)

2014-11-24 10:24:38 · 作者: · 浏览: 0

众所周知, NDK可以生成lib,让java程序通过jni来调用,其实,NDK也可以生成C/C++的可执行程序.不过这个程序要被执行的话还有要求.


1.可执行文件的名字必须是lib*.so. 否则apk安装时不会安装上去,因为目前apk的安装只支持安装lib文件,即lib*.so文件,如果不是此文件格式的,安装时不会拷到lib目录里.也可以考虑把可执行文件放assets里,java程序运行后把它拷贝到其它目录或系统目录.


2.这个文件的执行必须由java程序通过Runtime.getRuntime().exec()来执行.


下面来看看代码.


#include
#include
#include

int main(int argc, char* argv[])
{
FILE *fp1;
char ch;
sleep(10); // sleep 10 second
if ((fp1 = fopen("textc.txt", "w")) == NULL)
{
printf("open file failed");
exit(0);
}

fprintf(fp1, "test string1");
fclose(fp1);
return 0;

}


再看看makefile文件.与test.c在同一目录
Android.mk


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

LOCAL_SRC_FILES:= test.c

LOCAL_MODULE:= test

LOCAL_FORCE_STATIC_EXECUTABLE := true

LOCAL_STATIC_LIBRARIES := libc

LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug

include $(BUILD_EXECUTABLE)


注意上面的makefile,与生成lib的差别就是最后以行include $(BUILD_EXECUTABLE),这个是生成可执行文件的关键.


android项目代码,android项目是一个简单的例子,其中只有一个textview,将其id设为textView01.只有一个Activity:


package com.nicebooks.naviteexec;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MyActivity extends Activity {
TextView mTextView01;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView01 = (TextView) findViewById(R.id.textView01);
String path = "/data/data/" + getPackageName();
String cmd1 = path + "/lib/libtest.so";
String cmd2 = path + "/test";
String cmd3 = "chmod 777 " + cmd2;
String cmd4 = "dd if=" + cmd1 + " of=" + cmd2;
RootCommand(cmd4); //拷贝lib/libtest.so到上一层目录,同时命名为test.
RootCommand(cmd3); //改变test的属性,让其变为可执行
RootCommand(cmd2); //执行test程序.
}

public boolean RootCommand(String command) {
Process process = null;
try {
process = Runtime.getRuntime().exec("sh"); //获得shell.
DataInputStream inputStream = new DataInputStream(process.getInputStream());
DataOutputStream outputStream = new DataOutputStream(process.getOutputStream());


outputStream.writeBytes(cd /data/data/" + getPackageName() + "\n"); //保证在command在自己的数据目录里执行,才有权限写文件到当前目录


outputStream.writeBytes(command + " &\n"); //让程序在后台运行,前台马上返回
outputStream.writeBytes("exit\n");
outputStream.flush();
process.waitFor();

byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
String s = new String(buffer);
mTextView01.setText("CMD Result:\n" + s);
} catch (Exception e) {
mTextView01.setText("Exception:"+ e.getMessage());
return false;
}
return true;
}
}

看看layout文件


main.xml


< xml version="1.0" encoding="utf-8" >
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:id="@+id/textView01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>


下面开始build, 关于cygwin和NDK的环境这篇文章就不再讲,大家可以去google一下.


1.进入cygwin,cd到andr