jni不通过线程c回调java的函数

整个工程的项目如下:

1、项目的思路是在activity中启动MyService这个服务,在服务中调用

JniScsManger类中的本地方法startNativeScsService,在
startNativeScsService的c代码实现中回调JniScsManger中的scsConnectStatus方法。下面我们来看下两种代码的实现:
package com.cetcs.ecmapplication.jni.scs;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        JniScsManger.getInstances().startNativeScsService();
    }
}

activity的代码:

package im.weiyuan.com.jni2;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import com.cetcs.ecmapplication.jni.scs.JniScsManger;
import com.cetcs.ecmapplication.jni.scs.MyService;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(MainActivity.this, MyService.class);
        startService(intent);
    }
}
package com.cetcs.ecmapplication.jni.scs;

import android.util.Log;

/**
 * Created by wei.yuan on 2017/6/7.
 */

public class JniScsManger {
    static {
        System.loadLibrary("jniscs");
    }

    private  static JniScsManger jniScsManger = null;
    private JniScsManger(){

    }

    public static JniScsManger getInstances(){
        if(jniScsManger == null){
            jniScsManger = new JniScsManger();
        }
        return  jniScsManger;
    }

    public native int startNativeScsService();

    public  void  scsConnectStatus(int status,String reason){

        Log.d("123456",""+status+","+reason);

    }

    public  void getScsStatus(){
        Log.d("123456",""+",");
    }

    public int onProgressCallBack(long total, long already) {
        //自行执行回调后的操作
        Log.d("123456",""+"onProgressCallBack");
        System.out.println("total123456:"+total);
        System.out.println("already:"+already);
        return 1;
    }

}

我们来看看本地native层实现的代码:

第一种方式:

//
// Created by wei.yuan on 2017/6/7.
//
#include <android/log.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <dlfcn.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <assert.h>
#include <android\log.h>
#include <errno.h>
#include <pthread.h>

#include "com_cetcs_ecmapplication_jni_scs_JniScsManger.h"
//动态链接库路径
#define LIB_SCS_PATH "libServerCenter.so"
#define LOG_TAG "SCS123456"
#define LOGI_JniSCS(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT jint JNICALL Java_com_cetcs_ecmapplication_jni_scs_JniScsManger_startNativeScsService(JNIEnv * env, jobject jobj){
    LOGI_JniSCS("start native ServerCenterService");

    //jobj对象就是java层调用startNativeScsService的对象,那个类调用startNativeScsService对应的jobj就是那个对象
    jclass javaClass = (*env)->FindClass(env, "com/cetcs/ecmapplication/jni/scs/JniScsManger");
    if (javaClass == 0) {
              LOGI_JniSCS("Unable to find class");
            return;
        }
        //获取要回调的方法ID
        jmethodID javaCallbackId = (*env)->GetMethodID(env, javaClass,"scsConnectStatus", "(ILjava/lang/String;)V");
        if (javaCallbackId == NULL) {
             LOGI_JniSCS("Unable to find method:onProgressCallBack");
            return;
        }
        //执行回调,注意第二个参数是jobj,不是javaClass
            (*env)->CallVoidMethod(env, jobj, javaCallbackId,1,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!"));

    return 4000000;

}

第二种方式:

//
// Created by wei.yuan on 2017/6/7.
//
#include <android/log.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <dlfcn.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <assert.h>
#include <android\log.h>
#include <errno.h>
#include <pthread.h>

#include "com_cetcs_ecmapplication_jni_scs_JniScsManger.h"
//动态链接库路径
#define LIB_SCS_PATH "libServerCenter.so"
#define LOG_TAG "SCS123456"
#define LOGI_JniSCS(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT jint JNICALL Java_com_cetcs_ecmapplication_jni_scs_JniScsManger_startNativeScsService(JNIEnv * env, jobject jobj){
    LOGI_JniSCS("start native ServerCenterService");

    //jobj对象就是java层调用startNativeScsService的对象,那个类调用startNativeScsService对应的jobj就是那个对象
    jclass javaClass = (*env)->GetObjectClass(env, jobj);
    if (javaClass == 0) {
              LOGI_JniSCS("Unable to find class");
            return;
        }
        //获取要回调的方法ID
        jmethodID javaCallbackId = (*env)->GetMethodID(env, javaClass,"scsConnectStatus", "(ILjava/lang/String;)V");
        if (javaCallbackId == NULL) {
             LOGI_JniSCS("Unable to find method:onProgressCallBack");
            return;
        }
        //执行回调,注意第二个参数是jobj,不是javaClass
            (*env)->CallVoidMethod(env, jobj, javaCallbackId,1,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!"));

    return 4000000;

}

注意点:

FindClass是通过传java中完整的类名来查找java的class, 而GetObjectClass是通过传入jni中的一个java的引用来获取该引用的类型。 前者要求你必须知道完整的类名,后者要求在Jni有一个类的引用。上面中传入的
(JNIEnv * env, jobject jobj)中的jobj就是调用startNativeScsService的对象,就是JniScsManger的一个对象实例。
FindClass是通过类名获得该对象的实例,
GetObjectClass是获得该对象的一个引用。

现在增加一个需求:我们在上传新增加一个类:
我们要在startNativeScsService的c代码实现中回调Sb中的scsConnectStatus方法如何实现了,我们来看c层的代码
package com.cetcs.ecmapplication.jni.scs;

import android.util.Log;

/**
 * Created by wei.yuan on 2017/6/26.
 */

public class Sb {
    public  void  scsConnectStatus(int status,String reason){

        Log.d("123456",""+status+","+reason);

    }
}
//
// Created by wei.yuan on 2017/6/7.
//
#include <android/log.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <dlfcn.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <assert.h>
#include <android\log.h>
#include <errno.h>
#include <pthread.h>

