第一步:爆结果照,让你有坚持下去的信心
二、NDK解释
NDK全称:Native Development Kit。
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。
NDK集成了交叉编译器,并提供了相应的mk文件隔离cpu、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。
NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。
三、NDK环境搭建
(a)Project->Properties->Builders->New,新建一个FirstBuilder。
(b)在弹出的【Choose configuration type】对话框,选择【Program】,点击【OK】:
(c)在弹出的【Edit Configuration】对话框中,配置选项卡【Main】。
在“Name“中输入新builders的名称(这个名字可以任意取)。
在“Location”中输入nkd-build.cmd的路径(这个是下载完ndkr10e后解压后的路径,这个建议放在根目录下面,路径不能有空格和中文)。根据各自的ndk路径设置,也可以点击“Browser File System…”来选取这个路径。
在“Working Diretcoty”中输入TestNdk位置(也可以点击“Browse Workspace”来选取TestNdk目录)。如图1
第一个箭头是ndk目录下面的ndk-build.cmd
第二个箭头是选自己的项目
(d)继续在这个【Edit Configuration】对话框中,配置选项卡【Refresh】。如图2
勾选“Refresh resources upon completion”,
勾选“The entire workspace”,
勾选“Recuresively include sub-folders”。
图2
(e)继续在【Edit Configuration】对话框中,配置选项卡【Build options】。
勾选“After a “Clean””,(勾选这个操作后,如果你想编译ndk的时候,只需要clean一下项目 就开始交叉编译)
勾选“During manual builds”,
勾选“During auto builds”,
勾选“Specify working set of relevant resources”。如图3
图3
点击“Specify Resources…”勾选FirstJni工程,点击”finish“。 点击“OK“,完成配置。 如图4
编译环境以及成功搭建完
四、demo的简单实现
package com.example.firstjni; public class JniClient { static public native String AddStr(String strA,String strB); static public native int AddInt(int a,int b); }
(1)用cmd命令定位到JniClient.class 所在目录,输入“javac JniClient.java“后回车,生成JniClinet.class文件(如果是用的Eclipse建的工程,在TestNdk\bin\classes\com\ndk\test目录下就已经有JniClinet.class文件了)。com.example.firstjni
(2)将JniClinet.class拷贝到FirstJni\bin\classes\com\example\firstjni目录,将cmd命令定位到FirstJni\bin\classes目录,输入”javah com.example.firstjni.JniClient“后回车,在FirstJni\bin\classes目录下就生成了C++头文件com_example_firstjni_JniClient.h
图片讲解如下:
com_example_firstjni_JniClient.h的文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_firstjni_JniClient */ #ifndef _Included_com_example_firstjni_JniClient #define _Included_com_example_firstjni_JniClient #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_firstjni_JniClient * Method: AddStr * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_firstjni_JniClient_AddStr (JNIEnv *,jclass,jstring,jstring); /* * Class: com_example_firstjni_JniClient * Method: AddInt * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_firstjni_JniClient_AddInt (JNIEnv *,jint,jint); #ifdef __cplusplus } #endif #endif3.在jni目录下新建一个Android.mk文件,其内容如下 ( 关于mk文件需要注意,很重要,还有c和c++文件的mk文件还不一样,此处是调用c语言的mk文件,至于其他的怎么调用,这个自己去百度吧,在此就不多说了 )
# Copyright (C) 2009 The Android Open Source Project # # Licensed under the Apache License,Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing,software # distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := FirstJni LOCAL_SRC_FILES := com_example_firstjni_JniClient.c include $(BUILD_SHARED_LIBRARY)
4. 将刚刚手动生成的com_example_firstjni_JniClient.h拷贝到FirstJni工程的jni目录下,
然后新建一个com_example_firstjni_JniClient.c文件完成头文件中函数的实现,其内容如下(本来想写两个方法的,现在只讲解第一个方法,返回一个字符串“HelloWorld from JNI”,另一个方法是一个a+b的运算,方法写到这里,感兴趣的可以自己去研究):
com_example_firstjni_JniClient.c
#include "com_example_firstjni_JniClient.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #ifdef __cplusplus extern "C" { #endif /* * Class: com_ndk_test_JniClient * Method: AddStr * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_firstjni_JniClient_AddStr (JNIEnv *env,jclass arg,jstring instringA,jstring instringB) { jstring str = (*env)->NewStringUTF(env,"I am chenyu,This is my first ubuntu jni!!!!"); return str; } /* * Class: com_ndk_test_JniClient * Method: AddInt * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_firstjni_JniClient_AddInt (JNIEnv *env,jint a,jint b) { return a + b; } #ifdef __cplusplus } #endif
此刻,当编辑com_ndk_test_JniClient.c并保存后,project下的—clean 一下工程,然后再去ndk-build项目,就可以生存响应的so文件
5.在MainActivity.java中完成对JniClient.java中函数的调用(首先静态加载动态链接so库):
package com.example.firstjni; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends ActionBarActivity { public String string1 = "I am chenyu "; public String string2 = "this is my first ubuntu jni"; public int a = 3; public int b = 5; static { System.loadLibrary("FirstJni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = new TextView(this); tv.setText(JniClient.AddStr(string1,string2)+"3 + 5 = " + JniClient.AddInt(a,b)); setContentView(tv); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main,menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button,so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
6.运行FirstJni工程,就出现了上面的爆图。