Activity啟動Service – 以GPS定位為例

Activity啟動Service – 以GPS定位為例

Activity啟動Service – 以GPS定位為例

 

資料來源:http://mrandroidking.blogspot.tw/2011/02/activityservice-gps.html

 

 

Service以背景服務方式提供程序的運作執行. 在其運作執行期間, 並不能直接處理使用者介面的內容, 完全以背景服務方式執行. 如果必提供資料給前景的Activity, 則必須以一個android.os.Handler物件負責處理. 或是呼叫 sendBroadcast()方法送出一個Broadcast, 而由Activity預先產生的BroadcastReceiver負責接受, 進而處理使用者介面.

 

啟動Service的方式通常是呼叫Context.startService()方法.

 

 

 

一個Activity中有兩個按鈕, 分別處理啟動GPS的啟動與停止, 而有一個文字介面呈現啟動的GPS所傳回相關的資訊. 當啟動按鈕按下之後, 將會由Activity呼叫startService()啟動一個Service的生命周期:
1. onCreate()
2. onStartCommand()
3. onDestroy()

通常會在onCreate()中進行相關的初始化的程序, 而onStartCommand()負責主要的服務程序, 當Activity呼叫了stopService(), 就會使該Service進入到onDestroy()的程序.

此時Service負責蒐集目前GPS相關資訊, 並且將資料以sendBroadcast()方法發送給Activity, Activity會預先一個BroadcastReceiver務件負責接收, 並且將資料呈現在文字介面.

 

 

 

首先, 先簡單處理顯示的版面配置:

 

main.xml

 

<?xml version=”1.0″ encoding=”utf-8″?>

 

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”

 

    android:orientation=”vertical”

 

    android:layout_width=”fill_parent”

 

    android:layout_height=”fill_parent”

 

    >

 

 <Button

 

  android:id=”@+id/service” 

 

     android:layout_width=”fill_parent”

 

     android:layout_height=”wrap_content”

 

     android:text=”Service”

 

     />

 

 <Button

 

  android:id=”@+id/stop” 

 

     android:layout_width=”fill_parent”

 

     android:layout_height=”wrap_content”

 

     android:text=”Stop”

 

     />

 

 <TextView

 

  android:id=”@+id/info” 

 

     android:layout_width=”fill_parent”

 

     android:layout_height=”wrap_content”

 

     />

 

</LinearLayout>

 


接著在Activity中加上一個自訂的BroadcastReceiver:

 

private class MyReceiver extends BroadcastReceiver {

 

  @Override

 

  public void onReceive(Context context, Intent intent) {

 

   double Lat = intent.getDoubleExtra(“Lat”, 0.0);

 

   double Long = intent.getDoubleExtra(“Long”, 0.0);

 

   float Accuracy = intent.getFloatExtra(“Accuracy”, 0.0f);

 

   float Bearing = intent.getFloatExtra(“Bearing”, 0.0f);

 

   float Speed = intent.getFloatExtra(“Speed”, 0.0f);

 

   long Time = intent.getLongExtra(“Time”, 0);

 

  

 

   info.setText(“Lat: ” + Lat + “\n” +

 

      “Long” + Long + “\n” +

 

      “Accuracy” + Accuracy + “\n” +

 

      “Bearing” + Bearing + “\n” +

 

      “Speed” + Speed + “\n” +

 

      “Time” + Time + “\n”

 

      );

 

  }    

 

 }

 


上段程式重點如下:

 
  • 繼承 extends BroadcastReceiver, 並Override onReceive()方法
  • 假設將會收到一個Intent物件, 其內含地理位置資訊資料.
  • 取出資料後, 呈現在 info 的TextView物件中.
 

回到Activity中:

 

MyReceiver receiver = new MyReceiver();

 

IntentFilter filter = new IntentFilter(“MyFilter”);

 

registerReceiver(receiver, filter);

 

 

 

上段程式重點如下:

 
  • 建構出前段程式中自訂的 MyReceive 物件
  • 建構特定的 IntentFilter 物件, 只處理 “MyFilter” 的 Intent.
  • 註冊 Receiver, 之後只要收到 Broadcast 後, 觸發 onReceive() 方法
 

將按鈕及其他部份處理上去:

 

package tw.brad.android.test.ServiceTest;

 

 

 

import android.app.Activity;

 

import android.content.BroadcastReceiver;

 

import android.content.Context;

 

import android.content.Intent;

 

import android.content.IntentFilter;

 

import android.os.Bundle;

 

import android.view.View;

 

import android.view.View.OnClickListener;

 

import android.widget.Button;

 

import android.widget.TextView;

 

 

 

public class ServiceTest extends Activity {

 

    private Button service,stop;

 

    private TextView info;

 

    private MyReceiver receiver;

 

    private IntentFilter filter;

 

    @Override

 

