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程序设计有所帮助。