ndk开发入门(上)

1.AS创建Android工程

(1)创建java源文件

           创建一个类名为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) 创建.c源文件

         在src的main目录下面创建一个jni目录,在src/main/jni 下创建一个名bitmap-lib.c的文件

  2、配置编译环境

   (1)cmake构建文件

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

 (2)build.gradle配置

           在modle的build.gradle中配置ndk

             项目结构如下图:

3、生成头文件

        打开as的Terminal终端,进入到ndk工具类NdkUtils.java所在的文件夹(不带包名的那一级,本示例见上图可知是       D:\WorkPlace\android\qianlifeng\BitampTool\app\src\main\java),注意:一定要到.java文件所在的目录里面,不 然生成头文件会出现各种莫名其妙得问题

  

           切换到如下图所示的路径下:           使用javah命令生成c代码的头文件,首先看一下javah命令的用法:

       

         生成头文件的具体命令(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 目录下面,结构如下:

  

4、编写c源码

         在bitmap-lib.c文件中编写c代码,导入头文件,把ndkdev_fcw_cn_bitamptool_NdkUtils.h中的方法拷贝过来,加上形参

#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) {
}

  5、编译工程

          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动态库的目录:

   

           运行效果如下图:

  

 6、jni反射

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

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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值