使用AndroiStudio、Cmake 开发ndk 入门(上)

1.AS创建一个Android工程

   (1)创建java和c的源文件,配置Cmake

     1> 创建一个类名为Ndkuitls的native工具类

  

public class NdkUtils {
    static {
        System.loadLibrary("bitmap-lib");
    }
    public static native int  addByNdk(int m,int n);
    public static native String  getStringFromNdk(int k);
    public  static native Bitmap getBitmap();
    public  static native void doneBitmap(Bitmap bitmap, int r);
    public static native void countPixels(int[] img, int w, int h, int r);
}

   2> 在src的main目录下面创建一个jni目录,在src/main/jni 下创建一个名bitmap-lib.c的文件,这里.c的命名就是Cmakelists

         配置中所引用的文件

   3>在app目录下面创建一个名称CMakeLists.txt的文件,内容和如下:

   

    通过配置CMakeLists.txt就可以运用ndk中的cmake环境将bitamp-lib.c编译成android平台的so动态库

    项目结构如下图:

    

 (2)在modle的build.gradle中配置ndk

 

   (3)编译工程

2、生成头文件

  (1)打开as的Terminal终端,进入到ndk工具类NdkUtils.java所在的文件夹(不带包名的那一级,本示例见上图可知是      

    D:\WorkPlace\android\qianlifeng\BitampTool\app\src\main\java),注意:一定要到.java文件所在的目录里面,不

    然生成头文件会出现各种莫名其妙得问题

  

  执行  cd  /

    cd WorkPlace\android\qianlifeng\BitampTool\app\src\main\java  切换到如下图所示的路径下:     (2)使用javah命令生成c代码的头文件 

         1>首先看一下javah命令的用法:

       

         2>生成头文件的具体命令(javah  -classpath  ***.jar;.  包名+类名)

           javah  -classpath  C:\sdk\platforms\android-26\android.jar;.   ndkdev.fcw.cn.bitamptool.NdkUtils

           此处有坑,一定要以上格式写,不然会报错,上面的命令可以分成3块:

         

    执行完指令后会在src\main\java目录下生成一个名为   ndkdev_fcw_cn_bitamptool_NdkUtils.h的文件,将此文件剪切到  

    src/mian/jni 目录下面,结构如下:

  


  (3)在bitmap-lib.c文件中编写c代码:

         1>导入头文件,把ndkdev_fcw_cn_bitamptool_NdkUtils.h中的方法拷贝过来,加上形参

         2>写具体的c代码

       示例一:通过java回调c,生成一个制定长度的字串

           

#include <jni.h>
#include <string.h>
#include "ndkdev_fcw_cn_bitamptool_NdkUtils.h"
JNIEXPORT jstring JNICALL Java_ndkdev_fcw_cn_bitamptool_NdkUtils_getStringFromNdk
        (JNIEnv *env, jclass jb, jint n) {
         if (n<0){
             char* res="请输入大于0的数据";
             return (*env)->NewStringUTF(env,res);
         } else{
             char  *buffer[n];
             int i;
             for(i=0;i<n;i++){
                 buffer[i]=i%3==0?"Java":(i%3==1?"回调":"c/c++代码");
             }
             char  res[1024]={0};
             char  res0[1024]={0};
             for(i=0;i<n;i++){
                 char te[15]={0};
                 strcat(te,buffer[i]);
                 strcat(res,te);
             }
             return (*env)->NewStringUTF(env,strcat(res0,res));
         }
}

JNIEXPORT jint JNICALL Java_ndkdev_fcw_cn_bitamptool_NdkUtils_addByNdk
        (JNIEnv *env, jclass jb, jint m, jint n) {
}


  

     写Android的界面的逻辑

      MainActivty的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="ndkdev.fcw.cn.bitamptool.MainActivity">
    <EditText
        android:inputType="number"
        android:maxEms="6"
        android:layout_marginTop="10dp"
        android:id="@+id/sample_text"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text=""
        android:layout_gravity="center_horizontal"
     />
    <TextView
        android:layout_gravity="center_horizontal"
        android:background="@color/colorPrimaryDark"
        android:textColor="@color/colorAccent"
        android:id="@+id/show_tv"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:layout_width="200dp"
        android:minHeight="40dp"
        android:layout_height="wrap_content" />
    <TextView
        android:layout_gravity="center_horizontal"
        android:background="@color/colorPrimary"
        android:text="点击"
        android:id="@+id/done_tv"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:layout_width="200dp"
        android:layout_height="40dp" />
</LinearLayout>

  mainactiy的java代码:

  

public class MainActivity extends AppCompatActivity {
    private EditText mSampleText;
    private TextView mShowTv;
    private TextView mDoneTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSampleText = (EditText) findViewById(R.id.sample_text);
        mShowTv = (TextView) findViewById(R.id.show_tv);
        mDoneTv = (TextView) findViewById(R.id.done_tv);
        mDoneTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                 if (!TextUtils.isEmpty(mSampleText.getText().toString())){
                     int i = Integer.parseInt(mSampleText.getText().toString());
                     String  res= NdkUtils.getStringFromNdk(i>0?i:1);
                     mShowTv.setText(res);
                 }
            }
        });
    }
}

  生成so动态库的目录:

   


     运行效果如下图:

 

 jni开发中常用的函数jstring和char*之间的相互转换

 方法1:利用反射机制

 

jstring charTojstring(JNIEnv* env, const char* pat) {
    jclass strClass = (*env)->FindClass(env,"Ljava/lang/String;");
    jmethodID ctorID = (*env)->GetMethodID(env,strClass, "<init>", "([BLjava/lang/String;)V");
    jbyteArray bytes = (*env)->NewByteArray(env,strlen(pat));
    (*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*) pat);
    jstring encoding = (*env)->NewStringUTF(env,"GB2312");
    return (jstring) (*env)->NewObject(strClass, ctorID, bytes, encoding);
}

char* jstringToChar(JNIEnv* env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (*env)->FindClass(env,"java/lang/String");
    jstring strencode = (*env)->NewStringUTF(env,"GB2312");
    jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray)  (*env)->CallObjectMethod(jstr, mid, strencode);
    jsize alen = (*env)->GetArrayLength(env,barr);
    jbyte* ba = (*env)->GetByteArrayElements(env,barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    free(rtn);
    (*env)->ReleaseByteArrayElements(env,barr, ba, 0);
    return rtn;
}

    下一篇 ndk处理bitmap

猜你喜欢

转载自blog.csdn.net/fengchengwu2012/article/details/79412501