Android調(diào)用服務(wù)

前言:

HI阻逮,歡迎來到《每周一博》粱快。從九月開始,我將繼續(xù)每周更新一篇博客叔扼,配合不定期更新的喜馬拉雅事哭,讓自己一直保持學(xué)習(xí)的狀態(tài)。今天是九月第一周瓜富,我先給大家分享一些和定位相關(guān)的知識鳍咱。

Android提供了定位服務(wù)和地理編碼服務(wù),它們分別是由LocationManager和Geocoder來提供的与柑,下面我來分別介紹這2部分內(nèi)容谤辜。

一. LocationManager:

LocationManager系統(tǒng)服務(wù)是位置服務(wù)的核心組件蓄坏,它提供了一系列方法來處理與位置相關(guān)的問題,比如查詢上一個已知位置丑念,定期更新設(shè)備的地理位置涡戳,或者當(dāng)設(shè)備進入給定地理位置附近時,觸發(fā)應(yīng)用指定意圖等渠欺;

(A). 使用LocationManager需要以下過程妹蔽;

1.獲取LocationManager,它不能直接實例化:

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

2.了解LocationProvider:它是位置信息提供者挠将,系統(tǒng)一般提供三種方式獲取地理位置信息:

(1)GPS_PROVIDER:通過 GPS 來獲取地理位置的經(jīng)緯度信息胳岂;
優(yōu)點:獲取地理位置信息精確度高;
缺點:只能在戶外使用舔稀,獲取經(jīng)緯度信息耗時乳丰,耗電;

(2)NETWORK_PROVIDER:通過移動網(wǎng)絡(luò)的基站或者 Wi-Fi 來獲取地理位置内贮;
優(yōu)點:只要有網(wǎng)絡(luò)产园,就可以快速定位,室內(nèi)室外都可夜郁;
缺點:精確度不高什燕;

(3)PASSIVE_PROVIDER:被動接收更新地理位置信息,而不用自己請求地理位置信息竞端。 PASSIVE_PROVIDER 返回的位置是通過其他 providers 產(chǎn)生的屎即,可以查詢 getProvider() 方法決定位置更新的由來,需要 ACCESS_FINE_LOCATION 權(quán)限事富,但是如果未啟用 GPS技俐,則此 provider 可能只返回粗略位置匹配;

獲取provider的方法有g(shù)etProviders统台,getAllProviders雕擂,getBestProvider(根據(jù)一組條件來返回合適的provider)

        List<String> list = locationManager.getProviders(true);
        if (list != null) {
            for (String x : list) {
                Log.e("gzq", "name:" + x);
            }
        }

        LocationProvider lpGps = locationManager.getProvider(LocationManager.GPS_PROVIDER);
        LocationProvider lpNet = locationManager.getProvider(LocationManager.NETWORK_PROVIDER);
        LocationProvider lpPsv = locationManager.getProvider(LocationManager.PASSIVE_PROVIDER);


        Criteria criteria = new Criteria();
        // Criteria是一組篩選條件
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        //設(shè)置定位精準(zhǔn)度
        criteria.setAltitudeRequired(false);
        //是否要求海拔
        criteria.setBearingRequired(true);
        //是否要求方向
        criteria.setCostAllowed(true);
        //是否要求收費
        criteria.setSpeedRequired(true);
        //是否要求速度
        criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
        //設(shè)置電池耗電要求
        criteria.setBearingAccuracy(Criteria.ACCURACY_HIGH);
        //設(shè)置方向精確度
        criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
        //設(shè)置速度精確度
        criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
        //設(shè)置水平方向精確度
        criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH);
        //設(shè)置垂直方向精確度
       
        //返回滿足條件的當(dāng)前設(shè)備可用的provider,第二個參數(shù)為false時返回當(dāng)前設(shè)備所有provider中最符合條件的那個provider贱勃,但是不一定可用
        String mProvider = locationManager.getBestProvider(criteria, true);
        if (mProvider != null) {
            Log.e("gzq", "mProvider:" + mProvider);
        }
    }

打印出來的結(jié)果就是passive井赌,gps,network贵扰;

3.聲明權(quán)限
(1)ACCESS_FINE_LOCATION是精確位置族展,如果使用GPS_PROVIDER或者同時使用GPS_PROVIDER和NETWORK_PROVIDER,需聲明該權(quán)限拔鹰,它對于這兩個provider都是有效的仪缸;
(2)ACCESS_COARSE_LOCATION是粗略位置,該權(quán)限只針對NETWORK_PROVIDER列肢。

4.注冊一個位置監(jiān)聽器來接受結(jié)果

private final class MyLocationListener implements LocationListener{
   
