问题描述如题。下来我贴代码:
这是含有native函数的java文件
public class ProgressBarOperation {
static {
System.loadLibrary("Pressure");
}
public native void startMonitor();
public native void stopMonitor();
}
native函数所在的java文件不能继承Activity之类的。是我哪里搞错了还是什么原因,求大神解释。
接下来就是主文件,继承Activity的
public class MainActivity extends Activity implements OnClickListener {
private ProgressBar progressBar;
private ProgressBarOperation operation;
private Button btn_start, btn_stop;
static {
System.loadLibrary("Pressure");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
operation = new ProgressBarOperation();
btn_start = (Button)findViewById(R.id.btn_start);
btn_start.setOnClickListener(this);
btn_stop = (Button)findViewById(R.id.btn_stop);
btn_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_start) {
new Thread(new Runnable() {
@Override
public void run() {
operation.startMonitor();
}
}).start();
} else if (v.getId() == R.id.btn_stop) {
operation.stopMonitor();
}
}
public void setPressure(int pressure) {
Log.e("pressure", "" + pressure);
progressBar.setProgress(pressure);
}
}
接下来就是自己编写jni文件了。中间自动生成头文件就不说了
我把整个cpp文件全部贴过来
#include <jni.h>
#include <stdlib.h>
#include <unistd.h>
#include "com_example_pressuretest_ProgressBarOperation.h"
int getPressure() {
return rand() % 100;
}
int flag = JNI_TRUE;
JNIEXPORT void JNICALL Java_com_example_pressuretest_ProgressBarOperation_startMonitor(
JNIEnv *env, jobject obj) {
while (flag) {
sleep(1);
//拿到字节码对象
jclass clazz = env->FindClass("com/example/pressuretest/MainActivity");
jmethodID methodId = env->GetMethodID(clazz, "setPressure", "(I)V");
jobject dpobj= env->NewObject(clazz, methodId);
env->CallVoidMethod(dpobj, methodId, getPressure());
}
}
JNIEXPORT void JNICALL Java_com_example_pressuretest_ProgressBarOperation_stopMonitor(
JNIEnv *env, jobject obj) {
flag = JNI_FALSE;
}
env->CallVoidMethod(dpobj, methodId, getPressure());这句话一直报错,错误提示也看不来究竟错在哪里
我看错了,这个obj代表的是ProgressBarOperation 的对象,你要想办法把MainActivity 的对象传进来或者可以取到,而不能直接去new一个
你先看看这个clazz 有没有正确的取到,输出日志查一下
这个主活动好像不能直接像这样jobject dpobj
直接new一个对象,要用函数传进来的那个obj,就是函数JNIEXPORT void JNICALL Java_com_example_pressuretest_ProgressBarOperation_startMonitor(
的第二个参数
JNIEnv *env, jobject obj)
我现在再把我的问题补充一下
JNIEXPORT void JNICALL Java_com_example_pressuretest_ProgressBarOperation_startMonitor(
JNIEnv *env, jobject obj) {
while (flag) {
sleep(1);
//静态方法
//jclass clazz = env->FindClass("com/example/pressuretest/MainActivity");
//jmethodID methodId = env->GetStaticMethodID(clazz, "set", "(I)V");
//env->CallStaticVoidMethod(clazz, methodId, getPressure());
//非静态方法
jclass clazz = env->FindClass("com/example/pressuretest/MainActivity");
jmethodID methodId = env->GetMethodID(clazz, "setPressure", "(I)V");
jobject dpobj = env->NewObject(clazz, methodId);
env->CallVoidMethod(obj, methodId, getPressure());
}
}
在MainActivity里面重新定义了两个方法
public void setPressure(int pressure) {
Log.e("pressure", "" + pressure);
progressBar.setProgress(pressure);
}
public static void set(int pressure) {
Log.e("pressure", "" + pressure);
}
静态方法的调用没有问题,有log显示。非静态的就不行,《android开发与艺术探索》中提到的“非静态只是多了一步构造对象的过程”,它没有具体说明怎么构造,所以我就自己构造了一个jobject dpobj = env->NewObject(clazz, methodId);。但是还是有问题
你这个写法完全有问题:
你想在JNI里面回调Activity的方法,那你必须将activity的对象传到JNI里面去,而不是说在JNI里面去New一个Activity的对象,这样的话就不是同一个对象了
我建议你将回调方法setPressure写到ProgressBarOperation 类里面,然后Activity再监听ProgressBarOperation的setPressure方法