Android获取设备电池信息,玩些新花样
2015-11-11 18:17
323 查看
在开发过程中有时我们不可避免地需要了解当前设备电池的状态,比如当前剩余电量、电池温度、是否在充电中等等..
经过查询一些资料,我发现电池的信息大多是通过广播获取的,详细的代码不贴了,到处都是,大致的流程是注册一个广播,过滤设为 Intent.ACTION_BATTERY_CHANGED 在其中的onReceive方法中,我们通过系统给的Intent参数,调用getIntExtra可以获得大部分电池信息。
不过今天遇到一个问题,如何获取到设备电池的总容量,注意!,在广播中,通过Intent我们通过“scale”键可以获得一个值,这个值通常是100,并不是我们所要的电池容量,考究了一番,网上关于电池容量的一些信息还是比较少的。下面我们的工作就是 get it。
首先明确,电池的信息是厂商直接提供的,并不是通过硬件检测而来的,其实道理很简单,我们无法通过电池的金属头直接探测电池的容量,最多也就是个电压和温度信息,这些能够探测的信息在上面说的广播的方法中也可以获得。那如何获得电池容量呢?设备在写入操作系统时,厂家会在操作系统中附带一个关于电池、各部件耗电情况的表单,表单名叫 power_profile.xml,路径是com.android.internal.R.xml.power_profile,我们的任务就是从这个表单中读取信息。这时有人可能会问了,我换块电池怎么办,那么,没办法,我们能得到的只是原装电池。。。。(貌似现在的Android机能换电池的并不多)
读取这个文件的信息并不是个简单的操作,大家都知道,Android系统并不是把所有的api都暴露给开发者的,由于一些安全上面的考虑,或是由于有些api还没有最终确定形态,其中的一些值或参数后期还会改变,故将这些方法或类进行了隐藏,我们开发时所用的sdk是不包含这些类和方法的。比如我们现在需要读取power_profile的类就不能调用。
嘿嘿,但总有解决办法。
从根源想想,开发版的sdk没有,那么编译就会报错,所以就有这么几个解决方案:
1、让开发时的sdk有这些方法(这不废话么)。
2、让程序感觉开发时的sdk有这些类和方法(什么鬼!)。
3、绕过编译(终于是一句人话了)。
首先我们来说最容易理解的第3条,绕过编译,其实就是用java反射的方法,要使用反射,我们需要知道类的完整路径,参数列表,这个嘛,Android源码里有,这里我们就直接给出了。
上码!
mPowerProfile = Class.forName(“com.android.internal.os.PowerProfile”).getConstructor(Context.class).newInstance(this); 这句创建了解析power_profile文件的PowerProfile类实例,try语句内得到相关方法并调用,最终得到了电池的容量,是一个double值。
上面的代码很简单了,不在赘述,如果不懂反射建议学习一些,网上的资料也很多。
然后,我们来说说这个 让sdk有这个方法。这个是最复杂的一种解决方案,强烈不推荐使用,太费劲了,我只说一下简要的流程吧。首先我们要获取手机系统中/system/framework/framework.jar文件,framework.jar包含了所有隐藏的api,然后从中获取classes.dex,将其转化成classes.jar,再从classes.jar中解压获得android.jar,最后用这个android.jar编译我们的工程。好吧,心好累。。。这种方法比较锻炼人的各种技能,恩,作为一个爱探索的青年,我选择放弃。
最后来说说 让程序感觉开发时的sdk有这些类和方法。
这个,其实呢牛逼点的叫法应该是api欺骗,由于Android系统在加载类时是根据包名判断的,
那么我们就在我们的工程中建立一个一模一样的包,于是我们在项目中新建了包:com.android.internal.os,接下来再新建类PowerProfile.java,最后给类加入你需要的方法getAveragePower(),因为你需要知道方法签名,也就是返回值和参数列表,于是你不可避免的看了一眼Android源码。。。
哦,这样啊,函数体不用写,返回随意,只要按签名来就行,反正系统不会理你这个方法,这个方法唯一的作用就是让编译器感觉你的代码ok,没有调用不存在的东西,
但是! 当程序运行在设备上时~嘿嘿,系统加载了自己framework.jar中com.android.internal.os包的类文件,调用了自己类中的方法。
恩~这种方法就好像是~空手套白狼。。。。呜呜~程序员都是骗子!
有没有感觉又get了一个新技能?
由于api是隐藏的,相关方面的文档也是少得可怜,人家的东西就算拿来了也不一定会用啊(多么痛的领悟!)
最后的最后!!!!!!!!!!!!!!!!隐藏的api在不同系统版本下可能会产生不可预期的错误,正如前面所说的,其中的一些常量值在不同系统中都可能不一样!!!方法的参数列表也可能有差异!!!所以在用的时候千万要小心翼翼!!!!! 就这么多,收~
经过查询一些资料,我发现电池的信息大多是通过广播获取的,详细的代码不贴了,到处都是,大致的流程是注册一个广播,过滤设为 Intent.ACTION_BATTERY_CHANGED 在其中的onReceive方法中,我们通过系统给的Intent参数,调用getIntExtra可以获得大部分电池信息。
不过今天遇到一个问题,如何获取到设备电池的总容量,注意!,在广播中,通过Intent我们通过“scale”键可以获得一个值,这个值通常是100,并不是我们所要的电池容量,考究了一番,网上关于电池容量的一些信息还是比较少的。下面我们的工作就是 get it。
首先明确,电池的信息是厂商直接提供的,并不是通过硬件检测而来的,其实道理很简单,我们无法通过电池的金属头直接探测电池的容量,最多也就是个电压和温度信息,这些能够探测的信息在上面说的广播的方法中也可以获得。那如何获得电池容量呢?设备在写入操作系统时,厂家会在操作系统中附带一个关于电池、各部件耗电情况的表单,表单名叫 power_profile.xml,路径是com.android.internal.R.xml.power_profile,我们的任务就是从这个表单中读取信息。这时有人可能会问了,我换块电池怎么办,那么,没办法,我们能得到的只是原装电池。。。。(貌似现在的Android机能换电池的并不多)
读取这个文件的信息并不是个简单的操作,大家都知道,Android系统并不是把所有的api都暴露给开发者的,由于一些安全上面的考虑,或是由于有些api还没有最终确定形态,其中的一些值或参数后期还会改变,故将这些方法或类进行了隐藏,我们开发时所用的sdk是不包含这些类和方法的。比如我们现在需要读取power_profile的类就不能调用。
嘿嘿,但总有解决办法。
从根源想想,开发版的sdk没有,那么编译就会报错,所以就有这么几个解决方案:
1、让开发时的sdk有这些方法(这不废话么)。
2、让程序感觉开发时的sdk有这些类和方法(什么鬼!)。
3、绕过编译(终于是一句人话了)。
首先我们来说最容易理解的第3条,绕过编译,其实就是用java反射的方法,要使用反射,我们需要知道类的完整路径,参数列表,这个嘛,Android源码里有,这里我们就直接给出了。
上码!
private double getDeviceBatteryCapavity(){ Object mPowerProfile_ = null; double batteryCapacity=0; try { mPowerProfile = Class.forName("com.android.internal.os.PowerProfile") .getConstructor(Context.class).newInstance(this); } catch (Exception e) { e.printStackTrace(); } try { batteryCapacity = (Double) Class .forName("com.android.internal.os.PowerProfile") .getMethod("getAveragePower", java.lang.String.class) .invoke(mPowerProfile, "battery.capacity"); Log.e(TAG, "" + batteryCapacity); } catch (Exception e) { e.printStackTrace(); } return batteryCapacity; }
mPowerProfile = Class.forName(“com.android.internal.os.PowerProfile”).getConstructor(Context.class).newInstance(this); 这句创建了解析power_profile文件的PowerProfile类实例,try语句内得到相关方法并调用,最终得到了电池的容量,是一个double值。
上面的代码很简单了,不在赘述,如果不懂反射建议学习一些,网上的资料也很多。
然后,我们来说说这个 让sdk有这个方法。这个是最复杂的一种解决方案,强烈不推荐使用,太费劲了,我只说一下简要的流程吧。首先我们要获取手机系统中/system/framework/framework.jar文件,framework.jar包含了所有隐藏的api,然后从中获取classes.dex,将其转化成classes.jar,再从classes.jar中解压获得android.jar,最后用这个android.jar编译我们的工程。好吧,心好累。。。这种方法比较锻炼人的各种技能,恩,作为一个爱探索的青年,我选择放弃。
最后来说说 让程序感觉开发时的sdk有这些类和方法。
这个,其实呢牛逼点的叫法应该是api欺骗,由于Android系统在加载类时是根据包名判断的,
那么我们就在我们的工程中建立一个一模一样的包,于是我们在项目中新建了包:com.android.internal.os,接下来再新建类PowerProfile.java,最后给类加入你需要的方法getAveragePower(),因为你需要知道方法签名,也就是返回值和参数列表,于是你不可避免的看了一眼Android源码。。。
哦,这样啊,函数体不用写,返回随意,只要按签名来就行,反正系统不会理你这个方法,这个方法唯一的作用就是让编译器感觉你的代码ok,没有调用不存在的东西,
但是! 当程序运行在设备上时~嘿嘿,系统加载了自己framework.jar中com.android.internal.os包的类文件,调用了自己类中的方法。
恩~这种方法就好像是~空手套白狼。。。。呜呜~程序员都是骗子!
有没有感觉又get了一个新技能?
由于api是隐藏的,相关方面的文档也是少得可怜,人家的东西就算拿来了也不一定会用啊(多么痛的领悟!)
最后的最后!!!!!!!!!!!!!!!!隐藏的api在不同系统版本下可能会产生不可预期的错误,正如前面所说的,其中的一些常量值在不同系统中都可能不一样!!!方法的参数列表也可能有差异!!!所以在用的时候千万要小心翼翼!!!!! 就这么多,收~
相关文章推荐
- 【MDCC2015】 平台与技术-Android专场总结
- Android 代码里动态设置TextView/Button等的文字颜色Seletor
- Android工具类—— android 从SIM卡获取联系人信息
- Android:详情界面左右滑动看更多,ViewPager动态添加Fragment,仿51job详情界面
- Android Studio常用插件——postfix
- android BitmapFacty.Options的用法
- Android Studio常用插件——codota
- Android4.0之后添加虚拟按键方法
- Android快速SDK(25)动画库Animation
- Android M中需要Runtime申请的权限
- Android之SurfaceView学习
- android 快捷键
- android休眠唤醒驱动流程分析【转】
- TextView的升级版———AutoCompleteTextView
- Android 判断一个点是否在封闭的Path内或不规则的图形内
- android webview加载/data/data/pkg/files/目录下html文件
- Android 输入系统之InputReader篇
- android kernel 源码 分析
- AndroidMainfest.xml文件详解
- Android利用Volley异步加载(JSON和图片)完整示例