Android getSystemService用法实例总结
本文实例分析了AndroidgetSystemService用法。分享给大家供大家参考,具体如下:
1.说明
android的后台运行在很多service,它们在系统启动时被SystemServer开启,支持系统的正常工作,比如MountService监听是否有SD卡安装及移除,ClipboardService提供剪切板功能,PackageManagerService提供软件包的安装移除及查看等等,应用程序可以通过系统提供的Manager接口来访问这些Service提供的数据,以下将说明他们的工具流程
2.举例说明基本流程
以android系统支持sensor(传感器)实例来说明框架层的service和manager是如何配合工作的
1)什么是sensor
sensor是传感器,比如控制横竖屏切换利用的就是重力传感器(gsensor),还有acceleratorsensor可取得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)查看系统提供哪些服务
findframeworks/base/core/java/android/-name*Manager.java
此处可以看到调用系统提供服务的入口
2)一般registerlistener,事件发生时都收到回调
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,"StartingConnectivityService.");
ServiceManager.addService(Context.CONNECTIVITY_SERVICE,new
ConnectivityService(context));
}catch(Throwablee){
Log.e(TAG,"FailurestartingConnectivityService",e);
}
ConnectivityService的构造函数会创建WifiService,
if(DBG)Log.v(TAG,"StartingWifiService."); mWifiStateTracker=newWifiStateTracker(context,handler); WifiServicewifiService=newWifiService(context,mWifiStateTracker); ServiceManager.addService(Context.WIFI_SERVICE,wifiService);
WifiStateTracker会创建WifiMonitor接收来自底层的事件,WifiService和WifiMonitor是整个模块的核心。WifiService负责启动关闭wpa_supplicant、启动关闭WifiMonitor监视线程和把命令下发给wpa_supplicant,而WifiMonitor则负责从wpa_supplicant接收事件通知。
1.连接AP
使能WIFIWirelessSettings在初始化的时候配置了由WifiEnabler来处理Wifi按钮,
privatevoidinitToggles(){
mWifiEnabler=newWifiEnabler(
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中的监视,线程。
privatebooleansetWifiEnabledBlocking(booleanenable){
finalinteventualWifiState=enable?WIFI_STATE_ENABLED:WIFI_STATE_DISABLED;
updateWifiState(enable?WIFI_STATE_ENABLING:WIFI_STATE_DISABLING);
if(enable){
if(!WifiNative.loadDriver()){
Log.e(TAG,"FailedtoloadWi-Fidriver.");
updateWifiState(WIFI_STATE_UNKNOWN);
returnfalse;
}
if(!WifiNative.startSupplicant()){
WifiNative.unloadDriver();
Log.e(TAG,"Failedtostartsupplicantdaemon.");
updateWifiState(WIFI_STATE_UNKNOWN);
returnfalse;
}
mWifiStateTracker.startEventLoop();
}
//Success!
persistWifiEnabled(enable);
updateWifiState(eventualWifiState);
returntrue;
}
当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION这个Intent通知外界WIFI
已经成功使能了。WifiEnabler创建的时候就会向Android注册接收WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。
privatevoidhandleWifiStateChanged(intwifiState){
if(wifiState==WIFI_STATE_ENABLED){
loadConfiguredAccessPoints();
attemptScan();
}
2.查找AP
扫描的入口函数是WifiService的startScan,它其实也就是往wpa_supplicant发送SCAN命令。
staticjbooleanandroid_net_wifi_scanCommand(JNIEnv*env,jobjectclazz)
{
jbooleanresult;
//Ignoreanyerrorfromsettingthescanmode.
//Thescanwillstillwork.
(void)doBooleanCommand("DRIVERSCAN-ACTIVE","OK");
result=doBooleanCommand("SCAN","OK");
(void)doBooleanCommand("DRIVERSCAN-PASSIVE","OK");
returnresult;
}
当wpa_supplicant处理完SCAN命令后,它会向控制通道发送事件通知扫描完成,从而
wifi_wait_for_event函数会接收到该事件,由此WifiMonitor中的MonitorThread会被执行来出来这个事件,
voidhandleEvent(intevent,Stringremainder){
caseSCAN_RESULTS:
mWifiStateTracker.notifyScanResultsAvailable();
break;
WifiStateTracker则接着广播发送SCAN_RESULTS_AVAILABLE_ACTION这个Intent
caseEVENT_SCAN_RESULTS_AVAILABLE:
mContext.sendBroadcast(newIntent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
WifiLayer注册了接收SCAN_RESULTS_AVAILABLE_ACTION这个Intent,所以它的相关
处理函数handleScanResultsAvailable会被调用,在该函数中,先会去拿到SCAN的结果(最终是往wpa_supplicant发送SCAN_RESULT命令并读取返回值来实现的),
List<ScanResult>list=mWifiManager.getScanResults();
对每一个扫描返回的AP,WifiLayer会调用WifiSettings的onAccessPointSetChanged函数,从而最终把该AP加到GUI显示列表中。
publicvoidonAccessPointSetChanged(AccessPointStateap,booleanadded){
AccessPointPreferencepref=mAps.get(ap);
if(added){
if(pref==null){
pref=newAccessPointPreference(this,ap);
mAps.put(ap,pref);
}else{
pref.setEnabled(true);
}
mApCategory.addPreference(pref);
}
}
3.配置AP参数
当用户在WifiSettings界面上选择了一个AP后,会显示配置AP参数的一个对话框,
publicbooleanonPreferenceTreeClick(PreferenceScreenpreferenceScreen,Preferencepreference){
if(preferenceinstanceofAccessPointPreference){
AccessPointStatestate=((AccessPointPreference)preference).getAccessPointState();
showAccessPointDialog(state,AccessPointDialog.MODE_INFO);
}
}
4.连接
当用户在AcessPointDialog中选择好加密方式和输入密钥之后,再点击连接按钮,Android就会去连接这个AP。
privatevoidhandleConnect(){
Stringpassword=getEnteredPassword();
if(!TextUtils.isEmpty(password)){
mState.setPassword(password);
}
mWifiLayer.connectToNetwork(mState);
}
WifiLayer会先检测这个AP是不是之前被配置过,这个是通过向wpa_supplicant发送
LIST_NETWORK命令并且比较返回值来实现的,
//NeedWifiConfigurationfortheAP WifiConfigurationconfig=findConfiguredNetwork(state);
如果wpa_supplicant没有这个AP的配置信息,则会向wpa_supplicant发送ADD_NETWORK命令来添加该AP,
if(config==null){
//Connectingforthefirsttime,needtocreateit
config=addConfiguration(state,ADD_CONFIGURATION_ENABLE|ADD_CONFIGURATION_SAVE);
}
ADD_NETWORK命令会返回一个ID,WifiLayer再用这个返回的ID作为参数向wpa_supplicant发送ENABLE_NETWORK命令,从而让wpa_supplicant去连接该AP。
//Makesurethatnetworkisenabled,anddisableothers
mReenableApsOnNetworkStateChange=true;
if(!mWifiManager.enableNetwork(state.networkId,true)){
Log.e(TAG,"CouldnotenablenetworkID"+state.networkId);
error(R.string.error_connecting);
returnfalse;
}
5.配置IP地址
当wpa_supplicant成功连接上AP之后,它会向控制通道发送事件通知连接上AP了,从而wifi_wait_for_event函数会接收到该事件,由此WifiMonitor中的MonitorThread会被执行来出来这个事件,
voidhandleEvent(intevent,Stringremainder){
caseCONNECTED:
handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);
break;
WifiMonitor再调用WifiStateTracker的notifyStateChange,WifiStateTracker则接着会往自身发送EVENT_DHCP_START消息来启动DHCP去获取IP地址,
privatevoidhandleConnectedState(){
setPollTimer();
mLastSignalLevel=-1;
if(!mHaveIPAddress&!mObtainingIPAddress){
mObtainingIPAddress=true;
mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget();
}
}
然后再广播发送NETWORK_STATE_CHANGED_ACTION这个Intent
caseEVENT_NETWORK_STATE_CHANGED:
if(result.state!=DetailedState.DISCONNECTED||!mDisconnectPending){
intent=newIntent(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消息,
privateclassDhcpHandlerextendsHandler{
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseEVENT_DHCP_START:
if(NetworkUtils.runDhcp(mInterfaceName,mDhcpInfo)){
event=EVENT_DHCP_SUCCEEDED;
}
WifiLayer处理EVENT_DHCP_SUCCEEDED消息,会再次广播发送NETWORK_STATE_CHANGED_ACTION这个Intent,这次带上完整的IP地址信息。
caseEVENT_DHCP_SUCCEEDED: mWifiInfo.setIpAddress(mDhcpInfo.ipAddress); setDetailedState(DetailedState.CONNECTED); intent=newIntent(WifiManager.NETWORK_STATE_CHANGED_ACTION); intent.putExtra(WifiManager.EXTRA_NETWORK_INFO,mNetworkInfo); mContext.sendStickyBroadcast(intent); break;
至此为止,整个连接过程完成。
问题:目前的实现不支持Ad-hoc方式。
希望本文所述对大家Android程序设计有所帮助。