1. 程式人生 > >Android四大元件之服務(一)-----服務基礎功能簡述

Android四大元件之服務(一)-----服務基礎功能簡述

服務(Service)是android的四大元件之一,在Android專案中擔任著後臺執行的大任,主要去完成那些不需要和使用者互動而且還要求長時間執行在後臺的工作。服務的執行不會對使用者使用app造成任何影響,這個元件屬於很常用的元件,幾乎每一款app產品都會用到,比如後臺更新天氣,這個動作是在我們毫無察覺的情況下替我們完成的。今天就學習一下,服務的基本使用者。

效果圖:


程式碼:

layout資料夾下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"
    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" >

    <Button
        android:id="@+id/stop_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/start_service"
        android:layout_alignBottom="@+id/start_service"
        android:layout_toRightOf="@+id/start_service"
        android:text="關閉服務" />

    <Button
        android:id="@+id/start_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="42dp"
        android:layout_marginTop="24dp"
        android:text="啟動服務" />

    <Button
        android:id="@+id/bind_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/start_service"
        android:layout_below="@+id/start_service"
        android:layout_marginTop="24dp"
        android:text="繫結服務" />

    <Button
        android:id="@+id/unbind_service"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/bind_service"
        android:layout_alignLeft="@+id/stop_service"
        android:text="解綁服務" />

</RelativeLayout>

MainActivity.java中的程式碼:
package com.demo.myservicedemo;

import com.demo.myservicedemo.MyService.DownloaderBinder;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {
	
	private static final String TAG = "MyService" ;
	
	private Button startService;
	private Button stopService;
	private Button bindService;
	private Button unbindService;
	/**
	 * 建立MyService中DownloaderBinder類的物件
	 */
	private MyService.DownloaderBinder downloadBinder;
	/**
	 * 是否繫結服務 true:繫結;false未繫結
	 */
	private boolean is_bindService = false ;
	/**
	 * 例項化MyServiceConnection類
	 */
	private MyServiceConnection connection = new MyServiceConnection();

	/**
	 * 新建一個MyServiceConnection類,實現ServiceConnection介面
	 * 
	 * @author honey
	 */
	class MyServiceConnection implements ServiceConnection {

		/**
		 * 活動與服務成功繫結時呼叫
		 */
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			/**
			 * 獲得MyService中onBind方法返回的例項物件dbinBinder, 獲得dbinBinder物件後,
			 * 就可以在activity中操作Myservice中內部類DownloaderBinder中的方法了
			 */
			Log.d(TAG, "MainActivity中onServiceConnected()方法") ;
			Toast.makeText(MainActivity.this, "服務繫結成功,Activity開始與服務通訊", 0).show() ;
			is_bindService = true ;//繫結服務的標誌
			/**
			 * 向下轉型,例項化MyService中DownloaderBinder類的例項
			 */
			downloadBinder = (DownloaderBinder) service;
			downloadBinder.startDownload();
			downloadBinder.getProgress();
		}

		/**
		 * 1、service的連線意外丟失時呼叫該方法,比如當service崩潰了或被強殺了.
		 * 2、客戶端解除繫結(即呼叫unbindService()這個方法)時,只會呼叫服務中的onDestroy()方法,不會呼叫onServiceDisconnected()方法.
		 */
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			Log.d(TAG, "MainActivity中onServiceDisconnected()方法") ;
		}

	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		startService = (Button) findViewById(R.id.start_service);
		stopService = (Button) findViewById(R.id.stop_service);
		startService.setOnClickListener(this);
		stopService.setOnClickListener(this);
		bindService = (Button) findViewById(R.id.bind_service);
		unbindService = (Button) findViewById(R.id.unbind_service);
		bindService.setOnClickListener(this);
		unbindService.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.start_service:
			/**
			 * 呼叫startService()方法,相應的服務就會啟動,並回調onStartCommond()方法,
			 * 如果這個服務之前沒有建立過,那麼onCreate()方法會先於onStartCommond()執行,
			 * 如果這個服務之前建立過,則不再執行onCreate()方法。
			 * 注:因為每個服務只存在一個例項,所以,不管我們呼叫多少次startService()方法,
			 * 只要呼叫一次stopService()或stopSelf()方法,服務就會停止
			 */
			Intent startIntent = new Intent(this, MyService.class);
			startService(startIntent); // 啟動服務
			Toast.makeText(this, "服務啟動", 0).show() ;
			break;
		case R.id.stop_service:
			/**
			 * 呼叫stopService()方法,會進入Service類的onDestroy()方法中,停止服務
			 */
			Intent stopIntent = new Intent(this, MyService.class);
			stopService(stopIntent); // 停止服務
			Toast.makeText(this, "服務停止", 0).show() ;
			break;
		case R.id.bind_service:// 繫結服務
			/**
			 * 通過bindSerbice()方法將MainActivity和MyService進行繫結,獲取一個服務的持久連線,會回撥服務中的onBind()方法。
			 * 如果服務還未建立,則會先呼叫onCreate()方法,然後通過onBind()方法獲得IBinder物件,這樣就可以操作服務了
			 *  BIND_AUTO_CREATE表示在活動和服務進行繫結後自動 建立服務。
			 *  自動建立服務-->MyService類中的onCreate()方法得到執行,onStartCommand()方法不會執行
			 */
			Intent bindIntent = new Intent(this, MyService.class);
			bindService(bindIntent, connection, BIND_AUTO_CREATE);
			Toast.makeText(this, "繫結服務", 0).show() ;
			break;
		case R.id.unbind_service:// 解除繫結
			/**
			 * unbindService()方法,回撥服務中的onDestroy()方法
			 */
			if(is_bindService) {
				unbindService(connection);
				is_bindService = false ;//沒有繫結的服務了
				Toast.makeText(this, "解除繫結", 0).show() ;
			}else {
				Toast.makeText(getApplicationContext(), "還沒有繫結的服務", 0).show() ;
			}
			break;
		default:
			break;
		}
	}

}

