回 Android手機程式設計人才培訓班 課程時間表

GPS衛星定位

簡介

Android提供兩種定位方式,一種是GPS,另一種是網路定位(Network)。前者用於室外;後者用於室內。

程式範例

  1. 加入權限(AndroidManifest.xml):
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    
    • android.permission.ACCESS_FINE_LOCATION: 使用GPS定位服務
    • android.permission.ACCESS_COARSE_LOCATION: 使用網路定位服務
  2. 將java/res/layout/activity_main.xml版面改成FrameLayout並加入一個TextView用來顯示定位資訊:
    <FrameLayout 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">
    
        <WebView android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView android:id="@+id/info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="20dp"
                android:text="Provider: network\nPosition:" 
                android:textColor="#ff00ff"
                android:shadowDx="3"
                android:shadowDy="3"
                android:shadowColor="#000000"
                android:shadowRadius="3"/>        
    
        </LinearLayout>
    </FrameLayout>
    
  3. 實現LocationListener介面及其抽象方法(可直接由MainActivity來實現):
    • onLocationChanged: 座標更新時會觸發的方法。
    • onProviderDisabled: 定位服務被關閉時會觸發的方法。
    • onProviderEnabled: 定位服務開啟時會觸發的方法。
    • onStatusChanged: 定位服務狀態變更時會觸發的方法。

    實現LocationListener介面:
    public class MainActivity extends ActionBarActivity implements LocationListener
    {
        TextView info = null;
        ...
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 關聯WebView
            myWebView = (WebView)findViewById(R.id.webview);
    
            info = (TextView)findViewById(R.id.info);
    
            ...以下省略...
    
    實現LocationListerner介面方法:
    public class MainActivity extends ActionBarActivity implements LocationListener
    {
        ...以上省略...
    
        // 用來存放目前最新位置
        Location loc = null;
    
        // 接收最新的定位訊息
        @Override
        public void onLocationChanged(Location location)
        {
            // 存下最新位置資訊
            loc = location;
    
            // 取得經緯度
            double lat = location.getLatitude();  // 緯度
            double lng = location.getLongitude(); // 經度
    
            // 更新最新資訊到TextView上
            float acc = location.getAccuracy(); // 單位: 公尺
            float bea = location.getBearing(); // 方向
            float spd = location.getSpeed(); // 速度: 小時/公尺
            float time = location.getTime(); // 該資訊的時間(1970年1月1日到現在經過的毫秒, UTC)
    
            info.setText("Latitude: " + lat + "\n" +
                         "Longitude: " + lng + "\n" +
                         "Accuracy: " + acc + "\n" +
                         "Bearing: " + bea + "\n" +
                         "Speed: " + spd + "\n" +
                         "Time: " + time);
    
            // 呼叫JavaScript
            // 例: javascript:centerAt(25.12345, 33.0987);
            myWebView.loadUrl("javascript:centerAt(" + lat + ", " + lng + ");");
    
            Toast.makeText(this, "位置更新: " + lat + ", " + lng + "(" +
            location.getProvider() + ")", Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void onProviderDisabled(String provider)
        {
            Toast.makeText(this, provider + "被關閉了.", Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void onProviderEnabled(String provider)
        {
            Toast.makeText(this, provider + "被啟動了.", Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void onStatusChanged(String provider, int status, Bundle arg2)
        {
            switch (status)
            {
            case LocationProvider.AVAILABLE:
                Toast.makeText(this, provider + "服務中", Toast.LENGTH_SHORT).show();
                break;
            case LocationProvider.OUT_OF_SERVICE:
                Toast.makeText(this, provider + "沒有服務", Toast.LENGTH_SHORT).show();
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                Toast.makeText(this, provider + "暫時不可使用", Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }
    
  4. 使用LocationManager物件來初始化定位服務:
    public class MainActivity extends ActionBarActivity implements LocationListener
    {
        ...以上省略...
    
        // Android系統透過LocationManager物件來使用定位相關服務
        LocationManager lm = null; 
    
        // 初始化定位服務
        // 需要權限:
        // android.permission.ACCESS_FINE_LOCATION
        // android.permission.ACCESS_COARSE_LOCATION
        private void setupLocationService()
        {
            // 取得LocationManager
            lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    
            // 判斷GPS定位服務或Network定位服務是否有打開
            if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER) &&
            !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
            {
                // 顯示錯誤訊息
                AlertDialog.Builder dlg = new AlertDialog.Builder(this);
                dlg.setTitle("警告");
                dlg.setMessage("請至少開啟GPS或網路來使用定位服務");
                dlg.show();
                return;
            }
    
            // 如果Network是打開的, 則啟動Network定位
            if(lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
            {
                Toast.makeText(this, "NETWORK已開啟 使用NETWORK定位", Toast.LENGTH_SHORT).show();
    
                // 開啟NETWORK定位
                lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, // 要使用的Provider 
                                          1000, // 獲取GPS資訊的時間單位(毫秒), 時間越短會越耗電 
                                          0, // 觸發listener位置改變的距離(公尺), 在該距離之內不做回應
                                          this);
            }
    
            // 如果GPS是打開的, 則啟動GPS定位
            if(lm.isProviderEnabled(LocationManager.GPS_PROVIDER))
            {
                Toast.makeText(this, "GPS已開啟 使用GPS定位", Toast.LENGTH_SHORT).show();
    
                // 開啟GPS定位
                lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, // 要使用的Provider
                                          1000, // 獲取GPS資訊的時間單位(毫秒), 時間越短會越耗電
                                          0, // 觸發listener位置改變的距離(公尺), 在該距離之內不做回應
                                          this);
            }
        }
        
        ... 以下省略...
    }
    
  5. WebViewClient物件中的onPageFinished()方法中初始化定位服務:
    // 初始化定位服務
    setupLocationService();
    
  6. 在Activity的onDestory()生命週期中解除定位服務:
    @Override
    protected void onDestroy() 
    {
        // 關閉定位, 否則定位服務在離開app後仍然會一直定位
        lm.removeUpdates(this);
    
        super.onDestroy();
    }
    

  7. 完成。