• 【转】使用NDK生成native C/C++的可执行程序


    原文网址:http://www.linuxidc.com/Linux/2011-08/40901.htm

    众所周知, 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() + " ");   //保证在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才能执行的命令.

    全文完.

  • 相关阅读:
    SQL Server数据查询之使用TSQL查询数据
    SQL Server数据查询之聚合函数与分组查询
    服务器配置—开网站空间
    什么是子域名、二级域名、次级域名?
    【转】关于Infragistics.WebUI.UltraWebGrid的使用
    SqlBulkCopy批量赋值数据
    在 ASP.NET MVC 中创建自定义 HtmlHelper
    asp.net web.config加密和解密
    ASP.NET程序中常用的三十一种代码
    ASP.NET MVC3 实现多语言介绍
  • 原文地址:https://www.cnblogs.com/wi100sh/p/4308580.html
Copyright © 2020-2023  润新知