編輯:Android開發實例
這部分對於上層寫應用的朋友來比較熟悉,我們通過一個簡單的應用來分析框架層和底層的實現。
通常編寫一個傳感器的應用程序有以下步驟:
l 通過調用 Context.getSystemService(SENSOR_SERVICE)獲得傳感器服務,實現返回的是封裝了SensorService的SensorManager對象
l 調用SensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION)來獲得指定類型的傳感器對象,方便獲得傳感器的數據
l 通過SensorManager.registerListener注冊SensorEventListener監聽器,監聽獲得的傳感器對象,當傳感器數據提交上來時,能被應用程序得到
l 實現監聽器裡傳感器上報數據的具體操作
由編寫應用程序的步驟可知,所有程序的操作都和SensorManager有關。在開始分析具體實現之前我們先來談談SensorManager概念。
Manager中文直譯是處理者,經理,管理人,總而言之,管事的人。用我的話說就是:有權有錢,屁事不干,指點江山,NB朝天。在Android的服務框架裡Manager被安排作為經理人、領導,它負責自己管轄區的所有操作。類似於公司裡的行政部門,它是一個純粹非盈利服務部門,行政部門經理自己從來不干活,天天指揮別人干這干那,如果其它部門要想使用行政部門的服務,先要向行政經理提申請,申請通過了,安排具體人員為你服務。我們分析的是Sensor服務,Sensor服務用戶程序不能直接訪問,要通過SensorManager來訪問,也就是說SensorManager是SensorService提供服務接口的封裝。
通常在Android的Manager裡都會維護對其管理Service的引用,用戶程序提出Service操作申請,Manager將操作申請交由其管理的Service處理,然後將處理結果再交給用戶程序或回調用戶注冊的監聽接口。
總結:
1) Manager是應用程序直接面對的接口
2) Manager裡維護對應的Service
3) 應用程序不能直接訪問Service
為什麼要這麼設計??
使用Manager機制的好處是顯而易見的:
l Service是服務,服務是所有應用共享,不能屬於某一個具體的進程,即:Android程序。
l 基於第一點,Android應用與Service在不同進程,它們之間必然要進行通信,要使用IPC,即:進程間通信,而框架的作用是讓應用程序快速開發提供API,不可能讓進程間通信的代碼出現在Android應用中,這些所謂的後台操作不能讓程序開發者感知到,即:隱藏通信手段與細節。
既然如此,那Google就給我們寫一個Manager類,把共享服務隱藏起來,只暴露操作接口,操作細節,IPC細節統統後台去。
OK,理解了這個,可以看得出來,我們的之前寫的LedHAL是如此的弱智,如此的沒有規范,如此的不考慮框架設計,如此的不復用代碼,如此…,太多了,沒有辦法,慢慢在後面再優化吧,差不多了,開始吧。
前面說了,使用Sensor服務要用SensorManager,讓我們來看看一個簡單應用的代碼,再逐漸展開。
public class SensorAppDemoActivity extends Activity implementsSensorEventListener{
private TextViewmTextView;
/** Calledwhen the activity is first created. */
@Override
public voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView= (TextView) findViewById(R.id.mTextView);
// 得到SensorManager
SensorManager sm = (SensorManager)this.getSystemService(SENSOR_SERVICE);
// 獲得指定類型的傳感器對象
SensortempSensor = sm.getDefaultSensor(Sensor.TYPE_TEMPERATURE);
// 注冊傳感器對象的監聽器
sm.registerListener(this, tempSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public voidonAccuracyChanged(Sensor sensor, int accuracy) {
// TODOAuto-generated method stub
// 未實現該方法
}
@Override
public void onSensorChanged(SensorEvent event) {
// TODOAuto-generated method stub
mTextView.setText("Currenttemperature is :" + event.values[0]);
}
}
上面代碼很簡單,得到溫度傳感器對象後,注冊傳感器事件監聽器,當數據變化時在Activity上的TextView上顯示溫度。
現在我們分析每個步驟框架的實現:
先來看Context.getSystemService(SENSOR_SERVICE)。
上面代碼裡getSystemService(String)是在當前Activity裡直接調用的,說明它不是Activity的方法就是其父類的方法,按照繼承關系向上查找:
@frameworks/base/core/java/android/app/ContextImpl.java
@Override
public Object getSystemService(String name) {
ServiceFetcherfetcher = SYSTEM_SERVICE_MAP.get(name);
returnfetcher == null ? null : fetcher.getService(this);
}
這是什麼?我恨Android新版本的代碼,沒有老版本的看著簡單。先來看下SYSTEM_SERVICE_MAP是什麼東西,看樣子像映射關系:
private static final HashMap<String,ServiceFetcher> SYSTEM_SERVICE_MAP =
newHashMap<String, ServiceFetcher>();
SYSTEM_SERVICE_MAP其實是一個哈希鍵值映射表,其Key為String類型,Value為ServiceFetcher類型,而我們獲得服務時通過服務名來查找一個ServiceFetcher類型,並返回ServiceFetcher.getService()的結果作為SensorManager。
static class ServiceFetcher {
intmContextCacheIndex = -1;
publicObject getService(ContextImpl ctx) {
// mServiceCache是ArrayList<Object>類型對象
ArrayList<Object> cache =ctx.mServiceCache;
Object service;
synchronized (cache) {
// 對於新創建的Activity mServiceCache裡沒有元素,所以size為0
if (cache.size() == 0) {
// Initialize the cache vector on first access.
// At this point sNextPerContextServiceCacheIndex
// is the number of potential services that are
// cached per-Context.
// sNextPerContextServiceCacheIndex為每個Android服務的索引值
for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
cache.add(null); // 添加null對象
}
}else { // size不為0的時候,即,之前已經調用過getSystemService
service = cache.get(mContextCacheIndex);
if (service != null) {
return service; // 直接拿到之前添加的對象返回
}
}
service = createService(ctx); // cache.size=0並且已經添加了一個null對象到cache裡
cache.set(mContextCacheIndex, service); // 設置新創建的服務添加到cache裡
return service; // 返回該服務
}
}
publicObject createService(ContextImpl ctx) { // 必須實現的方法
thrownew RuntimeException("Not implemented");
}
}
通過分析代碼可知,在ContextImpl類裡維護了一個ArrayList<Object>對象,其裡面保存著所有注冊的Service對象,並且Service對象的獲得和創建由ServiceFether來封裝,該類就兩個方法:createService和getService,而createService是未實現的方法。createSerive的實現在後面:
private static int sNextPerContextServiceCacheIndex =0;
private static void registerService(String serviceName, ServiceFetcher fetcher){
if(!(fetcher instanceof StaticServiceFetcher)) { //是否為StaticServiceFetcher的對象
fetcher.mContextCacheIndex =sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher); // 添加到SYSTEM_SERVICE_MAP鍵值表裡
}
static {
…
registerService(POWER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(service, ctx.mMainThread.getHandler());
}});
…
registerService (SENSOR_SERVICE,new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new SensorManager(ctx.mMainThread.getHandler().getLooper());
}});
…
}
好家伙,一下子在靜態初始化語句塊裡通過私有方法registerService注冊了30多個服務,其第二個參數為ServiceFetcher類型,每個注冊的服務都是匿名內部類,都實現了createService方法,在createService方法裡創建了SensorManager對象,該對象和Activity的Looper共享消息隊列。
總結下吧:
用戶程序調用getSystemService(SENSOR_SERVICE),其實現在ContextImpl.java中,在其實實現中從SYSTEM_SERVICE_MAP鍵值表查找與SENSOR_SERVICE鍵對應的對象ServiceFetcher,調用ServiceFetcher.getService方法得到SensorManager對象,而ContextImpl對象裡還維護著一個ServiceCache,如果某個服務被get過一次,就會被記錄在這個所謂緩存裡,ServiceFetcher.getService先查找緩存裡有沒有Cache的Object,如果沒有,則調用自己的createService方法創建這個Object,而createService沒有實現,其在registerService注冊服務時創建ServiceFetcher匿名內部類時實現,並且將注冊的服務添加到SYSTEM_SERVICE_MAP中,在創建SensorManager對象時,它和Activity共享了一個Looper。
總而言之,言而總之,在getSystemService(SENSOR_SERVICE)裡,創建了SensorManager對象並且和Activity共享Looper。
轉自:http://blog.csdn.net/mr_raptor/article/details/8090508
Android原生控件只有橫向進度條一種,而且沒法變換樣式,比如原生rom的樣子 很丑是吧,當偉大的產品設計要求更換前背景,甚至縱向,甚至圓弧狀的,咋辦,比如:
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個
andriod短信整合備份發送到gmail郵箱,需要在andoid手機配置好gmail郵箱 github代碼 https://github.com/zhwj184