2014年6月3日

android 使用google map API v2 顯示地圖

android 使用google map API v2 顯示地圖

要利用google 所提供的map api來顯示地圖。

在測試程式之前,有一先準備工作要先完成,可以先參考這個網址: http://www.cnblogs.com/mengdd/archive/2013/01/01/2841390.html

準備好後,就可以寫個測試程式來踹看看。

先建立一個android project,將它命名為googlemaptest。

AndroidManifaset.xml

<?xml version="1.0" encoding= "utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.googlemaptest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion= "14"
        android:targetSdkVersion= "14" />

    <permission
        android:name= "com.example.mapdemo.permission.MAPS_RECEIVE"
        android:protectionLevel= "signature" />

    <uses-feature
        android:glEsVersion= "0x00020000"
        android:required= "true" />

    <uses-permission android:name= "com.example.mapdemo.permission.MAPS_RECEIVE" />
    <uses-permission android:name= "com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name= "android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name= "android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name ="android.permission.INTERNET" />
    <uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup= "true"
        android:icon= "@drawable/ic_launcher"
        android:label= "@string/app_name"
        android:theme= "@style/AppTheme" >
        <activity
            android:name= "com.example.googlemaptest.MainActivity"
            android:label= "@string/app_name" >
            <intent-filter >
                <action android:name= "android.intent.action.MAIN" />

                <category android:name= "android.intent.category.LAUNCHER" />
            </intent-filter >
        </activity >

        <meta-data
            android:name= "com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name= "com.google.android.maps.v2.API_KEY"
            android:value="yourAPI_KEY" />
    </application >

</manifest>

要加入的東西不少

<permission
    android:name= "com.example.mapdemo.permission.MAPS_RECEIVE"
    android:protectionLevel= "signature" />

<uses-feature
    android:glEsVersion= "0x00020000"
    android:required= "true" />

<uses-permission android:name= "com.example.mapdemo.permission.MAPS_RECEIVE" />
<uses-permission android:name= "com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name= "android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name= "android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" />

在application 裡加入

<meta-data
    android:name= "com.google.android.gms.version"
    android:value ="@integer/google_play_services_version" />
<meta-data
    android:name= "com.google.android.maps.v2.API_KEY"
    android:value ="yourAPI_KEY" />

activity_main.xml

<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"
    tools:context=".MainActivity" >

    <RelativeLayout
        android:id= "@+id/topbar1"
        android:layout_width= "fill_parent"
        android:layout_height= "wrap_content"
        android:background= "#00666666" >

        <Button
            android:id= "@+id/btn_query"
            android:layout_width= "wrap_content"
            android:layout_height= "wrap_content"
            android:layout_alignParentRight="true"
            android:text= "查詢"
            android:textSize= "16sp" />

        <EditText
            android:id= "@+id/et_address"
            android:layout_width= "wrap_content"
            android:layout_height= "wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_toLeftOf= "@+id/btn_query"
            android:ems= "10"
            android:inputType= "textMultiLine" />

    </RelativeLayout >

    <fragment
        android:id= "@+id/map"
        android:layout_width= "match_parent"
        android:layout_height= "match_parent"
        android:layout_below= "@+id/topbar1"
        class= "com.google.android.gms.maps.MapFragment" />

在xml中配置一個輸入地址的文字框,一個查詢按鈕,和一個顯示地圖的map fragment。

MainActivity.java

 private EditText et_address ;
 private Button btn_query;
 private GoogleMap map;
 private LocationManager mgr;
 private LocationListener mLocationListenerGPS;
 private LocationListener mLocationListenerNETWORK;
 private final int TIMEOUT_SEC = 20;
 private int currentTime = 0;
 private Handler handler = new Handler();
 private boolean getLocationFlag = false;
 private LatLng START = null; // 啟始座標

 @Override
 protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout. activity_main);
       et_address = (EditText) this.findViewById(R.id. et_address);

       // 先打開GPS定位
       map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map ))
                 .getMap();
       map.setMyLocationEnabled( true);
       mgr = (LocationManager) getSystemService(LOCATION_SERVICE );
       getGps();

 }

 public void getGps () {

       getLocationFlag = false;
       initLocationListener();
       startTimeoutMechanism();

       if (!mgr.isProviderEnabled(LocationManager. GPS_PROVIDER)) {

            Log. d("GpsTools!" , "gps not open!!!" );
            Toast. makeText( this, "GPS衛星定位尚未開啟\n請先開啟GPS衛星定位尚未開啟" ,
                       Toast. LENGTH_LONG).show();
       } else {
             mgr.requestLocationUpdates(LocationManager. GPS_PROVIDER, 0, 0,
                        mLocationListenerGPS);
       }

       NetworkTools networkTools = new NetworkTools();
       if (!networkTools.checkInternetConnection( this)) {
            Log. d("GpsTools!" , "network not open!!!" );
       } else {
             mgr.requestLocationUpdates(LocationManager. NETWORK_PROVIDER, 0, 0,
                        mLocationListenerNETWORK);
       }
 }

 private void stopGps() {
        mgr.removeUpdates( mLocationListenerNETWORK);
        mgr.removeUpdates( mLocationListenerGPS);
 }

 private void initLocationListener() {
        mLocationListenerGPS = new LocationListener() {
             @Override
             public void onLocationChanged(Location location) {
                 //設定位置
                 setLocation(location);
            }

             @Override
             public void onProviderDisabled(String provider) {
                 Log. d("mLocationListenerGPS" , "onProviderDisabled" );
            }

             @Override
             public void onProviderEnabled(String provider) {
                 Log. d("mLocationListenerGPS" , "onProviderEnabled" );
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                 Log. d("mLocationListenerGPS" , "onStatusChanged" );
            }
       };

       mLocationListenerNETWORK = new LocationListener() {
             @Override
             public void onLocationChanged(Location location) {
                 //設定位置
                 setLocation(location);
            }

            @Override
            public void onProviderDisabled(String provider) {
                 Log. d("mLocationListenerNETWORK" , "onProviderDisabled" );
            }

            @Override
            public void onProviderEnabled(String provider) {
                 Log. d("mLocationListenerNETWORK" , "onProviderEnabled" );
            }

            @Override
            public void onStatusChanged(String provider, int status,
                       Bundle extras) {
                 Log. d("mLocationListenerNETWORK" , "onStatusChanged" );
            }

       };
 }

 private Runnable timeOutRunnable = new Runnable() {
        public void run() {
            Log. d("GpsTools" , "" + currentTime );
             currentTime++;
             if ( currentTime > TIMEOUT_SEC) {
                 //停止定位
                 stopGps();
                 getLocationFlag = true;
            }

             if (! getLocationFlag) {
                  // 如為false,表示尚未取得,再試一次
                  handler.postDelayed( this, 1000);
            } else {

            }

       }
 };

 private void startTimeoutMechanism() {
        handler.postDelayed( timeOutRunnable, 1000);
 }



 private void setLocation (Location location) {
       String addrline = null;
       Double longitude = null;
       Double latitude = null;

       Log. d("GpsTools" , "longitude" + location.getLongitude());
       Log. d("GpsTools" , "latitude" + location.getLatitude());

       try {
            Geocoder gc = new Geocoder(MainActivity. this,
                       Locale. TRADITIONAL_CHINESE); // 地區:台灣
             // 自經緯度取得地址
            List<Address> lstAddress = gc.getFromLocation(
                       location.getLatitude(), location.getLongitude(), 1);
            Address address = lstAddress.get(0);
            addrline = address.getAddressLine(0);

            et_address.setText(addrline); //顯示定位後的地址

            longitude = address.getLongitude();
            latitude = address.getLatitude();
       } catch (Exception e) {
            e.printStackTrace();
       }

       if (addrline != null) {
            stopGps();
             // 取到位置了,將flag設為true,讓timeout機制不要再跑了
             getLocationFlag = true;
             START = new LatLng(latitude, longitude);
             setMapMarker( "現在位置" );
       }
 }

 private void setMapMarker(String addrStr) {
       if ( map != null) {
            map.clear();
            Marker note1 = map.addMarker( new MarkerOptions().position(START).title(addrStr));
       }

       // 設定中心點
       CameraUpdate center = CameraUpdateFactory.newLatLng(START);
       map.moveCamera(center);
       map.animateCamera(CameraUpdateFactory. zoomTo(15), 1000, null );

       // 也可以用這個方法取代上面設定中心點
       // map.moveCamera(CameraUpdateFactory.newLatLngZoom(START, 15));
       //

 }

加一個class NetworkTools.java

package com.example.googlemaptest;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class NetworkTools {
     public boolean checkInternetConnection(Context c){
          ConnectivityManager cm=(ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
          NetworkInfo ni=cm.getActiveNetworkInfo();
          if(ni!=null && ni.isConnected()){
               // System.out.println("ni.isConnected() = "+ni.isConnected());
               return ni.isConnected();
          }else{
               // System.out.println("ni.isConnected() = "+ni.isConnected());
               return false;
          }
     }
}

執行測試程式,如果順利的話,應該可以定位到目前位置,在欄位顯示大略地址,並在地圖上顯示節點和抬頭說明。

我們也可以輸入地址來查詢地址: 接著在MainActivity, 也加入一個Method:

private void getLatLngByAddr() {

    Geocoder gc = new Geocoder(this, Locale.TRADITIONAL_CHINESE); // 地區:台灣

    try {
        List<Address> addresses = gc.getFromLocationName(et_address
                .getText().toString().trim(), 1);

        if (addresses != null && !addresses.isEmpty()) {
            double latitude = ((Address) addresses.get(0)).getLatitude();
            double longitude = ((Address) addresses.get(0)).getLongitude();
            String addrline = ((Address) addresses.get(0))
                    .getAddressLine(0);

            if (addrline != null) {
                START = new LatLng(latitude, longitude);
                setMapMarker(et_address.getText().toString().trim());
            }
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

在onCreate Method中加入

btn_query = (Button) this.findViewById(R.id. btn_query);

        btn_query.setOnClickListener( new OnClickListener() {

             @Override
             public void onClick(View v) {
                 //getLatLngByAddr();
            }
        });

執行程式再試試看,應該可以用地址查詢位置了。