    public void onLocationChanged(Location location) {
        Log.e("gzq", "onLocationChanged" + location.toString());
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
        Log.e("gzq", "onStatusChanged" + status);
    }

    public void onProviderEnabled(String provider) {
        Log.e("gzq", "onProviderEnabled");
    }

    public void onProviderDisabled(String provider) {
        Log.e("gzq", "onProviderDisabled");
    }

}

這個回調(diào)里面有4個方法恰画;
(1)onLocationChanged:當(dāng)位置發(fā)生改變后就會回調(diào)該方法宾茂,經(jīng)緯度相關(guān)信息存在Location里面;
(2)onStatusChanged:我們所采用的provider狀態(tài)改變時會回調(diào)拴还,該狀態(tài)有3種跨晴;
LocationProvider.OUT_OF_SERVICE = 0:無服務(wù)
LocationProvider.AVAILABLE = 2:provider可用
LocationProvider.TEMPORARILY_UNAVAILABLE = 1:provider不可用
(3)onProviderEnabled:當(dāng)provider可用時被觸發(fā),比如定位模式切換到了使用精確位置時GPSProvider就會回調(diào)該方法片林;
(4)onProviderDisabled:當(dāng)provider不可用時被觸發(fā)端盆,比如定位模式切換到了使用使用網(wǎng)絡(luò)定位時GPSProvider就會回調(diào)該方法;

5.獲取位置信息费封,調(diào)用監(jiān)聽方法焕妙,不過在獲取位置前先判斷一下要調(diào)用的provider是否可用;

if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5,10, locationListener);
}

這個方法表明要跟蹤GPS位置的變化弓摘,并且每5秒刷新一次焚鹊,同時兩次的位置的間隔要超過10米;

在不需要位置的時候解注冊監(jiān)聽:

locationManager.removeUpdates(locationListener);

關(guān)于requestLocationUpdates有一些問題需要注意:

(1)剛才我們傳入的是Listener,其實也可以用PendingIntent來代替Listener韧献,當(dāng)位置更新時會通過廣播回調(diào)末患,使用2個鍵KEY_LOCATION_CHANGED和Location來接收位置變化;

(2)參數(shù)這里里可以傳遞一個Looper锤窑,如果不指定的話璧针,則調(diào)用線程必須已經(jīng)是一個Looper線程,比如調(diào)用Activity的主線程渊啰,如果指定了Looper探橱,則在提供的Looper線程上進行回調(diào);

(B). LocationManager還提供了一些其他有用的方法:

1.獲取緩存中的位置信息getLastKnownLocation

Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

該方法不會發(fā)起監(jiān)聽虽抄,返回的是上一次的位置信息,但此前如果沒有位置更新的話独柑,返回的位置信息可能是錯誤的迈窟;

2.獲取一次定位結(jié)果requestSingleUpdate

locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,locationListener忌栅,null);

如果不想一直監(jiān)聽位置信息车酣,那么可以用requestSingleUpdate來實現(xiàn)只請求一次定位,該方法也要在主線程上執(zhí)行索绪;

3.發(fā)送輔助指令sendExtraCommand

mLocationManager.sendExtraCommand("LOC","NOTIFY_DOWNLOAD", extras);

可以通過Bundle參數(shù)來發(fā)送相關(guān)信息湖员;

4.判斷provider是否可用

mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

5.添加地理圍欄

locationManager.addProximityAlert(38.234, 114.234, 5, -1, PendingIntent.getBroadcast(this, 1, new Intent(), 3));

可以設(shè)置一個區(qū)域,當(dāng)進入或離開這個區(qū)域的時候會收到通知瑞驱,前兩個參數(shù)指定一個點娘摔,第三個參數(shù)是半徑,第四個參數(shù)是超時時間唤反,設(shè)置為-1表示不存在超時凳寺,最后一個是廣播接收器鸭津。
觸發(fā)的Intent將使用鍵KEY_PROXIMITY_ENTERING,如果值為true肠缨,則設(shè)備進入鄰近區(qū)域逆趋,如果是false,說明設(shè)備離開該區(qū)域晒奕。


二. Geocoder:

上面介紹了LocationManager的使用闻书,下面介紹下地理編碼的使用。

Geocoder 用于處理地理編碼和反地理編碼脑慧,地理編碼是將街道地址或其他地理位置變換為經(jīng)緯度的過程魄眉。逆向地理編碼是將經(jīng)緯度轉(zhuǎn)換為地址的過程。反地理編碼位置描述中的細(xì)節(jié)數(shù)量可能會有所不同漾橙,例如可能包含最近建筑物的完整街道地址杆融,而另一個可能只包含城市名稱和郵政編碼。

