基礎樣例
這部分才是重點?。《嗝辞蓄}。直接先看下運行的東西咯^^
是不是更有看的動力了,?還是你拉到下邊直接下載去了==。(沒被鄙視簡單吧T^T)
1)C部分
1.1)TestJni.h
-
/*
-
* TestJni.h
-
*
-
* Created on: 2011-12-20
-
* Author: Join
-
*/
-
-
#ifndef TESTJNI_H_
-
#define TESTJNI_H_
-
-
#include <jni.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <android/log.h>
-
#include <android/bitmap.h>
-
-
// 測試回調(diào)Java
-
#include "CallJava.h"
-
-
#define LOG_TAG "JNI_DEBUG"
-
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
-
// JNI調(diào)用函數(shù)必須要用C編譯器編譯
-
// C++不加extern "C",,調(diào)用會有異常
-
#ifdef __cplusplus
-
extern
"C"
{
-
#endif
-
-
/*
-
* 說明:
-
* 1,、JNIEXPORT、JNICALL:jni的宏,,在android的jni中不必須
-
* 2,、jstring:返回值類型(對應java的jni基本類型)
-
* 3、C方法名:Java_pacakege_class_method
-
* 4,、JNIEnv*,、jobject:jni必要參數(shù)(分別表示jni環(huán)境、java對象)
-
*/
-
// 樣例1:獲取字符串
-
JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_getStr(JNIEnv*,
-
jobject);
-
// 樣例2:C回調(diào)Java靜態(tài)及非靜態(tài)方法
-
JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_callJava(JNIEnv*,
-
jobject,
int
,
int
,
int
,
int
);
-
// 樣例3:灰度化圖像(Bitmap作為參數(shù))(注:android-8才提供Bitmap.h)
-
JNIEXPORT
void
JNICALL Java_org_join_ndk_jni_TestJni_convertToGray(JNIEnv*,
-
jobject, jobject);
-
-
// 樣例4:缺少JNIEXPORT,、JNICALL測試
-
jintArray Java_org_join_ndk_jni_TestJni_getIntArray(JNIEnv*, jobject);
-
-
// 樣例5:C方法不按規(guī)則命名嘗試
-
jint getInt(JNIEnv*, jobject);
-
-
#ifdef __cplusplus
-
}
-
#endif
-
-
// C++調(diào)用C
-
//extern "C" {
-
//#include "ImageUtil.h"
-
//}
-
-
//標準頭文件為何有如下結(jié)構(gòu),?
-
//#ifdef __cplusplus
-
//extern "C" {
-
//#endif
-
//...
-
//#ifdef __cplusplus
-
//}
-
//#endif
-
-
#endif /* TESTJNI_H_ */
1.2)TestJni.cpp
-
/*
-
* TestJni.cpp
-
*
-
* Created on: 2011-12-20
-
* Author: Join
-
*/
-
-
#include "TestJni.h"
-
-
// 樣例1:獲取字符串
-
JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_getStr(JNIEnv *env,
-
jobject obj) {
-
return
env->NewStringUTF(
"I'm from C!"
);
-
}
-
-
int
min(
int
x,
int
y) {
-
return
(x <= y) ? x : y;
-
}
-
-
// 樣例2:C回調(diào)Java靜態(tài)及非靜態(tài)方法
-
JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_callJava(JNIEnv *env,
-
jobject obj,
int
add_x,
int
add_y,
int
sub_x,
int
sub_y) {
-
char
str[128];
// 字符數(shù)組
-
int
result_add = add(env, add_x, add_y);
// 回調(diào)Java靜態(tài)方法求和
-
LOGE(
"==[%d+%d=%d]=="
, add_x, add_y, result_add);
-
int
result_sub = sub(env, sub_x, sub_y);
// 回調(diào)Java非靜態(tài)方法求差
-
LOGE(
"==[%d-%d=%d]=="
, sub_x, sub_y, result_sub);
-
// 將比較得的整數(shù)轉(zhuǎn)成字符串
-
sprintf(str,
"Hello, I'm Join! min=%d"
, min(result_add, result_sub));
-
return
env->NewStringUTF(str);
-
}
-
-
typedef
struct
{
-
uint8_t red;
-
uint8_t green;
-
uint8_t blue;
-
uint8_t alpha;
-
} argb;
-
-
// 樣例3:灰度化圖像(Bitmap作為參數(shù))(注:android-8才提供Bitmap.h)
-
/**
-
* bitmap:ARGB_8888,32位ARGB位圖
-
*/
-
JNIEXPORT
void
JNICALL Java_org_join_ndk_jni_TestJni_convertToGray(JNIEnv * env,
-
jobject obj, jobject bitmap) {
-
AndroidBitmapInfo info;
-
void
* pixels;
-
int
ret;
-
-
LOGI(
"convertToGray"
);
-
if
((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
-
LOGE(
"AndroidBitmap_getInfo() failed ! error=%d"
, ret);
-
return
;
-
}
-
-
LOGI(
-
"color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d"
, info.width, info.height, info.stride, info.format, info.flags);
-
if
(info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
-
LOGE(
"Bitmap format is not RGBA_8888 !"
);
-
return
;
-
}
-
-
if
((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
-
LOGE(
"AndroidBitmap_lockPixels() failed ! error=%d"
, ret);
-
}
-
-
// modify pixels with image processing algorithm
-
-
int
x, y;
-
uint8_t gray;
-
for
(y = 0; y < info.height; y++) {
-
argb * line = (argb *) pixels;
-
for
(x = 0; x < info.width; x++) {
-
gray = 0.3 * line[x].red + 0.59 * line[x].green
-
+ 0.11 * line[x].blue;
-
line[x].red = line[x].green = line[x].blue = gray;
-
// line[x].alpha = 0xff; // 完全不透明
-
}
-
-
pixels = (
char
*) pixels + info.stride;
-
}
-
-
LOGI(
"unlocking pixels"
);
-
AndroidBitmap_unlockPixels(env, bitmap);
-
-
}
-
-
// 樣例4:缺少JNIEXPORT,、JNICALL測試
-
jintArray Java_org_join_ndk_jni_TestJni_getIntArray(JNIEnv *env, jobject obj) {
-
int
array[] = { 12, 34 };
// 新建一個int[]
-
jintArray result = env->NewIntArray(2);
// 新建一個jintArray
-
env->SetIntArrayRegion(result, 0, 2, array);
// 將int[]存入result
-
return
result;
-
}
-
-
// 樣例5:C方法不按規(guī)則命名嘗試
-
jint getInt(JNIEnv *env, jobject obj) {
-
return
256;
-
}
1.3)回調(diào)相關
參照我的
Java JNI簡單實現(xiàn)
一文,,講了些jni注意點的吧?
2)Java部分
2.1)TestJni
-
public
class
TestJni {
-
-
/** TAG標識 */
-
private
static
final
String TAG =
"TestJni"
;
-
-
/**
-
* 載入動態(tài)庫
-
*/
-
static
{
-
System.loadLibrary(
"TestJni"
);
-
}
-
-
/** 樣例1:獲取字符串 */
-
public
static
native
String getStr();
-
-
/** C回調(diào)Java方法(靜態(tài)) */
-
public
static
int
add(
int
x,
int
y) {
-
Log.e(TAG,
"==Java靜態(tài)add方法=="
);
-
return
x + y;
-
}
-
-
/** C回調(diào)Java方法(非靜態(tài)) */
-
public
int
sub(
int
x,
int
y) {
-
Log.e(TAG,
"==Java非靜態(tài)sub方法=="
);
-
return
x - y;
-
}
-
-
/** 樣例2:C回調(diào)Java靜態(tài)及非靜態(tài)方法 */
-
public
static
native
String callJava(
int
add_x,
int
add_y,
int
sub_x,
-
int
sub_y);
-
-
-
public
static
native
void
convertToGray(Bitmap bitmap);
-
-
/** 樣例4:缺少JNIEXPORT,、JNICALL測試 */
-
public
static
native
int
[] getIntArray();
-
-
/** 樣例5:C方法不按規(guī)則命名嘗試 */
-
public
static
native
int
getInt();
-
-
}
2.2)AndroidNDKActivity
-
public
class
AndroidNDKActivity
extends
Activity
implements
-
View.OnClickListener {
-
-
/** 標簽 */
-
private
TextView text;
-
-
/** 按鈕 */
-
private
Button btn1, btn2, btn3, btn4, btn5;
-
-
/** 圖像 */
-
private
ImageView imageView;
-
-
@Override
-
public
void
onCreate(Bundle savedInstanceState) {
-
super
.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
-
/* 初始化話各組件 */
-
text = (TextView) findViewById(R.id.text);
-
btn1 = (Button) findViewById(R.id.btn1);
-
btn1.setOnClickListener(
this
);
-
btn2 = (Button) findViewById(R.id.btn2);
-
btn2.setOnClickListener(
this
);
-
btn3 = (Button) findViewById(R.id.btn3);
-
btn3.setOnClickListener(
this
);
-
btn4 = (Button) findViewById(R.id.btn4);
-
btn4.setOnClickListener(
this
);
-
btn5 = (Button) findViewById(R.id.btn5);
-
btn5.setOnClickListener(
this
);
-
imageView = (ImageView) findViewById(R.id.imageView);
-
}
-
-
@Override
-
public
void
onClick(View v) {
-
switch
(v.getId()) {
-
case
R.id.btn1:
-
// 樣例1:獲取字符串
-
text.setText(TestJni.getStr());
-
break
;
-
case
R.id.btn2:
-
// 樣例2:C回調(diào)Java靜態(tài)及非靜態(tài)方法
-
text.setText(TestJni.callJava(
2
,
5
,
8
,
3
));
-
break
;
-
case
R.id.btn3:
-
// 獲得Bitmap資源(32位)
-
// BitmapFactory.Options options = new BitmapFactory.Options();
-
// options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
// Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
-
// R.drawable.ic_launcher, options);
-
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
-
R.drawable.ic_launcher);
-
// 樣例3:灰度化圖像(Bitmap作為參數(shù))
-
TestJni.convertToGray(bitmap);
-
imageView.setImageBitmap(bitmap);
-
break
;
-
case
R.id.btn4:
-
// 樣例4:缺少JNIEXPORT,、JNICALL測試
-
int
[] array = TestJni.getIntArray();
-
int
len = array.length;
-
StringBuffer sb =
new
StringBuffer();
-
for
(
int
i =
0
; i < len -
1
; i++) {
-
sb.append(array[i]);
-
sb.append(
","
);
-
}
-
sb.append(array[len -
1
]);
-
text.setText(sb.toString());
-
break
;
-
case
R.id.btn5:
-
// 樣例5:C方法不按規(guī)則命名嘗試
-
try
{
-
int
value = TestJni.getInt();
-
text.setText(String.valueOf(value));
-
}
catch
(UnsatisfiedLinkError e) {
-
text.setText(
"UnsatisfiedLinkError!"
);
-
e.printStackTrace();
-
}
-
break
;
-
}
-
}
-
}
三、后記
也是整理的基礎樣例工程,,嘿嘿,!
注意:
1)需要2.2系統(tǒng)才可,用了Bitmap.h,。
2)樣例5(不按命名規(guī)則的那個),,用jni對方法進行注冊,不按要求寫方法名也是可以的,。
3)灰度化是用的標準公式:Gray = R*0.299 + G*0.587 + B*0.114(考慮效率的話,,有移位公式)
4)在android-ndk-r6\platforms\android-8\arch-arm\usr\lib目錄下是NDK提供的可調(diào)用庫。(有OpenGL ES^^)
另一個實例,,jni調(diào)用java的方法:
給出兩個點的坐標,,求它們的距離。
首先,,創(chuàng)建一個Point對象,,
Java代碼
-
public class Point {
-
float x;
-
float y;
-
}
-
-
然后在c文件中定義一個函數(shù)
C代碼
-
jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b){}
返回值是float,在jni中定義的是jfloat。
函數(shù)名規(guī)則: Java開頭,,接著是包名的每一段,,然后是類名,最后是Java中調(diào)用的方法名,,中間都用下劃線隔開,。第一個參數(shù)JNIEnv* env和第二個參數(shù)jobject thiz都是必須的,后面的才是Java中傳遞進來的參數(shù),。這里是兩個Point對象,。
首先確定要做的步驟:
◆找到這個Point類
◆找到類中的域x和y的域id
◆根據(jù)ID取出x和y的值
◆計算結(jié)果并返回
那么代碼如下:
Java代碼
-
#include
<
jni.h
>
-
#include
<
math.h
>
-
#include
<
android
/log.h
>
-
-
jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b)
-
{
-
//步驟1
-
jclass
point_class
= (*env)-
>
FindClass(env, "chroya/demo/ndk/Point");
-
if(
point_class
== NULL) {
-
//printf("class not found");
-
__android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "class Point not found");
-
return 0;
-
} else {
-
__android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "found class Point");
-
}
-
//步驟2
-
jfieldID
field_x
= (*env)-
>
GetFieldID(env, point_class, "x", "F");
-
jfieldID
field_y
= (*env)-
>
GetFieldID(env, point_class, "y", "F");
-
//步驟3
-
jfloat
ax
= (*env)-
>
GetFloatField(env, a, field_x);
-
jfloat
ay
= (*env)-
>
GetFloatField(env, a, field_y);
-
jfloat
bx
= (*env)-
>
GetFloatField(env, b, field_x);
-
jfloat
by
= (*env)-
>
GetFloatField(env, b, field_y);
-
//步驟4
-
return sqrtf(powf(bx-ax, 2) + powf(by-ay, 2));
-
}
-
然后在Java里面調(diào)用:
Java代碼
-
public class Main extends Activity {
-
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
TextView
tv
=
new
TextView(getApplicationContext());
-
Point
a
=
new
Point();
-
a.x
=
3
;
-
a.y
=
3
;
-
-
Point
b
=
new
Point();
-
b.x
=
5
;
-
b.y
=
5
;
-
-
float
d
=
distance
(a,b);
-
tv.setText("distance(a,b):"+d);
-
setContentView(tv);
-
}
-
-
public native float distance(Point a, Point b);
-
-
static {
-
System.loadLibrary("demo");
-
}
-
}
-
轉(zhuǎn)自:
http://vaero.blog.51cto.com/4350852/782787
http://mobile.51cto.com/android-218239.htm
|