我們知道,Android架構中上層應用是以java來編寫的,而底層則用C/C++編寫。一般而言,上層android工程師在開發過程中,不會或很少涉及到C/C++層,但項目中一旦涉及到復雜的算法或耗時操作時(例如圖像處理等),通常使用C/C++完成算法實現並提供給java層(通過JNI)調用,以此提升軟件的運行效率。在這個過程中,C/C++所實現的代碼以及JNI調用相關的代碼被打包為.so庫,這即是所謂的目錄設備上的二進制動態庫(SHARED LIBRARY)。本文在android源碼平台(Ubuntu)下編寫了一個小程序:由上層JAVA代碼通過JNI調用底層C/C++代碼(.so庫),完成加法運算的操作。注意,對於不具備源碼環境的情況下,GOOGLE提供了NDK工具以完成C/C++層的開發,關於NDK配置使用不在本文討論范圍內。
1 JAVA層的開發
首先給出程序的運行效果圖,如下所示:
圖1 運行效果截圖
在兩個輸入框中分別輸入兩個數字(45,35),點擊"Confirm"則在上面顯示出運算結果(sum = 80)。此過程中,加法操作用C代碼實現。整個工程的根目錄路徑設置如下:
圖2 Helloworld根目錄
我們需要關注jni目錄,此目錄下包含著C/C++相關的代碼。
1.1 MainActivity.java
package com.eton.helloworld;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView tvSum;
private EditText etAdd1;
private EditText etAdd2;
private Button btnConfirm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvSum = (TextView) findViewById(R.id.tv_sum);
etAdd1 = (EditText) findViewById(R.id.et_add1);
etAdd2 = (EditText) findViewById(R.id.et_add2);
btnConfirm = (Button) findViewById(R.id.bt_Confirm);
System.loadLibrary("jnicall");
btnConfirm.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
int add1 = Integer.parseInt(etAdd1.getText().toString());
int add2 = Integer.parseInt(etAdd2.getText().toString());
tvSum.setText("sum = " + add(add1, add2));
}
});
}
public native int add(int add1, int add2);
}
代碼29行:顯式加載.so類庫--libjnicall--我們自己的類庫,注意,代碼中為"jnicall",對應的是類庫libjnicall.so;
代碼43行:通過關鍵字native聲明本地函數add,此函數為C/C++實現;
代碼37行:調用本地函數add。