Android筆記二(service)

1、Service的基本用法

首先看一下如何在項目中定義一個服務,在這個項目中新增一個名爲 MyService 的類,並讓它繼承自 Service。這樣的話一個服務就定義好了。既然是定義一個服務,自然應該在服務中去處理一些事情了,那處理事情的邏輯應該寫在哪裏呢?這時就可以重寫 Service 中的另外一些方法。OnCreate()、onStartCommand()、onDestory()。這三個方法是最常用的方法。其中 onCreate()方法會在服務創建的時候調用,onStartCommand()方法會在每次服務啓動的時候調用,onDestroy()方法會在服務銷燬的時候調用。
通常情況下,如果我們希望服務一旦啓動就立刻去執行某個動作,就可以將邏輯寫在onStartCommand()方法裏。而當服務銷燬時,我們又應該在 onDestroy()方法中去回收那些不再使用的資源。

public class Myservice extends Service {
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onBind()--方法被調用");
		return null;
	}
	// onCreate()方法會在服務創建的時候調用
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Log.v("msg", "--onCreate()--方法被調用");
	}
	//onStartCommand()方法會在每次服務啓動的時候調用
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onStartCommand()--方法被調用");
		return super.onStartCommand(intent, flags, startId);
	}
	//onDestroy()方法會在服務銷燬的時候調用
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.v("msg", "--onDestroy()--方法被調用");
	}

}
另外需要注意,每一個服務都需要在 AndroidManifest.xml文件中進行註冊才能生效。

 <service android:name="com.test.testservice.Myservice"></service>
以上操作一個服務就定義好了,接下來去MainActivity中去啓動和停止這個服務

public class MainActivity extends Activity {
	private Button btn1;
	private Button btn2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn1 = (Button) findViewById(R.id.btn_01);
		btn2 = (Button) findViewById(R.id.btn_02);
		btn1.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//創建一個Intent對象,用來啓動服務
				Intent stratIntent = new Intent(MainActivity.this,
						Myservice.class);
				//啓動服務
				startService(stratIntent);
			}
		});
		btn2.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//創建一個Intent對象,用來停止服務
				Intent stopIntent = new Intent(MainActivity.this,
						Myservice.class);
				//停止服務
				stopService(stopIntent);
			}
		});
	}

}
  按鈕的點擊事件裏,我們構建出了一個 Intent 對象,並調用 startService()方法來啓動 MyService 這個服務。在 Stop Serivce 按鈕的點擊事件裏, 我們同樣構建出了一個Intent對象, 並調用stopService()方法來停止MyService這個服務。不用Activity去控制服務,只需要在 MyService 的任何一個位置調用 stopSelf()方法也能讓這個服務停止下來了。

2、服務和活動的基本通信
爲了讓活動和服務之間進行基本的通信,而不是活動發出一個命令之後就不能去控制服務怎麼運行,就需要使用到Service中的onBind()方法。

比如說目前我們希望在 MyService 裏提供一個下載功能,然後在活動中可以決定何時開始下載, 以及隨時查看停止下載。 實現這個功能的思路是創建一個專門的 Binder 對象來對下載功能進行管理

public class Myservice extends Service {
	//實例化MyBinder類
	private MyBinder myBinder = new MyBinder();
	//創建MyBinder類,繼承Binder,在這裏面寫activity要service做的事,例如方法startDownload()和stopDownload()
	class MyBinder extends Binder{
		public void startDownload() {
			// TODO Auto-generated method stub
			Log.v("msg", "開始下載!");
		}
		public void stopDownload() {
			// TODO Auto-generated method stub
			Log.v("msg", "停止下載!");
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onBind()--方法被調用");
		//當Activity要控制Service時返回MyBinder實例,否則返回null
		return myBinder;
	}
	// onCreate()方法會在服務創建的時候調用
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Log.v("msg", "--onCreate()--方法被調用");
	}
	//onStartCommand()方法會在每次服務啓動的時候調用
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onStartCommand()--方法被調用");
		return super.onStartCommand(intent, flags, startId);
	}
可以看到,這裏我們新建了一個 DownloadBinder 類,並讓它繼承自 Binder,然後在它的內部提供了開始下載以及查看下載進度的方法。當然這只是兩個模擬方法,並沒有實現真正的功能,我們在這兩個方法中分別打印了一行日誌。接着,在 MyService 中創建了 DownloadBinder 的實例,然後在 onBind()方法裏返回了這個實例,這樣 MyService 中的工作就全部完成了。

public class MainActivity extends Activity {
	private Button btn3;
	private Button btn4;

	private Myservice.MyBinder myBinder;
	//創建一個 ServiceConnection 的匿名類,在裏面重寫了onServiceConnected()方法和 onServiceDisconnected()方法
	private ServiceConnection connection = new ServiceConnection() {
		//當activity和service取消綁定時調用
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			Log.v("msg", "服務斷開連接");
		}
		//當activity和service成功綁定時調用
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			Log.v("msg", "服務連接");
			//向下轉型,得到MyBinder實例
			myBinder = (MyBinder) service;
			//調用MyBinder中的startDownload()方法
			myBinder.startDownload();
			//調用MyBinder中的stopDownload()方法
			myBinder.stopDownload();

		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn3 = (Button) findViewById(R.id.btn_03);
		btn4 = (Button) findViewById(R.id.btn_04);

