整个工程的项目如下:

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. vivo产能问题

    生产手机,第一天量产1台,接下来2天(即第二.三天)每天量产2件,接下来3天(即第四.五.六天)每天量产3件 ... ... 以此类推,请编程计算出第n天总共可以量产的手机数量. public int ...

  2. DQN(Deep Q-learning)入门教程(六)之DQN Play Flappy-bird ,MountainCar

    在DQN(Deep Q-learning)入门教程(四)之Q-learning Play Flappy Bird中,我们使用q-learning算法去对Flappy Bird进行强化学习,而在这篇博客 ...

  3. rewrite和return的简单需求

    Rewrite 需求作业 背景:现在我有一个网站,www.linux.com www.linux.com访问主页面 friend.linux.com访问交友页面 blog.linux.com访问博客页 ...

  4. [译]深入理解JVM Understanding JVM Internals

    转载: 英文原版地址:http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/ 翻不了墙的可以看这个英文版:https: ...

  5. Redis 入门到分布式 (四) 瑞士军刀Redis其他功能

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 目录: 慢查询 Pipeline 发布订阅 Bitmap(位图) HyperLogLog GEO 一.慢 ...

  6. Java实现 LeetCode 672 灯泡开关 Ⅱ(数学思路问题)

    672. 灯泡开关 Ⅱ 现有一个房间,墙上挂有 n 只已经打开的灯泡和 4 个按钮.在进行了 m 次未知操作后,你需要返回这 n 只灯泡可能有多少种不同的状态. 假设这 n 只灯泡被编号为 [1, 2 ...

  7. Java实现 LeetCode 507 完美数

    507. 完美数 对于一个 正整数,如果它和除了它自身以外的所有正因子之和相等,我们称它为"完美数". 给定一个 整数 n, 如果他是完美数,返回 True,否则返回 False ...

  8. Java实现 LeetCode 475 供暖器

    475. 供暖器 冬季已经来临. 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖. 现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径. 所以,你的输入将会是房 ...

  9. Java实现 蓝桥杯VIP 基础练习 完美的代价

    package 蓝桥杯VIP; import java.util.Scanner; public class 完美的代价 { public static int sum = 0; public sta ...

  10. Java实现第十届蓝桥杯数的分解

    试题 D: 数的分解 本题总分:10 分 [问题描述] 把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包 含数字 2 和 4,一共有多少种不同的分解方法? 注意交换 3 个整 ...