Geocoder 類需要一個未包含在核心Android框架中的服務(wù)霜运。如果平臺中沒有該服務(wù)脾歇,Geocoder查詢方法將返回一個空列表。使用 isPresent() 方法可以來確定Geocoder實現(xiàn)是否存在淘捡。由于國內(nèi)用不了GoogleServices 服務(wù)藕各,因此一般的手機廠商都會在自己的手機內(nèi)內(nèi)置百度或高德地圖服務(wù)。

主要方法有
1.isPresent():判斷當(dāng)前設(shè)備是否內(nèi)置了地理位置服務(wù)焦除,返回 true 表示地理編碼可以使用激况,false為不可使用;

2.getFromLocation():根據(jù)經(jīng)緯度返回對應(yīng)的地理位置信息膘魄,參數(shù)maxResults表示返回地址的數(shù)目乌逐,建議使用1-5;

        Geocoder geocoder = new Geocoder(this);
        boolean flag = Geocoder.isPresent();
        if (flag) {
            try {
                List<Address> addresses = geocoder.getFromLocation(39.345345, 116.345, 1);
                if (addresses.size() > 0) {
                    Address address = addresses.get(0);
                    String sAddress;
                    if (!TextUtils.isEmpty(address.getLocality())) {
                        if (!TextUtils.isEmpty(address.getFeatureName())) {
                            //市和周邊地址
                            sAddress = address.getLocality() + " " + address.getFeatureName();
                        } else {
                            sAddress = address.getLocality();
                        }
                    } else {
                        sAddress = "定位失敗";
                    }
                    Log.e("gzq", "sAddress:" + sAddress);
                }
            } catch (IOException e) {
            }
        }

該方法返回一個List创葡,從中取出第一個元素浙踢,如果有l(wèi)ocality(地址位置)屬性,并且有featureName(地址要素)灿渴,就可以去取相關(guān)信息洛波,比如國家(countryName),郵編(postalCode)骚露,國家編碼(countryCode)蹬挤,省份(adminArea),二級省份(subAdminArea)棘幸,二級城市(subLocality)焰扳,道路(thoroughfare)等;

3.getFromLocationName():返回描述地理位置信息的集合,maxResults是返回地址的數(shù)目蓝翰,建議使用1-5光绕;

        List<Address> addresses = geocoder.getFromLocationName("西二旗", 1);
        if (addresses.size() > 0) {
            //返回當(dāng)前位置,精度可調(diào)
            Address address = addresses.get(0);
            if (address != null) {
                Log.e("gzq", "sAddress:" + address.getLatitude());
                Log.e("gzq", "sAddress:" + address.getLongitude());
            }
        }

Geocoder的使用比較簡單畜份,getFromLocation和getFromLocationName都可以在線程里面執(zhí)行诞帐。

結(jié)尾:

本周給大家分享了客戶端應(yīng)該如何使用定位相關(guān)服務(wù),主要就是使用LocationManger和Geocoder的API爆雹,下周我將走讀LocationMangerService源碼停蕉,詳細(xì)分析定位服務(wù)系統(tǒng)是如何實現(xiàn)的,我們不僅要知道how钙态,還要知道why慧起,下周再見。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末册倒,一起剝皮案震驚了整個濱河市蚓挤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驻子,老刑警劉巖灿意,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異崇呵,居然都是意外死亡缤剧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門域慷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荒辕,“玉大人,你說我怎么就攤上這事犹褒〉种希” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵叠骑,是天一觀的道長李皇。 經(jīng)常有香客問我,道長座云,這世上最難降的妖魔是什么疙赠? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任付材,我火速辦了婚禮朦拖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厌衔。我一直安慰自己璧帝,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布富寿。 她就那樣靜靜地躺著睬隶,像睡著了一般锣夹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苏潜,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天银萍,我揣著相機與錄音,去河邊找鬼恤左。 笑死贴唇,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的飞袋。 我是一名探鬼主播戳气,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼巧鸭!你這毒婦竟也來了瓶您?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤纲仍,失蹤者是張志新(化名)和其女友劉穎呀袱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巷折,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡压鉴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锻拘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片油吭。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖署拟,靈堂內(nèi)的尸體忽然破棺而出婉宰,到底是詐尸還是另有隱情,我是刑警寧澤推穷,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布心包,位于F島的核電站,受9級特大地震影響馒铃,放射性物質(zhì)發(fā)生泄漏蟹腾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一区宇、第九天 我趴在偏房一處隱蔽的房頂上張望娃殖。 院中可真熱鬧,春花似錦议谷、人聲如沸炉爆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芬首。三九已至赴捞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間郁稍,已是汗流浹背赦政。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耀怜,地道東北人昼钻。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像封寞,于是被迫代替她去往敵國和親然评。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容