1. 程式人生 > >android:GPS獲取location經緯度並用谷歌解析為地理位置名稱

android:GPS獲取location經緯度並用谷歌解析為地理位置名稱

實現的功能:先獲取本地的經緯度,再根據經緯度,請求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" />