整个工程的项目如下:

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 == ) {
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,,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!")); return ; }

第二种方式:

//
// 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 == ) {
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,,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!")); return ; }

注意点:

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 == ) {
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,,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!0..22")); return ; }

程序代码的下载地址是:

https://pan.baidu.com/s/1gfosrp5

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

  1. jni不通过线程c回调java的函数 --总结

    1.JNIEnv类型是一个指向全部JNI方法的指针.该指针只在创建它的线程有效,不能跨线程传递 2.JavaVM是虚拟机在JNI中的表示,一个JVM中只有一个JavaVM对象,这个对象是线程共享的. ...

  2. JNI通过线程c回调java层的函数

    1.参看博客:http://www.jianshu.com/p/e576c7e1c403 Android JNI 篇 - JNI回调的三种方法(精华篇) 2.参看博客: JNI层线程回调Java函数关 ...

  3. Jni层回调java代码【转】

    本文转载自:http://www.linuxidc.com/Linux/2014-03/97562.htm JNI是Java Native Interface的缩写,是Java平台的重要特性,使得Ja ...

  4. Android jni中回调java的方法

    在上一篇的基础上,添加在C++代码中回调java方法. 代码如下: Demo.java 中添加callback函数, 打印一条log. package com.example.scarecrow.dy ...

  5. Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题

    最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候 出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就 ...

  6. Jni本地多线程回调Java函数,env->findClass()失败。

    遇到的问题,Native层本地多线程回调Java函数时env->findClass()失败. 前面的代码是这样的在 JNI_OnLoad记录全局变量g_vm static JavaVM* g_v ...

  7. Android C代码回调java方法

    本文将讲述下列三种C代码回调java方法 1.c代码回调java空方法 2.c代码回调java int类型参数方法 3.c代码回调javaString类型参数方法 方法都差不多,先看c代码回调java ...

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

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41862479 在上篇博客里了解了Java层是怎样传递数据到C层代码,并且熟悉了大部 ...

  9. Java线程新特征——Java并发库

    一.线程池   Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定 ...

随机推荐

  1. FHQ-Treap学习笔记

    平衡树与FHQ-Treap 平衡树(即平衡二叉搜索树),是通过一系列玄学操作让二叉搜索树(BST)处于较平衡的状态,防止在某些数据下退化(BST在插入值单调时,树形不平衡,单次会退化成 \(\math ...

  2. UWP开发入门(25)——通过Radio控制Bluetooth, WiFi

    回顾写了许久的UWP开发入门,竟然没有讲过通过Windows.Devices.Radios.Radio来控制Bluetooth和WiFi等功能的开关.也许是因为相关的API设计的简单好用,以至于被我给 ...

  3. go语言的主要特征

    go语言主要特征 1.自动立即回收. 2.更丰富的内置类型. 3.函数多返回值. 4.错误处理. 5.匿名函数和闭包. 6.类型和接口. 7.并发编程. 8.反射. 9.语言交互性. golang文件 ...

  4. Rocket - util - Counters

    https://mp.weixin.qq.com/s/q7R2Dn9p9cch_ABN4raReQ   介绍几种计数器的实现,以及其中的一点小细节.   ​​   1. ZCounter   ​​   ...

  5. IntelliJ IDEA连接不上数据库 (Connection to testdb@localhost failed. [08001] Could not create connection to database server. Attempted reconnect 3 times. Giving up.)

    问题提示为: 原因:MySQL数据库版本为8.0以上,需要在URL加上时区,即加上?serverTimezone=GMT 成功后为:

  6. js循环语句while,do..while,for

    1. while循环 while(循环条件){ 循环体语句块; } 2.do..while循环 do{ 循环体语句块; }while(循环条件) 两者区别:while先判断后执行.循环体语句可能一次都 ...

  7. Java实现 LeetCode 770 基本计算器 IV(暴力+分析题)

    770. 基本计算器 IV 给定一个表达式 expression 如 expression = "e + 8 - a + 5" 和一个求值映射,如 {"e": ...

  8. Java实现 蓝桥杯 素因子去重

    素因子去重 问题描述 给定一个正整数n,求一个正整数p,满足p仅包含n的所有素因子,且每个素因子的次数不大于1 输入格式 一个整数,表示n 输出格式 输出一行,包含一个整数p. 样例输入 1000 样 ...

  9. java实现第九届蓝桥杯整理玩具

    整理玩具 小明有一套玩具,一共包含NxM个部件.这些部件摆放在一个包含NxM个小格子的玩具盒中,每个小格子中恰好摆放一个部件. 每一个部件上标记有一个0~9的整数,有可能有多个部件标记相同的整数. 小 ...

  10. tensorflow2.0学习笔记第二章第三节

    2.3激活函数sigmoid函数 f(x)= 1/(1 + e^-x)tf.nn.sigmoid(x)特点:(1)求导后的数值在0-0.25之间,链式相乘之后容易使得值趋近于0,形成梯度消失 (2)输 ...