MyService.java中的程式碼:
package com.demo.myservicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {

	private static final String TAG = "MyService";

	/**
	 * 建立DownloaderBinder例項
	 */
	private DownloaderBinder dbinBinder = new DownloaderBinder();

	/**
	 * 新建DownloaderBinder類,繼承自Binder,在該類中提供兩個方法:開始下載和檢視下載進度
	 * @author honey
	 */
	class DownloaderBinder extends Binder {

		/**
		 * 自定義開始下載的方法
		 */
		public void startDownload() {
			Log.d(TAG, "startDownload");
		}

		/**
		 * 自定義獲得下載進度的方法
		 */
		public int getProgress() {
			Log.d(TAG, "getProgress");
			return 0;
		}
	}

	/**
	 * 返回DownloaderBinder類的例項,Activity可以使用這個例項與服務Service進行互動
	 */
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return dbinBinder;
	}

	/**
	 * 在服務第一次建立的時候呼叫,只調用一次,服務只要啟動了,以後再次進入服務就不在進入該方法
	 */
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Log.d(TAG, "onCreate");
	}

	/**
	 * 每次服務啟動的時候呼叫,不管服務是否啟動,每次進入服務都會執行該方法
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	/**
	 * 服務銷燬的時候 呼叫
	 * 1、如果只調用的startService()啟動方法,那麼呼叫stopService()方法即可停止服務;
	 * 2、如果只調用了bindService()方法繫結服務,那麼回撥unbindService()方法即可解除與服務的繫結;
	 * 3、如果同時呼叫了startService()方法啟動服務,bindService()方法繫結服務,
	 * 那麼要同時呼叫stopService()方法和unbindService()方法,onDestroy()方法才能執行,
	 * 沒有先後順序,而且,只有在第二個方法被呼叫後,才會進入到onDestroy()方法中
	 */
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.d(TAG, "onDestroy");
	}

}

AndroidManifest.xml中程式碼:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demo.myservicedemo"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.demo.myservicedemo.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>

        <service android:name="com.demo.myservicedemo.MyService" >
        </service>
    </application>

</manifest>

下載demo: