android:GPS獲取location經緯度並用谷歌解析為地理位置名稱
阿新 • • 發佈:2019-02-09
實現的功能:先獲取本地的經緯度,再根據經緯度,請求googleapis來解析地理位置名稱。
下面的例子,能夠跑起來,親測。
多說無益,看碼。
首先搞一個佈局,其實就是一個textView,一個button,點選button後,在textview展示地理位置資訊。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/tv_location_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/btn_show_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="獲取當前位置" > </Button> </RelativeLayout>
為了方便,我直接把獲取地理位置、經緯度解析,都放到MainActivity裡面了。(其實就是懶,這樣不好,還是該做什麼的類去做什麼,應該分開放的)
package com.example.getlocation; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.Manifest; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.support.v4.app.ActivityCompat; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private LocationManager locationManager;// 位置服務 private Location location;// 位置 private Button btn_show;// 按鈕 private TextView tv_show;// 展示地理位置 public static final int SHOW_LOCATION = 0; private String lastKnowLoc; //監聽地理位置變化,地理位置變化時,能夠重置location LocationListener locationListener = new LocationListener() { @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { tv_show.setText("更新失敗失敗"); } @Override public void onLocationChanged(Location loc) { if (loc != null) { location = loc; showLocation(location); } } }; //這個不用說了,主要是初始化頁面控制元件,並且設定按鈕監聽 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init();// 關聯控制元件,初始化按鈕、展示框 tv_show.setText("地理位置");// 設定預設的位置展示,也就是沒有點選按鈕時的展示 lastKnowLoc = "中國"; // 點選按鈕時去初始化一次當前位置 btn_show.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { locationInit();// 呼叫位置初始化方法 } }); } //這個就是地理位置初始化,主要通過呼叫其他方法獲取經緯度,並設定到location public void locationInit() { try { // 獲取系統服務 locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // 判斷GPS是否可以獲取地理位置,如果可以,展示位置, // 如果GPS不行,再判斷network,還是獲取不到,那就報錯 if (locationInitByGPS() || locationInitByNETWORK()) { // 上面兩個只是獲取經緯度的,獲取經緯度location後,再去呼叫谷歌解析來獲取地理位置名稱 showLocation(location); } else { tv_show.setText("獲取地理位置失敗,上次的地理位置為:" + lastKnowLoc); } } catch (Exception e) { tv_show.setText("獲取地理位置失敗,上次的地理位置為:" + lastKnowLoc); } } // GPS去獲取location經緯度 public boolean locationInitByGPS() { // 沒有GPS,直接返回 if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { return false; } locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener); location = locationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { return true;//設定location成功,返回true } else { return false; } } // network去獲取location經緯度 public boolean locationInitByNETWORK() { // 沒有NETWORK,直接返回 if (!locationManager .isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { return false; } locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 1000, 0, locationListener); location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { return true; } else { return false; } } //控制元件初始化 private void init() { btn_show = (Button) findViewById(R.id.btn_show_location); tv_show = (TextView) findViewById(R.id.tv_location_show); } //這是根據經緯度,向谷歌的API解析髮網絡請求,然後獲取response,這裡超時時間不要太短,否則來不及返回位置資訊,直接失敗了 private void showLocation(final Location loc) { new Thread(new Runnable() { @Override public void run() { try { // 去谷歌的地理位置獲取中去解析經緯度對應的地理位置 StringBuilder url = new StringBuilder(); url.append("http://maps.googleapis.com/maps/api/geocode/json?latlng="); url.append(loc.getLatitude()).append(","); url.append(loc.getLongitude()); url.append("&sensor=false"); // 通過HttpClient去執行HttpGet HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url.toString()); httpGet.addHeader("Accept-Language", "zh-CN"); HttpResponse httpResponse = httpClient.execute(httpGet); if (httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity entity = httpResponse.getEntity(); String response = EntityUtils.toString(entity, "utf-8"); JSONObject jsonObject = new JSONObject(response); JSONArray resultArray = jsonObject .getJSONArray("results"); if (resultArray.length() > 0) { JSONObject subObject = resultArray.getJSONObject(0); String address = subObject .getString("formatted_address"); Message message = new Message(); message.what = SHOW_LOCATION; message.obj = address; lastKnowLoc = address; handler.sendMessage(message); } } else { Message message = new Message(); message.what = SHOW_LOCATION; message.obj = "獲取地理位置失敗,上次的地理位置為:" + lastKnowLoc; handler.sendMessage(message); } } catch (Exception e) { Message message = new Message(); message.what = SHOW_LOCATION; message.obj = "獲取地理位置失敗,上次的地理位置為:" + lastKnowLoc; handler.sendMessage(message); e.printStackTrace(); } } }).start(); } //就是展示下獲取到的地理位置 private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case SHOW_LOCATION: String currentPosition = (String) msg.obj; tv_show.setText(currentPosition); break; default: break; } } }; }
上面基本就做好了,但是還不行,因為獲取使用者地理位置這樣的LBS獲取,需要申請許可權,否則不允許的,程式會報錯。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" />