背景交代:熟悉用js开发的cordovaAPP;对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝我好运T^T
本文关键词:cordovaAPP插件开发、实战问题

开发中遇到的实际问题:

存在2个只会被系统实例化的类(安卓系统事件消息硬触发的BroadcastReceiver类,cordova触发的CordovaPlugin类),要求将CordovaPlugin 中js传来的callback地址传递到BroadcastReceiver类中。

困难1:两个类只会被系统实例化,无法获取实例对象的地址,所以也就无法实现传统的java回调。

困难2:BroadcastReceiver类会在系统事件消息(android.hardware.action.NEW_PICTURE)产生之后触发onReceive方法,并注销对象之后重新生成自己的实例对象。

尝试1:使用回调  (失败,单纯用回调)

知识:java回调

回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,常用于异步获取处理结果(耗时或处理时间不确定的操作)。

需要定义三个类,分别是主函数类,callback函数的接口类,耗时业务处理类,在业务处理类中,处理完业务之后,执行一个callback函数。

文件:CallBack.java (接口)

package com.sysnotify.lewes.sysnotify_test;

/* 创建一个callback接口
* 用于实现java回调,请仔细阅读下面的注释
* */
public interface CallBack {
public void onEndcallback();
}
//用法
/*
//主函数class
public class Main {
public static void main(String[] args) { //入口方法
new TestCallBack().compute(1000, new ComputeCallBackFun() { // 回调函数
public void onComputeEnd() {
System.out.println("end callback!!!"); }
});
}
} //耗时class
public class TestCallBack {
//耗时类中要有一个接受callback的入口函数
public void compute(int n, CallBack callback) {
{ //执行耗时操作
for (int i = 0; i < n; i++) {
System.out.println(i);
}
}
// 执行完调用这个规定格式的callback
callback.onEndcallback();
}
} */

尝试2:使用静态变量+接口回调   (17.1.3成功)

知识:静态变量

   类的成员变量有两种:一种是被static关键字修饰的变量,叫类变量或静态变量,一种是没有被static修饰的,叫做实例变量 
    静态变量和实例变量的区别在于: 
    类静态变量在内存中只有一个,java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享,静态变量可以通过类名直接访问。静态变量的生命周期取决于类的生命周期,当类被加载的时候,静态变量被创建并分配内存空间,当类被卸载时,静态变量被摧毁,并释放所占有的内存。 
    类的每一个实例都有相应的实例变量,每创建一个类的实例,java虚拟机为实例变量分配一次内存,实例变量位于堆区中,实例变量的生命周期取决于实例的生命周期,当创建实例时,为实例变量背创建,并分配内存,当实例被销毁时,实例 变量被销毁,并释放所占有的内存空间。 
    假如成员变量时引用变量,该成员变量结束生命周期时,并不意味着它所引用对象也结束生命周期。变量的生命周期和对象的生命周期是不同的概念。来源: http://leiguomin627-126-com.iteye.com/blog/422214
 

知识:java调试信息

在调试代码的时候我们需要查看调试信息,那我们就需要用Android Log类。原型Log.v(String tag, String msg)

android.util.Log常用的方法有以下5个:Log.v() Log.d() Log.i() Log.w() 以及 Log.e() 。根据首字母对应VERBOSE,DEBUG,INFO, WARN,ERROR。

1、Log.v 的调试颜色为黑色的,任何消息都会输出,这里的v代表verbose啰嗦的意思,平时使用就是Log.v("","");

2、Log.d的输出颜色是蓝色的,仅输出debug调试的意思,但他会输出上层的信息,过滤起来可以通过DDMS的Logcat标签来选择.

3、Log.i的输出为绿色,一般提示性的消息information,它不会输出Log.v和Log.d的信息,但会显示i、w和e的信息

4、Log.w的意思为橙色,可以看作为warning警告,一般需要我们注意优化Android代码,同时选择它后还会输出Log.e的信息。

5、Log.e为红色,可以想到error错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。

关键代码

文件:camerainfo.java (CordovaPlugin入口文件)

这里可以看做class A,由Cordova自动实例化,但无法获取其实例对象地址

package lewes;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONException; //class A
public class camerainfo extends CordovaPlugin{
@Override
public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
// 注册监听器-拍照事件
if("init".equals(action)){
new CameraReceiver().setCallback(new CallBack(){
@Override
public void onEndcallback() {
//在运行正确时,返回true,无传值用.success
//callbackContext.success();
// 如果需要返回数值(字符串,对象等),可以用PluginResult;
// 若返回错误要改PluginResult.Status.ERROR
PluginResult mPlugin = new PluginResult(PluginResult.Status.OK,
"photo get!");
mPlugin.setKeepCallback(true);
callbackContext.sendPluginResult(mPlugin);
}
} ); return true;
}
//传递消息到js 方法1 执行回调
callbackContext.error("error");
return false;
}
}
文件:CameraReceiver.java & AndroidManifest.xml (系统广播-拍照触发后系统自动调用的函数)
这里可以看做class B,由android自动实例化,但无法获取其实例对象地址
 
获取拍照事件广播的实现方法: 在AndroidManifest.xml中编辑好<receiver>,当系统消息广播-拍照被触发,会由安卓系统自动调用onReceive方法
详细请了解BroadcastReceiver 的2种用法(软监听、硬监听)
 
