背景交代:熟悉用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 (接口)

  1. package com.sysnotify.lewes.sysnotify_test;
  2.  
  3. /* 创建一个callback接口
  4. * 用于实现java回调,请仔细阅读下面的注释
  5. * */
  6. public interface CallBack {
  7. public void onEndcallback();
  8. }
  9. //用法
  10. /*
  11. //主函数class
  12. public class Main {
  13. public static void main(String[] args) { //入口方法
  14. new TestCallBack().compute(1000, new ComputeCallBackFun() {
  15.  
  16. // 回调函数
  17. public void onComputeEnd() {
  18. System.out.println("end callback!!!");
  19.  
  20. }
  21. });
  22. }
  23. }
  24.  
  25. //耗时class
  26. public class TestCallBack {
  27. //耗时类中要有一个接受callback的入口函数
  28. public void compute(int n, CallBack callback) {
  29. { //执行耗时操作
  30. for (int i = 0; i < n; i++) {
  31. System.out.println(i);
  32. }
  33. }
  34. // 执行完调用这个规定格式的callback
  35. callback.onEndcallback();
  36. }
  37. }
  38.  
  39. */

尝试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() 。根据首字母对应VERBOSEDEBUG,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自动实例化,但无法获取其实例对象地址

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

//camerainfo.java

  1. package lewes;
  2.  
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;

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

文件:CallBack.java (接口)

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

最终实现思路: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. 腾讯 auth_token

    auth_token 从cookies里取出supertoken=2881515311; function auth_token(str) { var hash = 0; for (var i = 0 ...

  2. angular

  3. Mac合并分区

    Mac合并分区 公司Mac电脑之前是win系统,重新安装了mac系统后,多了一个分区.用分区助手打开后,减号是灰色的,上网搜了很多帖子,都是点击减号直接将分区删除等等.减号不能点击的就要重新装系统了. ...

  4. 【BZOJ 2595】【WC 2008】游览计划

    http://www.lydsy.com/JudgeOnline/problem.php?id=2595 斯坦纳树的例题诶...我怎么做了好长时间_(:з」∠)_ 首先这是一棵树. 状压表示状态,\( ...

  5. 在SpringMVC中使用@SessionAttributes和@ModelAttribute将数据存储在session域中

    今天在我的springMVC项目--图书管理系统中,希望在登录时将登录的Users存在session中,开始是准备在controller中使用Servlet API中的对象,可是一直无法引用,不知道为 ...

  6. 图解TCP-IP协议

    本文通过图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图1所示,给出了TCP通信过程的示意图. 图1 TCP 三次握手四次挥手 图1 ...

  7. table里面,怎么根据checkbox选择的一行中的某个单元格的值是否为空,来判断是否该选中

    <table class="stripe" id="tab2"> <tr> <th>选择</th> <th ...

  8. wordpress默认index主页选择Your Projects提示无法找到项目解决办法?

    wordpress_4.5.3默认index主页选择Your Projects下部署的项目发现报错无法找到目标解决办法: 1.其实细心的小伙伴已经发现问题出在哪里,跳转后链接地址发生了错误没有加loc ...

  9. selenium-----chromedriver与chrome版本映射

    chromedriver下载地址:http://chromedriver.storage.googleapis.com/index.html chromedriver版本 支持的Chrome版本 v2 ...

  10. 个人作业——week3

    1.软件工程师的成长 拜读了多位优秀前辈的文章后,感觉十分复杂,虽然说不上是醍醐灌顶的那种大彻大悟,但是确实的感觉到自己内心中某个部分被真切的感触到了.推荐的文章语言都比较平易近人,感觉就像是和多年未 ...