lxj1137800599
勇敢地追
采纳率66.7%
2016-08-27 08:47 阅读 1.5k
已采纳

jni调用的函数和native函数不在一个java文件内,调用出错

问题描述如题。下来我贴代码:
这是含有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());这句话一直报错,错误提示也看不来究竟错在哪里

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

5条回答 默认 最新

  • 已采纳
    shihengzhen101 AlbertS 2016-08-27 09:59

    我看错了,这个obj代表的是ProgressBarOperation 的对象,你要想办法把MainActivity 的对象传进来或者可以取到,而不能直接去new一个

    点赞 评论 复制链接分享
  • shihengzhen101 AlbertS 2016-08-27 08:58

    你先看看这个clazz 有没有正确的取到,输出日志查一下

    点赞 评论 复制链接分享
  • shihengzhen101 AlbertS 2016-08-27 09:15

    这个主活动好像不能直接像这样jobject dpobj直接new一个对象,要用函数传进来的那个obj,就是函数JNIEXPORT void JNICALL Java_com_example_pressuretest_ProgressBarOperation_startMonitor(
    JNIEnv *env, jobject obj)
    的第二个参数

    点赞 评论 复制链接分享
  • lxj1137800599 勇敢地追 2016-08-27 09:27

    我现在再把我的问题补充一下

     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);。但是还是有问题

    点赞 评论 复制链接分享
  • luowenlong860502 媒体盒子 2016-08-29 05:27

    你这个写法完全有问题:
    你想在JNI里面回调Activity的方法,那你必须将activity的对象传到JNI里面去,而不是说在JNI里面去New一个Activity的对象,这样的话就不是同一个对象了

    我建议你将回调方法setPressure写到ProgressBarOperation 类里面,然后Activity再监听ProgressBarOperation的setPressure方法

    点赞 评论 复制链接分享

相关推荐