1. 程式人生 > >Android進階之路(三) -- JNI互動

Android進階之路(三) -- JNI互動

今天繼續學習C與Java通過JNIEnv互動。

昨天學習了C與Java互動方法,但感覺太輕鬆了,就像呼叫findViewById一樣簡單,可能是我遺漏了什麼東西,於是就想在今天繼續研究這一塊兒的內容,順便做一下總結。

C呼叫Java的方法和訪問Java中的變數都是通過JNIEnv進行的,它提供了一堆方法用來定位、呼叫方法和定位、讀取變數:

定位方法,如下:
GetFieldID(jclass clazz, const char* name, const char* sig);     	//獲取非靜態成員變數的Id
GetStaticFieldID(jclass clazz, const char* name, const char* sig);  	//獲取靜態成員變數的Id
GetMethodID(jclass clazz, const char* name, const char* sig);   	//獲取非靜態方法的Id
GetStaticMethodID(jclass clazz, const char* name, const char* sig);   	//獲取靜態方法的Id
它們都是通過變數名/方法名和簽名(簽名規則見前一章)來獲取ID的。

讀取和呼叫方法,如下:

GetXxxField(jobject obj, jfieldID fieldID);                                     //讀取非靜態成員變數的值
GetStaticXxxField(jclass clazz, jfieldID fieldID);			        //讀取靜態成員變數的值
CallXxxMethod(jobject obj, jmethodID methodID, ...)			        //呼叫非靜態方法
CallStaticXxxMethod(jclass clazz, jmethodID methodID, ...)		        //呼叫靜態方法
它們都是類/物件和剛才確定的ID實現讀取和呼叫的。

現在就用它們來實現一個影象處理的效果,其實也很簡單,Java層把影象矩陣傳給C層,C對影象進行處理,為了體現讀取變數和呼叫方法,影象矩陣就不以引數形式提供給C層,而在C層分別通過讀取成員變數和呼叫成員方法來獲取影象矩陣。

定義工具類:
public class ColorConvertHelper {
    static {
        System.loadLibrary("native-lib");
    }

    private int[] mColorMatrix;

    //設定影象矩陣
    public void setMatrix(int[] colorMatrix){
        mColorMatrix = colorMatrix;
    }

    //獲取影象矩陣
    public int[] getMatrix(){
        return mColorMatrix;
    }

    public ColorConvertHelper(int[] matrix){
        mColorMatrix = matrix;
    }
    //處理影象,values為處理的值,w、h為影象寬和高
    public native int[] changeColorMatrix(int values,int w,int h);
}

public native int[] changeColorMatrix(int values,int w,int h);中的values是通過Seekbar傳給自定義的ImageView的,這個方法在ImageView中呼叫,並且獲得返回結果後會呼叫重新整理方法,在OnDraw裡將返回結果設定給新的bitmap,再進行繪製,有興趣的可以自己動手試試,這裡就不貼程式碼了,寫得真的亂。

在C層實現該方法

#include <jni.h>
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_tustcs_ndktest_ColorConvertHelper_changeColorMatrix(JNIEnv *env, jobject instance, jint values,int w ,int h) {
    jclass mClass = env->GetObjectClass(instance);                                  //獲取當前型別

    //獲取矩陣的方法一:通過直接訪問物件成員變數獲取
    jfieldID mFieldId = env->GetFieldID(mClass,"mColorMatrix","[I");              //獲取成員變數ID
    jintArray mArray = (jintArray)env->GetObjectField(instance,mFieldId);         //強轉得到陣列型別
    // 獲取矩陣的方法二:通過直接訪問物件的get方法獲取
//    jmethodID mMethodId = env->GetMethodID(mClass,"getMatrix","()[I");              //獲取方法ID
//    jintArray mArray = (jintArray)env->CallObjectMethod(instance,mMethodId);        //強轉得到陣列型別

    int * array = env->GetIntArrayElements(mArray,NULL);

    jsize size = env->GetArrayLength(mArray);

    int alpha = 0xFF << 24;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            int color = array[w * i + j];
            int red = ((color & 0x00FF0000) >> 16);
            int green = ((color & 0x0000FF00) >> 8);
            int blue = color & 0x000000FF;
            red = red - values;
            green = green - values;
            blue = blue - values;
            color = alpha | (red << 16) | (green << 8) | blue;
            array[w * i + j] = color;
        }
    }
    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result, 0, size, array);
    env->ReleaseIntArrayElements(mArray, array, 0);
    return result;
}

