Android Studio 通過JNI機制和 ndk開發的C/C++ 互相溝通

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

可能.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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章