首页 / 操作系统 / Linux / 使用NDK生成native C/C++的可执行程序
众所周知, NDK可以生成lib,让java程序通过jni来调用,其实,NDK也可以生成C/C++的可执行程序.不过这个程序要被执行的话还有要求. 1.可执行文件的名字必须是lib*.so. 否则apk安装时不会安装上去,因为目前apk的安装只支持安装lib文件,即lib*.so文件,如果不是此文件格式的,安装时不会拷到lib目录里.也可以考虑把可执行文件放assets里,java程序运行后把它拷贝到其它目录或系统目录. 2.这个文件的执行必须由java程序通过Runtime.getRuntime().exec()来执行.下面来看看代码. test.c 可以将此文件放在Android项目的jni目录里,需要自己创建jni目录,与res,src等目录同级. #include <stdio.h> #include <stdlib.h> #include <string.h> 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.mkLOCAL_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() + "
"); //保证在command在自己的数据目录里执行,才有权限写文件到当前目录 outputStream.writeBytes(command + " &
"); //让程序在后台运行,前台马上返回 outputStream.writeBytes("exit
"); outputStream.flush(); process.waitFor(); byte[] buffer = new byte[inputStream.available()]; inputStream.read(buffer); String s = new String(buffer); mTextView01.setText("CMD Result:
" + s); } catch (Exception e) { mTextView01.setText("Exception:"+ e.getMessage()); return false; } return true; } } 看看layout文件main.xml<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/textView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 下面开始build, 关于cygwin和NDK的环境这篇文章就不再讲,大家可以去google一下.1.进入cygwin,cd到android项目的jni的路径,输入ndk-build,如果不出错,将在android项目里生成一个libs目录.libs目录还生成一个armeabi.在armeabi目录里会有一个test文件.2.我们要将test文件改名成libtest.so.3.然后在eclipse里clean/build.4.将程序在手机上运行.可以看到 程序自己的数据目录下生成一个textc.txt文件.而且即使java程序退出了,此test程序仍在执行,因为我用sleep和后台执行方式来执行的.test已经是一个独立的进程在android系统里运行了. 如果手机是破解的,有root权限的,可以将process = Runtime.getRuntime().exec("su");来替换上面同一行程序.这样你可以随意写文件到root能操作的目录,也可以执行其它root才能执行的命令.全文完.
收藏该网址