浅谈JAVA反射机制在Android应用开发中的应用

http://www.oschina.net/question/163910_27112

 

最近一个多月在准备某软件设计比赛的作品,因为自己对Android平台的喜欢,项目定在Android上的应用,此文仅作为一个多月来对学习Android的一点总结和反思。 


想必学过JAVA的人一定接触过“反射”(Reflection)这个名词,简单的来说,反射机制就是允许编程人员在程序运行时来改变程序的结构或者变量的类型。通过这个特性,我们可以在运行时得知某个类的所有成员,包括其属性和方法,同时也能够调用这些方法。请注意反射机制的特殊之处就在于可以使用编译期间完全未知的类,也就是通过反射机制可以加载一个在运行时才得知名字的类,从而取得其内部的成员函数并调用。

  下面来通过我准备比赛的过程中遇到的两个例子来说明JAVA强大的反射机制在Android开发中的应用。

  第一个例子。我想大家在做一些Android App时,App最常用到的一个就是登陆界面,当然登陆界面的设计可以在layout中完成,通过使用Eclipse中的插件来绘制我们的UI。但一日我突然发现和不利用Android外观不错的AlertDialog?在其内嵌入两个EditText和两个Button(其实两个Button无需嵌入,因为AlertDialog可以很方便的使用setPositiveButton、setNeutralButton以及setNegativeButton来添加按钮并配置其listener)

先放上一张效果图

  (我个人觉得在EditText前加上用户名和密码的TextView是个累赘,为何不试试看TextView的hint属性呢?很清爽吧)
 

  可能大家看起来简单的一个功能,可给我带来不晓得麻烦。我想实现的功能是,当用户点击登陆按钮,如果验证成功,跳入下一个Activity,如果验证失败,原地不动。



  使用过AlertDialog的朋友肯定都清楚一个事实,无论你怎么设置按键响应,这个Dialog都会被关闭。

  为了解决它,我的第一感觉是,是否可以自己写一个类来继承AlertDialog,通过重写其中的一些关键函数来实现我们的功能。(我感觉这方法过于万能J)

首先我们查看一下AlertDialog的源码,可以通过在Eclipse下按住Ctrl的同时点击AlertDialog来跳转到其源代码,前提是你已经下载了android的源码并且放在了sdk的正确目录下,例如*\android-sdk-windows\platforms\android-10\sources\,我们打开其代码,800行左右,粗略的浏览一下,发现几个重点,首先很惹眼的,800行代码的类中,只定义了一个变量:

private AlertController mAlert;

  我想这个足够引起我们的注意,AlertController类是Android的内部类,在包com.android.internal.app中,无法通过普通的方式访问。也无法在Eclipse中通过按Ctrl键跟踪进源代码,所以我们手动找一下源代码包中的AlertController.java文件

(位于android-sdk-windows\platforms\android-10\sources\com\android\internal\app)

打开后,我们只寻找我们感兴趣的部分,比如关键词Button,或者Cancel之类的字眼,在该文件的开头,我们看到定义了一个按钮mButtonPositive,难道不就是开头提到的setPositiveButton?恩,现在只能说也许,我们继续ctrl+f寻找一下mButtonPositive的踪迹,
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
View.OnClickListener mButtonHandler = new View.OnClickListener() {
         public void onClick(View v) {
             Message m = null ;
             if (v == mButtonPositive && mButtonPositiveMessage != null ) {
                 m = Message.obtain(mButtonPositiveMessage);
             } else if (v == mButtonNegative && mButtonNegativeMessage != null ) {
                 m = Message.obtain(mButtonNegativeMessage);
             } else if (v == mButtonNeutral && mButtonNeutralMessage != null ) {
                 m = Message.obtain(mButtonNeutralMessage);
             }
             if (m != null ) {
                 m.sendToTarget();
             }
 
             // Post a message so we dismiss after the above handlers are executed
             mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface)
                     .sendToTarget();
         }
     };
很快能发现这段比较惹眼的定义,并且最后出现DISMISS是关键。我们细看可以发现,if-else的部分其实是绑定了按钮及其触发的消息,最后注释后面的代码才是关键,无论我们按下哪个按钮,都会执行后面的这句,其实可以猜到了这就是令Dialog Dismiss的部分。

  再往下看,我们会发现ButtonHandler的定义,
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private static final class ButtonHandler extends Handler {
     // Button clicks have Message.what as the BUTTON{1,2,3} constant
     private static final int MSG_DISMISS_DIALOG = 1 ;
 
     private WeakReference<DialogInterface> mDialog;
 
     public ButtonHandler(DialogInterface dialog) {
         mDialog = new WeakReference<DialogInterface>(dialog);
     }
 
     @Override
     public void handleMessage(Message msg) {
         switch (msg.what) {
 
             case DialogInterface.BUTTON_POSITIVE:
             case DialogInterface.BUTTON_NEGATIVE:
             case DialogInterface.BUTTON_NEUTRAL:
                 ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
                 break ;
 
             case MSG_DISMISS_DIALOG:
                 ((DialogInterface) msg.obj).dismiss();
         }
     }
}
简单分析一下,很显然可以看到,在switch中的MSG_DISMISS_DIALOG分支,((DialogInterface) msg.obj).dismiss(); 这就因该是对话框总是消失的原因了吧。

  到此我们找到了根本原因,现在我们考虑一个问题,需要重新写类来继承AlertDialog吗?有没有更简单地方法?