這裡分別使用了呼叫方法和讀取成員變數這兩種方式來獲取影象矩陣。

程式碼寫到這裡花了不少時間,筆者看到env->GetIntArrayElements(mArray,NULL);方法就想當然的認為有提供類似env->GetIntArrayField(instance,mFieldId); 的方法,事實上並沒有,C層直接獲取Java層的陣列類需要通過env->GetObjectField(instance,mFieldId);然後進行強制型別轉換才能得到。這裡是對影象矩陣做了亂七八糟的處理,我也不知道這叫什麼效果。


相關推薦

Android -- JNI互動

今天繼續學習C與Java通過JNIEnv互動。昨天學習了C與Java互動方法,但感覺太輕鬆了,就像呼叫findViewById一樣簡單,可能是我遺漏了什麼東西,於是就想在今天繼續研究這一塊兒的內容,順便做一下總結。C呼叫Java的方法和訪問Java中的變數都是通過JNIEnv

JavaScript的引用類型Object類型和Array類型

reverse 代碼 -1 替換 fine 設置 sha unshift sum 引用類型 Object類型 function a(num){ if(num>3){ a(--num); } console.log(num);

Android -- AS 3.0NDK環境搭建及hello world

通過一段找實習的經歷,以及快應用、小程式、web app等移動開發模式的衝擊,深深為安卓原生開發的未來感到擔憂,希望接入人工智慧API和物聯網井噴能給安卓開發帶來新的生機吧。當然,作為小白我是不用擔心這麼多的,做自己喜歡的事就好了,於是拋開雜念,繼續學習安卓。NDK開發環境的

Android -- NDK初探

繼續學習NDK開發,今天來實現一個簡單的計算器功能,NativeUtil類中有一個靜態的native方法,它接收三個引數,分別是兩個運算元和一個操作符,並且返回C的計算結果。NativeUtil類定義如下public class NativeUtil { static

React

之前的文章我們介紹了 React 建立元件、JSX 語法、繫結資料和繫結物件。接下來我們將介紹 React 繫結屬性( 繫結class  繫結style)、引入圖片  迴圈陣列渲染資料。 上一篇中我們在 components 目錄中建立了 Home.js 元件並將其掛在到了 A

koa2 從入門到

之前的文章我們介紹了一下 koa 路由,get 傳值,動態路由,本節我們看一下 koa 中介軟體 以及 koa 中介軟體的洋蔥圖執行流程。 一、什麼是 Koa 的中介軟體 通俗的講:中介軟體就是匹配路由之前或者匹配路由完成做的一系列的操作,我們就可以把它叫做中介軟體。

Python 從入門到

在之前的文章我們介紹了一下 Python 中 if while for 的使用,本章我們來看一下 Python 中的變數型別。 在 Python 定義變數時的規則是 變數名 = 變數 ,Python 中的變數賦值不需要型別宣告。每個變數在記憶體中建立,都包括變數的標識,名稱和資料這些資訊。每個變數在使用前都

Python 爬蟲從入門到

之前的文章我們做了一個簡單的例子爬取了百度首頁的 html,本篇文章我們再來看一下 Get 和 Post 請求。 在說 Get 和 Post 請求之前,我們先來看一下 url 的編碼和解碼,我們在瀏覽器的連結裡如果輸入有中文的話,如:https://www.baidu.com/s?wd=貼吧,那麼瀏覽器會自

Java 從入門到

之前的文章我們介紹了 Java 中的變數和基本資料型別,本章我們來看一下 Java 的運算子和表示式。 計算機的最基本用途之一就是執行數學運算,作為一門計算機語言,Java也提供了一套豐富的運算子來操縱變數。我們可以把運算子分成以下幾組: 算術運算子 關係運算符 位運算子 邏輯運算子 賦值運算

Android 我的部落格文章目錄

為了方便讀者閱讀以及自己回顧,總結寫過的文章和一些想要寫的文章目錄如下: #1.Java 反射: 集合: 異常 IO / NIO #2.資料結構與演算法 資料結構: 演算法: #3.設計模式 #4.架構設計 MVC 的思路與實現 MVP 的

JavaScript的函數簡介,變量、作用域和內存問題

ret 優化 person get 簡介 web瀏覽器 都是 add 是把 <h3>ECMAScript中函數不存在函數簽名的概念,沒有重載</h3><h3>無需指定返回值,可以在任何時候返回任何值。未指定返回值的函數,返回的是一個特殊

慕課 從零到一spark

1.RDD RDD是spark特有的資料模型,談到RDD就會提到什麼彈性分散式資料集,什麼有向無環圖,本文暫時不去展開這些高深概念。 (0)隨便找個點理解以下 最重要的記住,RRD是不可變的,也就是說,已有的RDD不能被修改或者更新,但可以從已有的RDD轉化成一個新的RDD. 上面的

Java小白

1、字串操作:replace方法(舊字串,新子串)。 Scanner scanner = new Scanner(System.in); System.out.println("請輸入"); // 接收使用者的輸入的字串 String s1 = scanner.next(); // 接受整型 i

C#反射的應用

  反射在C#中的應用還是很多的,但它對程式碼的效能有一定影響。 反射的效能:   使用反射來呼叫型別或者觸發方法,或者訪問一個欄位或者屬性時clr 需要做更多的工作:校驗引數,檢查許可權等等,所以速度是非常慢的。所以儘量不要使用反射進行程式設計,對於打算編寫一個動態構造型別(晚繫結)的應用程

Python基礎元組、字典和字符串

python基礎 tag 基礎 block 場景 分隔 應用場景 agg bsp 元組 元組的定義 Tuple(元組)與列表類似,不同之處在於元組的 元素不能修改 元組 表示多個元素組成的序列 元組 在 Python 開發中,有特定的應用場景 用

Python基礎元組、字典和字串

元組 元組的定義   Tuple(元組)與列表類似,不同之處在於元組的 元素不能修改     元組 表示多個元素組成的序列   元組 在 Python 開發中,有特定的應用場景   用於儲存 一串 資訊,資料 之間使用

Python基礎字串

字串 字串的定義 字串 就是 一串字元,是程式語言中表示文字的資料型別 在 Python 中可以使用 一對雙引號 " 或者 一對單引號 ' 定義一個字串 雖然可以使用 \" 或者 \' 做字串的轉義,但是在實際開發中: 如果字串內部需要使用 ",可以使用 ' 定義字串 如果字串內部需要使用

Hadoop3——Hadoop檔案系統

Hadoop有一個抽象的檔案系統概念,HDFS只是其中的一個實現。Java抽象類org.apache.hadoop.fs.FileSystem定義了Hadoop中的一個檔案系統介面,並且該抽象類有幾個具體實現。 Hadoop檔案系統 檔案系統 URI方案 Ja

Linux:部署

經過長期的開發工作,在專案中經常會需要將打包好的專案部署到Linux伺服器上,不過,在此之前需要掌握一些Linux常用命令比如ls、ll、ps -ef|grep java 、cp、tail 等等,詳細的可以百度查一下,還是很多的。接下來,就說一下關於專案的部署。 首先需要一個遠端訪問Linu

Pandas使用DataFrame進行資料分析比賽:日期資料處理:按日期篩選、顯示及統計資料

首先,表格的資料格式如下: 1、獲取某年某月資料 data_train = pd.read_csv('data/train.csv') # 將資料型別轉換為日期型別 data_train[