//AndroidManifest.xml  在<application>标签内增加以下内容
  <receiver android:enabled="true" android:name="lewes.CameraReceiver">
<intent-filter android:priority="2147483647">
<action android:name="android.hardware.action.NEW_PICTURE" />
<data android:mimeType="image/*" />
</intent-filter>
</receiver>

//camerainfo.java

package lewes;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

//class B
public class CameraReceiver extends BroadcastReceiver {
public static CallBack cb;//关键是在这创建一个静态变量,保存传过来的callback指针
public void setCallback(CallBack callback){
cb=callback;
}
@Override
public void onReceive(Context context, Intent intent) {
cb.onEndcallback();
}
}

文件:CallBack.java (接口)

//文章开头已给出,注释此略
package com.sysnotify.lewes.sysnotify_test;
/* 创建一个callback接口
* */
public interface CallBack {
public void onEndcallback();
}
 

最终实现思路:java用接口(interface)来实现回调,所以首先定义一个名叫callback的接口,它有一个函数onEndCallback().

在class B 中创建一个接收callback指针的函数 setCallback(CallBack callback),一个储存callback指针的静态变量 public static CallBack cb

在class A 中实现接口的方法onEndCallback() (本文的这里使用了匿名类生成接口 参见http://www.cnblogs.com/yjmyzz/p/3448330.html)

并创建一个class B的实例,用来传递callback指针 new CameraReceiver().setCallback(callback指针)

最终,在class B 的接收事件产生时调用cb.onEndCallback()完成回调。

如果还没看懂,结合代码多看几遍。。。。

【java回调】java两个类之间的回调函数传递的更多相关文章

  1. python两个类之间变量和函数的调用

    1.class_a() class_b() 2.class_b使用class_a中的变量和函数 3.变量class_a中:class_a.num=... 函数class_b中:先实例化class_a( ...

  2. java string截取两个字符串之间的值

    java string截取两个字符串之间的值 import java.util.regex.Matcher; import java.util.regex.Pattern; public class ...

  3. (转) C++中基类和派生类之间的同名函数的重载问题

    下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...

  4. java中计算两个日期之间天数的程序设计。

    //用java编写出一个以下方法计算两个日期之间天数的程序设计. import java.util.regex.Matcher; import java.util.regex.Pattern; pub ...

  5. Java中的两个类:Desktop和SystemTray

    在JDK6中 ,AWT新增加了两个类:Desktop和SystemTray,前者可以用来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端给指定的邮箱发邮件,用默认应用程序打开或编辑文件(比如 ...

  6. 使用 Attribute +反射 来对两个类之间动态赋值

    看同事使用的 一个ORM 框架 中 有这样一个功能  通过特性(附加属性)的功能来 实现的两个类对象之间动态赋值的 功能 觉得这个功能不错,但是同事使用的 ORM 并不是我使用的  Dapper  所 ...

  7. java输出任意两个日期之间有多少天

    package JingDian; import java.text.ParseException; import java.text.SimpleDateFormat; import java.ut ...

  8. java中静态类与普通类之间区别

    所谓静态,指以static关键字修饰的,包括类,方法,块,字段. 非静态,指没有用static 修饰的. 一.静态类的特点 1.全局唯一,任何一次的修改都是全局性的影响 2.只加载一次,优先于非静态 ...

  9. 两个Select 之间的值的传递

    运行效果: 下面是代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML ...

随机推荐

  1. vue.js第六课

    class与style绑定 绑定HTML class 对象语法 数组语法 绑定内联样式 对象语法 数组语法 自动添加前缀 1.class与style绑定. 数据绑定一个常见需求就是 操作元素的clas ...

  2. 解决java.net.MalformedURLException: unknown protocol: c问题

    修改前代码: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builde ...

  3. input placeholder属性 样式修改(颜色,大小,位置)

    placeholder属性 样式修改 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  4. Apriori算法的原理与python 实现。

    前言:这是一个老故事, 但每次看总是能从中想到点什么.在一家超市里,有一个有趣的现象:尿布和啤酒赫然摆在一起出售.但是这个奇怪的举措却使尿布和啤酒的销量双双增加了.这不是一个笑话,而是发生在美国沃尔玛 ...

  5. SQLite

      什么是SQLite SQLite是一款轻型的嵌入式数据库 它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 它的处理速度比Mysql.PostgreSQL这两款著名的数据库都还快 ...

  6. Calendar类

    Calendar类 注意:根据日历规则,如果想要这个月减去5天,那么则为: add(Calendar.Day,-5) 成员方法: public int get(int field):返回给定日历段的值 ...

  7. excellent cushioning and also vitality go back with this boot

    The particular manufactured fine mesh higher almost addresses the complete boot. Here is the sort of ...

  8. coreseek操作

    开启服务$  /usr/local/coreseek/bin/searchd -c /usr/local/coreseek/etc/csft.conf 重新索引: /usr/local/coresee ...

  9. bootstrapvalidator+bootstrap-select select无法校验问题解决方法

    $("#form_user_input") .bootstrapValidator( { message : 'This value is not valid', excluded ...

  10. 大神php摘录

    1. $rs = M('order')->where('id='.$res['id'])->save($order); )){ M('member')->where('id='.$m ...