#include "com_cetcs_ecmapplication_jni_scs_JniScsManger.h"
//动态链接库路径
#define LIB_SCS_PATH "libServerCenter.so"
#define LOG_TAG "SCS123456"
#define LOGI_JniSCS(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT jint JNICALL Java_com_cetcs_ecmapplication_jni_scs_JniScsManger_startNativeScsService(JNIEnv * env, jobject jobj){
    LOGI_JniSCS("start native ServerCenterService");

    //jobj对象就是java层调用startNativeScsService的对象,那个调用startNativeScsService对应的jobj就是那个对象
    jclass javaClass = (*env)->FindClass(env, "com/cetcs/ecmapplication/jni/scs/Sb");
    if (javaClass == 0) {
        LOGI_JniSCS("Unable to find class");
        return;
    }
    //构造Sb这个对象
    jmethodID constructor = (*env)->GetMethodID(env, javaClass, "<init>", "()V");
    //获取要回调的方法ID
    jmethodID javaCallbackId = (*env)->GetMethodID(env, javaClass,"scsConnectStatus", "(ILjava/lang/String;)V");
    if (javaCallbackId == NULL) {
        LOGI_JniSCS("Unable to find method:onProgressCallBack");
        return;
    }
    jobject obj = (*env)->NewObject(env, javaClass, constructor);
    //执行回调,注意第二个参数是obj,不是jobj
    (*env)->CallVoidMethod(env, obj, javaCallbackId,1,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!0..22"));

    return 4000000;

}

程序代码的下载地址是:

https://pan.baidu.com/s/1gfosrp5
时间: 2024-11-08 11:10:08

jni不通过线程c回调java的函数的相关文章

Android开发实践:JNI层线程回调Java函数示例

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://ticktick.blog.51cto.com/823160/1358558 JNI是Java Native Interface的缩写,是Java平台的重要特性,使得Java代码可以方便地与C/C++代码编译生成的动态链接库进行交互.本文主要给出一份示例代码(工程文件见附件),描述如何在Android的JNI层开启一个线程,并在线程中回调Java层的函数. 代码主要分为Java层

Android NDK开发(五)--C代码回调Java代码【转】

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41862479 在上篇博客里了解了Java层是怎样传递数据到C层代码,并且熟悉了大部分的实际开发知识,基本上掌握这些就可以做一个基本的NDK开发了,但是光是了解Java回调C层的数据是不是还不够啊,考虑问题要考虑可逆性,Java能回调C,那么C能否反过来回调Java呢?答案是肯定可以的,这篇博客就介绍一个C语言如何调用Java层的代码.以下是一些问题场景,我们带着这个问题场景来分析

Android C代码回调java方法

本文将讲述下列三种C代码回调java方法 1.c代码回调java空方法 2.c代码回调java int类型参数方法 3.c代码回调javaString类型参数方法 方法都差不多,先看c代码回调java空方法,其他两种类似: ① 找到字节码对象 //jclass (*FindClass)(JNIEnv*, const char*); //第二个参数 要回调的java方法所在的类的路径 "com/itheima/callbackjava/JNI" ② 通过字节码对象找到方法对象 //jme

线程池;java实现线程池原理

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙.如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值.超过最大值的线程可以排队,但他们要等到其他线程完成后才启动. 组成部分 1.线程池

JNI文件中命名类与JAVA文件中匹配

jni.c中注册中 int register_android_boa(JNIEnv *env){    jclass clazz;    static const char* const kClassName = "com/lxl/ledClass"; //命名的类 /* look up the class */    clazz = (*env)->FindClass(env,kClassName);  //  clazz = env->FindClass(env,kCl

类内定义线程的回调函数问题

C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象.函数体可以通过显示调用该指针或直接访问类内成员.      回调函数是用指针来调用的函数,最常使用的回调函数就是在创建线程时,以一个函数指针以及传递给这个函数多个参数来调用线程函数来创建线程.那么一般的类成员函数是不能用作回调函数的,因为库函数在使用回调函数时,都会传递指定的符合回调函数声明的的参数给回调函数,而类成员函数隐式包含一个this指针参数,所以把类成员函数当作回调函数编译时因为参数不匹配会出错.

android开发教程(4)— jni编程之采用 javah 从java调用C++

用Java调用C/C++代码 当无法用 Java 语言编写整个应用程序时,JNI 允许您使用本机代码.在下列典型情况下,您可能决定使用本机代码: 希望用更低级.更快的编程语言去实现对时间有严格要求的代码. 希望从 Java 程序访问旧代码或代码库. 需要标准 Java 类库中不支持的依赖于平台的特性. 须知:SWIG和javah的区别(强烈推荐) 我看了网上的关于 jni编程 的教程很多,但不尽相同,刚开始会犯迷糊.我想笔者往往忽略了一个关键点,那就是采用了什么方式决定了步骤的流程.有两种生成

类的成员函数实现线程的回调函数

一般都是用静态函数作为线程的回调函数实现,但是总是感觉不是很顺畅,更改吧,就好像破坏了类的封装性,不改吧,访问实在是麻烦.所以,今天要做的就是让类的成员函数作为线程的回调函数存在,其中使用的一个比较特殊的结构就是 union { void ( *ThreadProc)(LPVOID pvParam); void ( student::*MemberProc)(LPVOID pvParam); } Proc; 联合类,用于转换类成员方法指针到普通函数指针 下面是一个小李子,变量名 就凑活看吧,核心

入门: 使用JNI 从C++代码中调用Java的静态方法

开发环境: 操作系统: (uname -a output)  Linux ubuntu 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux JDK 版本 : (java -version) java version "1.7.0_51"OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-0ubun