您的位置:首页 > 编程语言 > C语言/C++

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

2016-03-18 23:23 344 查看


使用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.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"?>

<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才能执行的命令.
全文完.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: