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 <[email protected]>
* 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
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
);
}