    public void onCreate(Bundle savedInstanceState) {

 

        super.onCreate(savedInstanceState);

 

        setContentView(R.layout.main);

 

       

 

        service = (Button)findViewById(R.id.service);

 

        stop = (Button)findViewById(R.id.stop);

 

        info = (TextView)findViewById(R.id.info);

 

  info.setText(“Stop Service”);

 

       

 

        receiver = new MyReceiver();

 

        filter = new IntentFilter(“MyFilter”);

 

        registerReceiver(receiver, filter);

 

 

 

        service.setOnClickListener(new OnClickListener(){

 

   @Override

 

   public void onClick(View v) {

 

    Intent intent = new Intent();

 

    intent.putExtra(“mode”, true);

 

    intent.setClass(ServiceTest.this, MyService.class);

 

    startService(intent);

 

   }        

 

        });

 

        stop.setOnClickListener(new OnClickListener(){

 

   @Override

 

   public void onClick(View v) {

 

    Intent intent = new Intent();

 

    intent.putExtra(“mode”, false);

 

    intent.setClass(ServiceTest.this, MyService.class);

 

    startService(intent);

 

    info.setText(“Stop Service”);

 

   }

 

        });

 

    }

 

   

 

 private class MyReceiver extends BroadcastReceiver {

 

  @Override

 

  public void onReceive(Context context, Intent intent) {

 

   double Lat = intent.getDoubleExtra(“Lat”, 0.0);

 

   double Long = intent.getDoubleExtra(“Long”, 0.0);

 

   float Accuracy = intent.getFloatExtra(“Accuracy”, 0.0f);

 

   float Bearing = intent.getFloatExtra(“Bearing”, 0.0f);

 

   float Speed = intent.getFloatExtra(“Speed”, 0.0f);

 

   long Time = intent.getLongExtra(“Time”, 0);

 

  

 

   info.setText(“Lat: ” + Lat + “\n” +

 

      “Long” + Long + “\n” +

 

      “Accuracy” + Accuracy + “\n” +

 

      “Bearing” + Bearing + “\n” +

 

      “Speed” + Speed + “\n” +

 

      “Time” + Time + “\n”

 

      );

 

  }    

 

 }

 

}

 


接下來將重點放在 Service:

 

package tw.brad.android.test.ServiceTest;

 

 

 

import android.app.Service;

 

import android.content.Intent;

 

import android.location.Location;

 

import android.location.LocationListener;

 

import android.location.LocationManager;

 

import android.os.Bundle;

 

import android.os.IBinder;

 

 

 

public class MyService extends Service {

 

 private LocationManager lm;

 

 private MyLocationListener mll;

 

 @Override

 

 public IBinder onBind(Intent arg0) {

 

  // TODO Auto-generated method stub

 

  return null;

 

 }

 

 

 

 @Override

 

 public void onCreate() {

 

  super.onCreate();

 

  lm = (LocationManager)getSystemService(LOCATION_SERVICE);

 

  mll = new MyLocationListener();

 

 }

 

 

 

 @Override

 

 public int onStartCommand(Intent intent, int flags, int startId) {

 

  boolean mode = intent.getBooleanExtra(“mode”, true);

 

  if (mode){

 

   lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 0, mll);

 

  }else {

 

   lm.removeUpdates(mll);

 

  }

 

 

 

  return super.onStartCommand(intent, flags, startId);

 

 }

 

 

 

 

 

 @Override

 

 public void onDestroy() {

 

  super.onDestroy();

 

  lm.removeUpdates(mll);

 

 }

 

 

 

 

 

 private class MyLocationListener implements LocationListener {

 

 

 

  @Override

 

  public void onLocationChanged(Location location) {

 

   Intent intent = new Intent(“MyFilter”);

 

   intent.putExtra(“Lat”, location.getLatitude());

 

   intent.putExtra(“Long”, location.getLongitude());

 

   intent.putExtra(“Accuracy”, location.getAccuracy());

 

   intent.putExtra(“Bearing”, location.getBearing());

 

   intent.putExtra(“Speed”, location.getSpeed());

 

   intent.putExtra(“Time”, location.getTime());

 

   sendBroadcast(intent);

 

  }

 

 

 

  @Override

 

  public void onProviderDisabled(String provider) {

 

   // TODO Auto-generated method stub

 

  

 

  }

 

 

 

  @Override

 

  public void onProviderEnabled(String provider) {

 

   // TODO Auto-generated method stub

 

  

 

  }

 

 

 

  @Override

 

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

 

   // TODO Auto-generated method stub

 

  

 

  }

 

 

 

 }

 

 

 

}

 

 

不要忘記 AndroidManifest.xml 中處理權限及Service:

 

<?xml version=”1.0″ encoding=”utf-8″?>

 

<manifest xmlns:android=”http://schemas.android.com/apk/res/android”

 

      package=”tw.brad.android.test.ServiceTest”

 

      android:versionCode=”1″

 

      android:versionName=”1.0″>

 

    <application android:icon=”@drawable/icon” android:label=”@string/app_name”>

 

        <activity android:name=”.ServiceTest”

 

                  android:label=”@string/app_name”>

 

            <intent-filter>

 

                <action android:name=”android.intent.action.MAIN” />

 

                <category android:name=”android.intent.category.LAUNCHER” />

 

            </intent-filter>

 

        </activity>

 

 

 

    <service android:name=”MyService”></service>

 

</application>

 

    <uses-sdk android:minSdkVersion=”7″ />

 

 

 

<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”></uses-permission>

 

</manifest>

 

 

 

 

 


發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *