項目需求討論 - 定位功能小結(jié)

前言:

我們知道我們的APP有可能需要獲取一些地理位置信息。比如定位用戶當前的位置,自動選定城市或者區(qū)域等塘揣。所以這次做個關(guān)于定位的一些總結(jié)。

正文

我們按照二大塊來進行分析:一塊是相關(guān)權(quán)限宿崭,一塊是具體獲取地理信息的相關(guān)代碼亲铡。(而實際開發(fā)代碼中,代碼這二塊是寫在一起的葡兑,單純是為了文章分析從而分開奖蔓。)


1.相關(guān)權(quán)限

這里的權(quán)限我特指了二塊:

  1. 一個是本身我們平常開發(fā)的app需要獲取各種權(quán)限,比如相機等讹堤,這時候我們既然要獲取當前手機的地理信息吆鹤,肯定也要有一個Location相關(guān)的權(quán)限。
  2. 本身手機需要打開相應的定位功能洲守,不然app有權(quán)限獲取疑务,但是手機關(guān)閉了整個的定位功能沾凄,就還是獲取不到。

1.1 app獲取手機權(quán)限

emmm......這塊我覺得應該不需要花更多的時間來說明了吧知允,主要就是:

  1. 檢查權(quán)限 (checkSelfPermission)
  2. 請求權(quán)限(requestPermissions)
  3. 回調(diào)事件處理(onRequestPermissionsResult)
    而我們要申請的權(quán)限無非就是Location相關(guān)的權(quán)限撒蟀。
android.permission.ACCESS_COARSE_LOCATION 
允許一個程序訪問CellID或WiFi熱點來獲取粗略的位置
android.permission.ACCESS_FINE_LOCATION 
允許一個程序訪問精良位置(如GPS)

我們可以看到第一個權(quán)限中的英文單詞COARSE粗略的意思,所以在想要粗略的獲取一個地理位置的時候廊镜,比如我們通過網(wǎng)絡(luò)來獲取牙肝,我們只需要申請這個權(quán)限即可;第二個權(quán)限中的英文單詞FINE說明是精確度高的嗤朴,比如我們需要通過GPS來獲取權(quán)限的時候配椭,我們就需要申請這個權(quán)限。

一般來說我們的app這二個權(quán)限都會申請股缸,因為會需要GPS配合網(wǎng)絡(luò)一起來確定地理位置信息敦姻。

1.2 手機的定位開關(guān)

在確定我們的app本身已經(jīng)具有了定位權(quán)限后镰惦,我們需要知道本身的手機是否已經(jīng)打開了定位功能旺入。

public static boolean isLocServiceEnable(Context context) {
    LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    if (gps || network) {
       return true;
    }
    return false;
}

我們可以看到上面我們提過一般來獲取定位是靠GPS和NetWork二種(為啥是一般呢茵瘾,因為還有一種 PASSIVE拗秘,后面會講到)雕旨。所以我們需要判定這二個功能是否可用。(如果用戶把定位功能給關(guān)了行瑞,那肯定二個都返回false奸腺。)


那這時候假如我們發(fā)現(xiàn)用戶把定位功能關(guān)了。我們肯定需要提示用戶血久,然后協(xié)助用戶跳到該設(shè)置界面突照,從而讓用戶把定位功能打開 (畢竟一般的普通用戶,可能還真的讓他去設(shè)置界面找氧吐,一時半會還真找不到讹蘑,畢竟安卓機型太多末盔,每個地方都不同 )座慰。

比如我們彈出一個彈框陨舱,提示用戶,按確定按鈕的時候跳轉(zhuǎn)到設(shè)置的定位界面:

AlertDialog.Builder builder  = new AlertDialog.Builder(activity);
builder.setMessage("尚未開啟位置定位服務");
builder.setPositiveButton("開啟", new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
            //啟動定位Activity
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
           //比如我們這里設(shè)定requestCode為 1 
            activity.startActivityForResult(intent , 1);
      }
});

builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
       @Override
       public void onClick(DialogInterface dialog, int which) {
       }
});

我們可以看到通過隱式啟動Action為Settings.ACTION_LOCATION_SOURCE_SETTINGS即可,但是這里記得用使用startActivityForResult而不是startActivity蛮粮,我看很多網(wǎng)上的的寫法是用startActivity,單純跳轉(zhuǎn)過去是沒問題莺奔,但是我們需要知道返回的結(jié)果,萬一用戶跳轉(zhuǎn)過去后沒有打開呢变泄。

既然我們用了statActivityForResult來啟動令哟,當我們返回回到自己的app界面的時候,在onActivityForResult中需要來判斷妨蛹,本來因為習慣性思維役听,所以以為自動在onActivityForResult的返回參數(shù)resultCode可以用來判斷乐严,后來發(fā)現(xiàn)不管開啟不開啟艾扮,都是返回RESULT_CANCELED,也就是0奖慌,畢竟在那個設(shè)置界面我們并沒有設(shè)定setResult(xxx)雕欺;所以當判斷了requestCode之后,我們需要重新判斷一次定位是否可用了蹦浦。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
      
    if (requestCode == 1) {
       //我們通過上面提過的方法,再次去判斷是否gps和network的provider都無效撞蜂。
       if (!isLocServiceEnable(MainActivity.this)) {
           Toast.makeText(this, "未開啟定位功能盲镶,請手動選擇地址位置", Toast.LENGTH_LONG).show();
       } else {
           //去獲取具體的地理位置信息...
       }
    } 
}

2 獲取地理位置

我們上面提到了我們想要獲取地理位置的時候,需要具備上面的基本權(quán)限蝌诡,然后才能正常使用我們的相關(guān)api去獲取信息溉贿。