		btn3.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//創建Intent對象,用來綁定Service bindService()方法接收三個參數, 第一個參數就
				//是剛剛構建出的 Intent 對象,第二個參數是前面創建出的 ServiceConnection 的實例,第三個
				//參數則是一個標誌位,這裏傳入 BIND_AUTO_CREATE 表示在活動和服務進行綁定後自動創建服務
				Intent bindIntent = new Intent(MainActivity.this,
						Myservice.class);
				//綁定service
				bindService(bindIntent, connection, BIND_AUTO_CREATE);
			}
		});
		btn4.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				//解除Activity和Service的綁定
				unbindService(connection);
			}
		});
	}

}
可以看到,這裏我們首先創建了一個 ServiceConnection 的匿名類,在裏面重寫了onServiceConnected()方法和 onServiceDisconnected()方法,這兩個方法分別會在活動與服務成功綁定以及解除綁定的時候調用。在 onServiceConnected()方法中,我們又通過向下轉型得到了 DownloadBinder 的實例,有了這個實例,活動和服務之間的關係就變得非常緊密了。現在我們可以在活動中根據具體的場景來調用 DownloadBinder 中的任何 public 方法,即實現了指揮服務幹什麼,服務就去幹什麼的功能。這裏仍然只是做了個簡單的測試,在onServiceConnected()方法中調用了 DownloadBinder的 startDownload()和 stopDownload()方法。當然,現在活動和服務其實還沒進行綁定呢,這個功能是在 Bind Service 按鈕的點擊事件裏完成的。可以看到,這裏我們仍然是構建出了一個 Intent 對象,然後調用 bindService()方法將 MainActivity 和 MyService 進行綁定。bindService()方法接收三個參數, 第一個參數就是剛剛構建出的 Intent 對象,第二個參數是前面創建出的 ServiceConnection 的實例,第三個參數則是一個標誌位,這裏傳入 BIND_AUTO_CREATE 表示在活動和服務進行綁定後自動創建服務。這會使得 MyService 中的 onCreate()方法得到執行,但 onStartCommand()方法不會執行。然後如果我們想解除活動和服務之間的綁定該怎麼辦呢?調用一下 unbindService()方法就可以了,這也是 Unbind Service 按鈕的點擊事件裏實現的功能。

3、使用前臺服務
前臺服務的使用是爲了防止系統內存不足時,關閉後臺的服務。

前臺服務使用只需要在MyService的方法onCreate()中加入如下代碼即可

//下面代碼是使用前臺服務,防止服務在系統內存不足時被回收
		Notification notification = new Notification(R.drawable.ic_launcher,"Notification comes", System. currentTimeMillis());
		Intent notificationIntent = new Intent(this, MainActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0);
		notification.setLatestEventInfo(this, "This is title", "This is content", pendingIntent);
		startForeground(1, notification);




4、使用IntentService

爲了防止程序在servcie中進行耗時操作,出現AND異常,可以使用IntentService來代替Service,這裏面開啓了子線程,可以用來進行耗時的操作。

public class MyIntentService extends IntentService {
	public MyIntentService() {
		// TODO Auto-generated constructor stub
		super("MyIntentService");
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		// TODO Auto-generated method stub
		//在這裏處理具體的邏輯問題,不用擔心ANR,這是一個子線程,事情做完會自動調用onDestroy()方法
		Log.v("msg","Thread id is " + Thread.currentThread().getId());
	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.v("msg", "--onDestroy()--方法被調用");
	}
}
這裏首先是要提供一個無參的構造函數,並且必須在其內部調用父類的有參構造函數。然後要在子類中去實現 onHandleIntent()這個抽象方法, 在這個方法中可以去處理一些具體的邏輯,而且不用擔心 ANR 的問題,因爲這個方法已經是在子線程中運行的了。這裏爲了證實一下, 我們在 onHandleIntent()方法中打印了當前線程的 id。 另外根據 IntentService 的特性,這個服務在運行結束後應該是會自動停止的,所以我們又重寫了 onDestroy()方法,在這裏也打印了一行日誌,以證實服務是不是停止掉了。

在 AndroidManifest.xml文件中進行註冊才能生效。

<service android:name="com.test.testservice.MyIntentService"></service>
看看MainActivity中的代碼,與Service的使用並沒什麼區別

public class MainActivity extends Activity {

	private Button btn5;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btn5 = (Button) findViewById(R.id.btn_05);

		btn5.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//  打印主線程的id
				Log.v("msg", "Thread id is " + Thread.currentThread().getId());
				//創建一個Intent對象
				Intent intentService = new Intent(MainActivity.this, MyIntentService.class);
				//開啓服務
				startService(intentService);
			}
		});
	}

}


以上代碼佈局非常簡單,就不給出

這些乃是作者看《第一行代碼》的筆記。另官方service介紹的鏈接:點擊打開鏈接





發佈了23 篇原創文章 · 獲贊 19 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章