Android Studio 通过JNI机制和 ndk开发的C/C++沟通的具体步骤 (以图像模糊化为例)
1、编写包含native本地方法的java类
2、通过javah工具生成C/C++语言的头文件
3、使用C/C++语言实现头文件
4、使用交叉编译工具对C/C++本地代码进行编译,最后通过链接生成*.so可执行的C/C++库
5、实际执行Java代码去和本地的C/C++代码互相沟通
Step1: 配置NDK相关信息
1.在local.properties文件中 添加ndk路径
sdk.dir=D\:\\Users\\yangguangbaoxian\\AppData\\Local\\Android\\sdk
ndk.dir=D\:\\ndk\\android-ndk-r10d
2.在build.gradle文件的defaultConfig分支中添加.os文件名的相应信息
ndk {
moduleName "genius_blur"
ldLibs "log", "z", "m", "jnigraphics"
abiFilters "armeabi", "armeabi-v7a", "x86"
}
3.在gradle.properties文件中 添加 android.useDeprecatedNdk=true 语句
Step2: 在JAVA类中添加native接口
代码如下;
/*
* Copyright (C) 2016 Qiujuer <qiujuer@live.cn>
* WebSite http://www.qiujuer.net
* Created 05/28/2015
* Changed 1/10/2015
* Version 1.0.0
*
* 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.
*/
package com.cloudhome.jni_project;
import android.graphics.Bitmap;
/**
* This use jni blur bitmap and pixels
* Blur arithmetic is StackBlur
*/
public class StackNative {
/**
* Load genius jni file
*/
static {
System.loadLibrary("genius_blur");//调用的.os文件要与生成的文件名保持一致
}
/**
* Blur Image By Pixels
*
* @param img Img pixel array
* @param w Img width
* @param h Img height
* @param r Blur radius
*/
protected static native void blurPixels(int[] img, int w, int h, int r);
/**
* Blur Image By Bitmap
*
* @param bitmap Img Bitmap
* @param r Blur radius
*/
protected static native void blurBitmap(Bitmap bitmap, int r);
}
Step3: 执行Build->Make Project检查native类是否生成一些.class文件
验证工程中并无其它错误,并对工程进行了编译,在上图的路径(debug)中生成了一些.class文件
Step4: 通过javah工具生成C/C++语言的头文件.h
打开Terminal输入指令窗口 依次点击"View->Tool Windows->Terminal"
1.首先进入src\main文件中。
命令 cd jin_blur1\src\main (jin_blur1是我的module名)
2.生成StackNative.java(native 接口所在的类) 对应的.h文件。
命令
javah -d jni -classpath D:\ide\android-sdk\platforms\android-22\android.jar;D:\ide\android-sdk\extras\android\support\v4\android-support-v4.jar;D:\ide\android-sdk\extras\android\sup
port\v7\appcompat\libs\android-support-v7-appcompat.jar;..\..\build\intermediates\classes\debug com.cloudhome.jni_project.StackNative
注意:如果有用到android-support-v4.jar;android-support-v7-appcompat.jar;就要另外加入D:\ide\android-sdk\extras\android\support\v4\android-support-v4.jar;D:\ide\android-sdk\extras\android\sup
port\v7\appcompat\libs\android-support-v7-appcompat.jar;
否则会报 找不到android.support.v7.app.AppCompatActivity的错
会在jni文件夹中生成.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_cloudhome_jni_project_StackNative */
#ifndef _Included_com_cloudhome_jni_project_StackNative
#define _Included_com_cloudhome_jni_project_StackNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_cloudhome_jni_project_StackNative
* Method: blurPixels
* Signature: ([IIII)V
*/
JNIEXPORT void JNICALL Java_com_cloudhome_jni_1project_StackNative_blurPixels
(JNIEnv *, jclass, jintArray, jint, jint, jint);
/*
* Class: com_cloudhome_jni_project_StackNative
* Method: blurBitmap
* Signature: (Landroid/graphics/Bitmap;I)V
*/
JNIEXPORT void JNICALL Java_com_cloudhome_jni_1project_StackNative_blurBitmap
(JNIEnv *, jclass, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif
可能.h文件会出险错误提示,一般不用担心。刚开始编译器对.c文件格式不支持,编译后就好了
Step5:根据生成的.h文件编写相应的.C/C++文件
在同一个jni文件夹下 自定义名字 com_cloudhome_jni_project_StackNative.c文件 用return返回数据
这里主要调用了另外一个头文件stackblur.h 和.c文件stackblur.c(模糊化图片主函数)
#include <android/bitmap.h>
#include <stackblur.h>
#include "stackblur.h"
JNIEXPORT void JNICALL
Java_com_cloudhome_jni_1project_StackNative_blurPixels
(JNIEnv
*env,
jclass obj, jintArray
arrIn,
jint w, jint
h,
jint r
)
{
jint *pix;
// cpp:
// pix = (env)->GetIntArrayElements(arrIn, 0);
pix = (*env)->GetIntArrayElements(env, arrIn, 0);
if (pix == NULL)
return;
// Start
pix = blur(pix, w, h, r);
// End
// if return:
// int size = w * h;
// jintArray result = env->NewIntArray(size);
// env->SetIntArrayRegion(result, 0, size, pix);
// cpp:
// (env)->ReleaseIntArrayElements(arrIn, pix, 0);
(*env)->
ReleaseIntArrayElements(env, arrIn, pix,
0);
// return result;
}
JNIEXPORT void JNICALL
Java_com_cloudhome_jni_1project_StackNative_blurBitmap
(JNIEnv
*env,
jclass obj, jobject
bitmapIn,
jint r
)
{
AndroidBitmapInfo infoIn;
void *pixelsIn;
int ret;
// Get image info
if ((
ret = AndroidBitmap_getInfo(env, bitmapIn, &infoIn)
) != 0)
return;
// Check image
if (infoIn.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
return;
// Lock all images
if ((
ret = AndroidBitmap_lockPixels(env, bitmapIn, &pixelsIn)
) != 0) {
//AndroidBitmap_lockPixels failed!
return;
}
// height width
int h = infoIn.height;
int w = infoIn.width;
// Start
pixelsIn = blur((int *) pixelsIn, w, h, r);
// End
// Unlocks everything
AndroidBitmap_unlockPixels(env, bitmapIn
);
}
到了这里,再执行一个"Build->Make Project 生成.os文件
如图,在"armeabi", "armeabi-v7a", "x86"文件夹中 生成了.so文件
Step5: 点run 安装运行
安装后结果
图片模糊化后的效果
参考文献
1.http://blog.csdn.net/sodino/article/details/41946607
2.http://blog.csdn.net/qiujuer/article/details/24282047