主要是通過```LocationManager``這個類。


但是android.location包下的并不是谷歌推薦的:


翻譯過來就是:此API不是訪問Android位置的推薦方法浦旱。
Google位置服務API是Google Play服務的一部分宇色,是向您的應用添加位置感知功能的首選方式颁湖。 它提供了更簡單的API宣蠕,更高的精度,低功耗的地理圍欄等等甥捺。 如果您當前正在使用android.location API抢蚀,強烈建議您盡快切換到Google Location Services API。

而是推薦the Google Location Services API ,然后你懂得....emmm........

2.1 直接獲取地理信息

使用getLastKnownLocation方法獲攘獭:

//獲取LocationManager的實例對象
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
//獲取支持的provider列表
List<String> providers = locationManager.getProviders(true);
Location bestLocation = null;
//遍歷provider列表
for (String provider : providers) {
    //通過getLastKnowLocation方法來獲取
    Location l = locationManager.getLastKnownLocation(provider);
    if (l == null) {
         continue;
    }
    if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
         // Found best last known location: %s", l);
         bestLocation = l;
     }
}

這里需要注意的是皿曲,為啥通過循環(huán)provider來獲取,比如有些人會問吴侦,我開啟了GPS屋休,我想通過GPS來定位,我不是直接getLastKnowLocation(LocationManager.GPS_PROVIDER)就可以了嗎备韧?理論上是沒問題的劫樟,但是大部分時候獲取到的都是null , 畢竟GPS本身定位時間也會很久,而且如果在室內(nèi)就更加GG了。

所以網(wǎng)上經(jīng)骋慊看到有提問:


當然解決方式也有很多听怕,有些人直接通過while循環(huán),比如一直請求:

while(xxx = null){
  xxx = getLastKnowLocation(LocationManager.GPS_PROVIDER);
}

這還不算坑爹虑绵,我用了華為和小米手機尿瞭,小米手機使用這個GPS來獲取Location,一下子就獲取了翅睛。華為我寫了while循環(huán)声搁,等了很久很久,也還是一直是null捕发。(居然還跟不同牌子手機都有關(guān)系)

所以最終我是遍歷了provider來獲取最佳的地址來解決的疏旨,如果獲取不到GPS定位,也會有network輔助扎酷。

也可以參考相關(guān)的鏈接了解一下:Android 成功 使用GPS獲取當前地理位置(解決getLastKnownLocation 返回 null),不過貌似也沒有找到百分百直接獲取GPS定位獲取信息的方式檐涝。


2.2 監(jiān)視位置變化

使用requestLocationUpdates方法來獲取。

public void requestLocationUpdates(
String provider, 
long minTime, 
float minDistance,
LocationListener listener) 
{

}

我們可以看到傳入provider,最小更新時間法挨,最小的更新距離谁榜,然后就是回調(diào)listener。

所以我們重點在于LocationListener:

mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
             //比如判斷l(xiāng)ocation是否為null,然后根據(jù)Location來轉(zhuǎn)換成相關(guān)的地址位置信息凡纳。
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
                  
        }

        @Override
        public void onProviderEnabled(String provider) {
            
        }

        @Override
        public void onProviderDisabled(String provider) {
                    //比如在provider失效了就取消監(jiān)聽
                    locationManager.removeUpdates(this);
        }
};

切記窃植,在某個你需要的條件下,通過removeUpdates()去取消監(jiān)聽荐糜,比如你可能在onPause中去取消等巷怜。

我們在onLocationChanged方法中獲取到了Location對象,就可以去獲取相關(guān)信息了暴氏。

  1. 通過Location來獲取相關(guān)的經(jīng)緯度:


double latitude = location.getLatitude();
double longitude = location.getLongitude();
  1. 通過Geocoder來把經(jīng)緯度轉(zhuǎn)換成相應的Address集合:


Geocoder geocoder = new Geocoder(context);
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
  1. 最后通過Address對象中的相關(guān)屬性延塑,拼接出自己想要的相關(guān)信息。
address.getCountryName() //國家
address.getPostalCode() //郵編
address.getCountryCode() //國家編碼
address.getAdminArea() //省份
address.getSubAdminArea() //二級省份
address.getThoroughfare() //道路
address.getSubLocality() //二級城市
.......
.......


結(jié)語:

emm.......大家輕噴即可答渔。页畦。。研儒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市独令,隨后出現(xiàn)的幾起案子端朵,更是在濱河造成了極大的恐慌,老刑警劉巖燃箭,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冲呢,死亡現(xiàn)場離奇詭異,居然都是意外死亡招狸,警方通過查閱死者的電腦和手機敬拓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門邻薯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乘凸,你說我怎么就攤上這事厕诡。” “怎么了营勤?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵灵嫌,是天一觀的道長。 經(jīng)常有香客問我葛作,道長寿羞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任赂蠢,我火速辦了婚禮绪穆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虱岂。我一直安慰自己玖院,他們只是感情好,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布量瓜。 她就那樣靜靜地躺著司恳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绍傲。 梳的紋絲不亂的頭發(fā)上扔傅,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音烫饼,去河邊找鬼猎塞。 笑死,一個胖子當著我的面吹牛杠纵,可吹牛的內(nèi)容都是我干的荠耽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼比藻,長吁一口氣:“原來是場噩夢啊……” “哼铝量!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起银亲,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤慢叨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后务蝠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拍谐,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了轩拨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片践瓷。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖亡蓉,靈堂內(nèi)的尸體忽然破棺而出晕翠,到底是詐尸還是另有隱情,我是刑警寧澤寸宵,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布崖面,位于F島的核電站,受9級特大地震影響梯影,放射性物質(zhì)發(fā)生泄漏巫员。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一甲棍、第九天 我趴在偏房一處隱蔽的房頂上張望简识。 院中可真熱鬧,春花似錦感猛、人聲如沸七扰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颈走。三九已至,卻和暖如春咱士,著一層夾襖步出監(jiān)牢的瞬間立由,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工序厉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锐膜,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓弛房,卻偏偏與公主長得像道盏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子文捶,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

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