(转载)JAVA反射机制在Android应用开发中的应用

简介: 想必学过JAVA的人一定接触过“反射”(Reflection)这个名词,简单的来说,反射机制就是允许编程人员在程序运行时来改变程序的结构或者变量的类型。通过这个特性,我们可以在运行时得知某个类的所有成员,包括其属性和方法,同时也能够调用这些方法。

想必学过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的踪迹,

 

 

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的定义

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显示之前,执行下面的反射即可。

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下。

 

/**
	*
	*@hide Dont open up yet
	*/
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled){
	try{
		return mService.setWifiApEnabled(wifiConfig,enabled);
	}catch(RemoteException e){
		return false;
	}
}

 

直接搜索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的目的。

具体的跟上面的思路一样。我只贴出反射部分代码:

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。

原文:

 http://www.ericyue.info/archive/java-reflection-on-android

 

 

 

 

 

 

 

目录
相关文章
|
1月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
164 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
25天前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
48 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
3月前
|
Java 开发者
Java中的异常处理机制深度剖析####
本文深入探讨了Java语言中异常处理的重要性、核心机制及其在实际编程中的应用策略,旨在帮助开发者更有效地编写健壮的代码。通过实例分析,揭示了try-catch-finally结构的最佳实践,以及如何利用自定义异常提升程序的可读性和维护性。此外,还简要介绍了Java 7引入的多异常捕获特性,为读者提供了一个全面而实用的异常处理指南。 ####
105 20
|
3月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
101 14
|
3月前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
3月前
|
搜索推荐 Android开发 开发者
安卓应用开发中的自定义控件实践
在安卓应用开发的广阔天地中,自定义控件如同璀璨的星辰,点亮了用户界面设计的夜空。它们不仅丰富了交互体验,更赋予了应用独特的个性。本文将带你领略自定义控件的魅力,从基础概念到实际应用,一步步揭示其背后的原理与技术细节。我们将通过一个简单的例子——打造一个具有独特动画效果的按钮,来展现自定义控件的强大功能和灵活性。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往更高阶UI设计的大门。
|
3月前
|
Java 程序员
深入理解Java异常处理机制
Java的异常处理是编程中的一块基石,它不仅保障了代码的健壮性,还提升了程序的可读性和可维护性。本文将深入浅出地探讨Java异常处理的核心概念、分类、处理策略以及最佳实践,旨在帮助读者建立正确的异常处理观念,提升编程效率和质量。
155 1
|
3月前
|
Java 开发者 UED
深入探索Java中的异常处理机制##
本文将带你深入了解Java语言中的异常处理机制,包括异常的分类、异常的捕获与处理、自定义异常的创建以及最佳实践。通过具体实例和代码演示,帮助你更好地理解和运用Java中的异常处理,提高程序的健壮性和可维护性。 ##
79 2
|
3月前
|
Java API 开发者
深入理解Java中的异常处理机制
本文探讨了Java编程语言中异常处理的核心概念,包括异常类型、异常捕获与抛出、以及最佳实践。通过分析常见的异常场景和处理策略,旨在帮助开发者更好地理解和运用异常处理机制,提高代码的健壮性和可维护性。文章不仅涵盖了基本的try-catch结构,还深入讨论了自定义异常的创建与使用,以及finally块的重要性和应用。此外,还将介绍一些高级技巧,如多异常捕获和嵌套异常处理,为读者提供全面的技术指导。
121 0
|
3月前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
98 0

热门文章

最新文章