Android getSystemService用法实例总结
本文实例分析了android getsystemservice用法。分享给大家供大家参考,具体如下:
1. 说明
android的后台运行在很多service,它们在系统启动时被systemserver开启,支持系统的正常工作,比如mountservice监听是否有sd卡安装及移除,clipboardservice提供剪切板功能,packagemanagerservice提供软件包的安装移除及查看等等,应用程序可以通过系统提供的manager接口来访问这些service提供的数据,以下将说明他们的工具流程
2. 举例说明基本流程
以android系统支持sensor(传感器)实例来说明框架层的service和manager是如何配合工作的
1) 什么是sensor
sensor是传感器, 比如控制横竖屏切换利用的就是重力传感器(gsensor), 还有accelerator sensor可取得x, y, z三个轴上的加速度(应用如平衡球, 小猴吃香蕉等)
2) 应用程序调用(以下为关键代码)
sensormanager=(sensormanager)getsystemservice(context.sensor_service); lightsensor = sensormanager.getdefaultsensor(sensor.type_light); sensormanager.registerlistener(sensorlistener, lightsensor, sensormanager.sensor_delay_normal);
3) manager层
a) 提供给应用程序调用的接口,同实与service交互,实现功能
frameworks/base/core/java/android/hardware/sensormanager.java
4) service层
a) 开机时就运行的管理sensor的后台服务
frameworks/base/services/java/com/android/server/sensorservice.java
b) snesor后台服务需要的jni,通过它与系统级交互
frameworks/base/services/jni/com_android_server_sensorservice.cpp
5) 系统层
a) 传感器的头文件,硬件提供商按此文件的定义实现其功能
hardware/libhardware/include/hardware/sensors.h
b) 传感器的系统层实现,与内核交互,此处通常是硬件提供商提供的
hareware/libsensors
6) 内核及硬件层
内核访问硬件,同时以设备文件等方式提供给上层控制接口和传感器数据
3. 系统层实现
1) frameworks/base/core/java/android/*manager.java 对应用的接口
2) frameworks/base/core/jni/ 对应用的接口的jni
3) frameworks/base/services/java/com/android/server/ 后台服务
4) frameworks/base/services/jni/ jni与系统层接口
5) hardware/libhardware/include/ 系统层头文件
6) hardware/libxxx 系统库支持
7) 内核支持
4. 应用程序如何使用
1) 查看系统提供哪些服务
find frameworks/base/core/java/android/ -name *manager.java
此处可以看到调用系统提供服务的入口
2) 一般register listener,事件发生时都收到回调
5. 新建一个service(以froyo为例)
1) 接口:接口供应用调用
frameworks/base/core/java/android/app/contextimpl.java 加服务名与manager对应
frameworks/base/core/java/android/content/context.java 加服务名定义
2) manager:提供服务对应的调用接口
frameworks/base/core/java/android/app/startxxxxmanager.java 实现调用接口
frameworks/base/core/java/android/app/ixxxxmanager.aidl 定义调用接口
frameworks/base/android.mk 加入aidl的编译
3) service:提供后台服务支持
frameworks/base/services/java/com/android/server/xxxxservice.java 服务实现
frameworks/base/services/java/com/android/server/systemserver.java 启动服务
getsystemservice是android很重要的一个api,它是activity的一个方法,根据传入的name来取得对应的object,然后转换成相应的服务对象。以下介绍系统相应的服务。
传入的name | 返回的对象 | 说明
window_service windowmanager 管理打开的窗口程序
layout_inflater_service layoutinflater 取得xml里定义的view
activity_service activitymanager 管理应用程序的系统状态
power_service powermanger 电源的服务
alarm_service alarmmanager 闹钟的服务
notification_service notificationmanager 状态栏的服务
keyguard_service keyguardmanager 键盘锁的服务
location_service locationmanager 位置的服务,如gps
search_service searchmanager 搜索的服务
vebrator_service vebrator 手机震动的服务
connectivity_service connectivity 网络连接的服务
wifi_service wifimanager wi-fi服务
telephony_service teleponymanager 电话服务
wi-fi设计原理:
初始化
在 systemserver 启动的时候,会生成一个 connectivityservice 的实例,
try { log.i(tag, "starting connectivity service."); servicemanager.addservice(context.connectivity_service, new connectivityservice(context)); } catch (throwable e) { log.e(tag, "failure starting connectivity service", e); }
connectivityservice 的构造函数会创建 wifiservice,
if (dbg) log.v(tag, "starting wifi service."); mwifistatetracker = new wifistatetracker(context, handler); wifiservice wifiservice = new wifiservice(context, mwifistatetracker); servicemanager.addservice(context.wifi_service, wifiservice);
wifistatetracker 会创建 wifimonitor 接收来自底层的事件,wifiservice 和 wifimonitor 是整个模块的核心。wifiservice 负责启动关闭 wpa_supplicant、启动关闭 wifimonitor 监视线程和把命令下发给 wpa_supplicant,而 wifimonitor 则负责从 wpa_supplicant 接收事件通知。
1.连接 ap
使能 wifi wirelesssettings 在初始化的时候配置了由 wifienabler 来处理 wifi 按钮,
private void inittoggles() { mwifienabler = new wifienabler( this, (wifimanager) getsystemservice(wifi_service), (checkboxpreference) findpreference(key_toggle_wifi));
当用户按下 wifi 按钮后, android 会调用 wifienabler 的 onpreferencechange, 再由 wifienabler 调用 wifimanager 的 setwifienabled 接口函数,通过 aidl,实际调用的是 wifiservice 的 setwifienabled 函数,wifiservice 接着向自身发送一条 message_enable_wifi 消息,在处理该消息的代码中做真正的使能工作:首先装载 wifi 内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ), 然 后 启 动 wpa_supplicant ( 配 置 文 件 硬 编 码 为 "/data/misc/wifi/wpa_supplicant.conf") 再通过 wifistatetracker 来启动 wifimonitor 中的监视,线程。
private boolean setwifienabledblocking(boolean enable) { final int eventualwifistate = enable ? wifi_state_enabled :wifi_state_disabled; updatewifistate(enable ? wifi_state_enabling : wifi_state_disabling); if (enable) { if (!wifinative.loaddriver()) { log.e(tag, "failed to load wi-fi driver."); updatewifistate(wifi_state_unknown); return false; } if (!wifinative.startsupplicant()) { wifinative.unloaddriver(); log.e(tag, "failed to start supplicant daemon."); updatewifistate(wifi_state_unknown); return false; } mwifistatetracker.starteventloop(); } // success! persistwifienabled(enable); updatewifistate(eventualwifistate); return true; }
当使能成功后,会广播发送 wifi_state_changed_action 这个 intent 通知外界 wifi
已 经 成 功 使 能 了 。 wifienabler 创 建 的 时 候 就 会 向 android 注 册 接 收wifi_state_changed_action,因此它会收到该 intent,从而开始扫描。
private void handlewifistatechanged(int wifistate) { if (wifistate == wifi_state_enabled) { loadconfiguredaccesspoints(); attemptscan(); }
2. 查找 ap
扫描的入口函数是 wifiservice 的 startscan,它其实也就是往 wpa_supplicant 发送 scan 命令。
static jboolean android_net_wifi_scancommand(jnienv* env, jobject clazz) { jboolean result; // ignore any error from setting the scan mode. // the scan will still work. (void)dobooleancommand("driver scan-active", "ok"); result = dobooleancommand("scan", "ok"); (void)dobooleancommand("driver scan-passive", "ok"); return result; }
当 wpa_supplicant 处理完 scan 命令后,它会向控制通道发送事件通知扫描完成,从而
wifi_wait_for_event 函数会接收到该事件,由此 wifimonitor 中的 monitorthread 会被执行来出来这个事件,
void handleevent(int event, string remainder) { case scan_results: mwifistatetracker.notifyscanresultsavailable(); break;
wifistatetracker 则接着广播发送 scan_results_available_action 这个 intent
case event_scan_results_available:
mcontext.sendbroadcast(new intent(wifimanager.scan_results_available_action));
wifilayer 注册了接收 scan_results_available_action 这个 intent,所以它的相关
处理函数 handlescanresultsavailable 会被调用,在该函数中,先会去拿到 scan 的结果(最终是往 wpa_supplicant 发送 scan_result 命令并读取返回值来实现的),
对每一个扫描返回的 ap,wifilayer 会调用 wifisettings 的 onaccesspointsetchanged 函数,从而最终把该 ap 加到 gui 显示列表中。
public void onaccesspointsetchanged(accesspointstate ap, boolean added) { accesspointpreference pref = maps.get(ap); if (added) { if (pref == null) { pref = new accesspointpreference(this, ap); maps.put(ap, pref); } else { pref.setenabled(true); } mapcategory.addpreference(pref); } }
3. 配置 ap 参数
当用户在 wifisettings 界面上选择了一个 ap 后,会显示配置 ap 参数的一个对话框, public boolean onpreferencetreeclick(preferencescreen preferencescreen, preference preference) { if (preference instanceof accesspointpreference) { accesspointstate state = ((accesspointpreference)preference).getaccesspointstate(); showaccesspointdialog(state, accesspointdialog.mode_info); } }
4. 连接
当用户在 acesspointdialog 中选择好加密方式和输入密钥之后,再点击连接按钮,android就会去连接这个 ap。
private void handleconnect() { string password = getenteredpassword(); if (!textutils.isempty(password)) { mstate.setpassword(password); } mwifilayer.connecttonetwork(mstate); }
wifilayer 会先检测这个 ap 是不是之前被配置过,这个是通过向 wpa_supplicant 发送
list_network 命令并且比较返回值来实现的,
// need wificonfiguration for the ap wificonfiguration config = findconfigurednetwork(state);
如果 wpa_supplicant 没有这个 ap 的配置信息,则会向 wpa_supplicant 发送 add_network 命令来添加该 ap,
if (config == null) { // connecting for the first time, need to create it config = addconfiguration(state,add_configuration_enable|add_configuration_save); }
add_network 命 令 会 返 回 一 个 id , wifilayer 再 用 这 个 返 回 的 id 作 为 参 数 向wpa_supplicant 发送 enable_network 命令,从而让 wpa_supplicant 去连接该 ap。
// make sure that network is enabled, and disable others mreenableapsonnetworkstatechange = true; if (!mwifimanager.enablenetwork(state.networkid, true)) { log.e(tag, "could not enable network id " + state.networkid); error(r.string.error_connecting); return false; }
5. 配置 ip 地址
当 wpa_supplicant 成功连接上 ap 之后,它会向控制通道发送事件通知连接上 ap 了,从而wifi_wait_for_event 函数会接收到该事件,由此 wifimonitor 中的 monitorthread 会被执行来出来这个事件,
void handleevent(int event, string remainder) { case connected: handlenetworkstatechange(networkinfo.detailedstate.connected,remainder); break;
wifimonitor 再调用 wifistatetracker 的 notifystatechange,wifistatetracker 则接着会往自身发送 event_dhcp_start 消息来启动 dhcp 去获取 ip 地址,
private void handleconnectedstate() { setpolltimer(); mlastsignallevel = -1; if (!mhaveipaddress & !mobtainingipaddress) { mobtainingipaddress = true; mdhcptarget.obtainmessage(event_dhcp_start).sendtotarget(); } }
然后再广播发送 network_state_changed_action 这个 intent
case event_network_state_changed: if (result.state != detailedstate.disconnected || !mdisconnectpending) { intent = new intent(wifimanager.network_state_changed_action); intent.putextra(wifimanager.extra_network_info, mnetworkinfo); if (result.bssid != null) intent.putextra(wifimanager.extra_bssid, result.bssid); mcontext.sendstickybroadcast(intent); } break;
wifilayer 注册了接收 network_state_changed_action 这个 intent,所以它的相关
处理函数 handlenetworkstatechanged 会被调用,
当 dhcp 拿到 ip 地址之后,会再发送 event_dhcp_succeeded 消息,
private class dhcphandler extends handler { public void handlemessage(message msg) { switch (msg.what) { case event_dhcp_start: if (networkutils.rundhcp(minterfacename, mdhcpinfo)) { event = event_dhcp_succeeded; }
wifilayer 处 理 event_dhcp_succeeded 消 息 , 会 再 次 广 播 发 送network_state_changed_action 这个 intent,这次带上完整的 ip 地址信息。
case event_dhcp_succeeded: mwifiinfo.setipaddress(mdhcpinfo.ipaddress); setdetailedstate(detailedstate.connected); intent = new intent(wifimanager.network_state_changed_action); intent.putextra(wifimanager.extra_network_info, mnetworkinfo); mcontext.sendstickybroadcast(intent); break;
至此为止,整个连接过程完成。
问题:目前的实现不支持 ad-hoc 方式。
希望本文所述对大家android程序设计有所帮助。
推荐阅读
-
Android编程之监听器用法实例分析
-
Android编程中Handler原理及用法实例分析
-
Android编程四大组件之Activity用法实例分析
-
Android编程四大组件之BroadcastReceiver(广播接收者)用法实例
-
Android webview用法实例简析
-
Android编程中自定义dialog用法实例
-
Android编程设置TextView颜色setTextColor用法实例
-
Android编程之自定义AlertDialog(退出提示框)用法实例
-
Android开发之浏览器用法实例详解(调用uc,opera,qq浏览器访问网页)
-
Android编程开发之RadioGroup用法实例