我们可以只重新定义ButtonHandler类,通过JAVA反射机制来使得AlertController中调用我们自己定义的这个handler即可。(注意不通过反射机制是行不通的,因为我们看到handler定义为私有,并且没有相应的接口~)

下面我们在dialog显示之前,执行下面的反射即可。
?
1
2
3
4
5
6
7
Field field = dialogBuilder.getClass().getDeclaredField( "mAlert" );
field.setAccessible( true );
Object obj = field.get(dialogBuilder);
field = obj.getClass().getDeclaredField( "mHandler" );
field.setAccessible( true );
field.set(obj, new ButtonHandler(dialogBuilder));
//设置我们自己定义的ButtonHandler
  OK,大功告成,现在看看我们的Dialog还会验证失败后消失么?

  第二个例子就简单的说一下好了,跟上面的差不多。

  在我的应用中,需要手机端实现自动建立WIFI无线热点,供身边的人来使用(我的目的是为了和身边的人交换大量数据,蓝牙是不行的)

搜遍了Android SDK 只发现了一些与WiFi连接有关的API,丝毫没有提及WiFiAP相关的内容。后来在StackOverflow上得到一个前辈的指导,解决的问题。下面我总结一下。其实事后我才发现跟我上面的思路是一样的。首先我们打开源代码中的WifiManager.java,位于*android-sdk-windows\platforms\android-10\sources\android\net\wifi下。

 

  直接搜索WifiAP,我们定位到一个函数setWifiApEnabled,看名字就知道使我们想要的。首先我解释一下,在源代码中,有一些API标记为hide,这些API是不允许在程序中调用的。Hidden API之所以被隐藏,是想阻止开发者使用SDK中那些未完成或不稳定的部分(接口或架构)。举个例子,Bluetooth API在API 5(Android 2.0)上才开放;在API 3 和4上都是用@hide属性隐藏了。当这些API被验证和清理后,Google的开发者会移除@hide属性,并让其在API 5官方化。很多地方在API 4 和5之间发生了变化。如果你的程序依赖某些隐藏的API,当其部署到新的平台上时,就有可能陷入困境。

  回到刚才定位到的函数,我们看到已经标记为hide,既然这样,如果我们需要再次利用反射机制来调用这个函数,从而实现我们建立Wifi-AP的目的。

  具体的跟上面的思路一样。我只贴出反射部分代码:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Method method1 = wifi.getClass().getMethod( "setWifiApEnabled" ,WifiConfiguration. class , boolean . class );
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = "\"Express Sensor\"" ;
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
netConfig.preSharedKey = "11111111" ;
method1.invoke(wifi, netConfig, enabled);
Method method2 = wifi.getClass().getMethod( "getWifiApState" );
state = (Integer) method2.invoke(wifi);
  WifiConfiguration 是网络配置类,用来配置我们的热点密码类型,秘密等等。不要忘记在打开AP后更改WP状态。即method2。关于JAVA反射机制就总结到这里~ 有什么问题可以留言讨论。

文章转自:  http://www.ericyue.info/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧农业是一种结合了现代信息技术,包括物联网、大数据、云计算等,对农业生产过程进行智能化管理和监控的新模式。它通过各种传感器和设备采集农业生产的关键数据,如大气、土壤和水质参数,以及生物生长状态等,实现远程诊断和精准调控。智慧农业的核心价值在于提高农业生产效率,保障食品安全,实现资源的可持续利用,并为农业产业的转型升级提供支持。 智慧农业的实现依赖于多个子系统,包括但不限于设施蔬菜精细化种植管理系统、农业技术资料库、数据采集系统、防伪防串货系统、食品安全与质量追溯系统、应急追溯系统、灾情疫情防控系统、农业工作管理系统、远程诊断系统、监控心、环境监测系统、智能环境控制系统等。这些系统共同构成了一个综合的信息管理和服务平台,使得农业生产者能够基于数据做出更加科学的决策。 数据采集是智慧农业的基础。通过手工录入、传感器自动采集、移动端录入、条码/RFID扫描录入、拍照录入以及GPS和遥感技术等多种方式,智慧农业系统能够全面收集农业生产过程的各种数据。这些数据不仅包括环境参数,还涵盖了生长状态、加工保存、检验检疫等环节,为农业生产提供了全面的数据支持。 智慧农业的应用前景广阔,它不仅能够提升农业生产的管理水平,还能够通过各种应用系统,如库房管理、无公害监控、物资管理、成本控制等,为农业生产者提供全面的服务。此外,智慧农业还能够支持政府监管,通过发病报告、投入品报告、死亡报告等,加强农业产品的安全管理和质量控制。 面对智慧农业的建设和发展,存在一些挑战,如投资成本高、生产过程标准化难度大、数据采集和监测的技术难题等。为了克服这些挑战,需要政府、企业和相关机构的共同努力,通过政策支持、技术创新和教育培训等手段,推动智慧农业的健康发展。智慧农业的建设需要明确建设目的,选择合适的系统模块,并制定合理的设备布署方案,以实现农业生产的智能化、精准化和高效化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值