Service在android中的地位和activity,只是它沒有單獨的界面,一般都是在后台運行,主要是用來運行一些消耗時間比較長的任務。我們可以用它來發送intent來更新activity的UI。另外需要注意的是service既不是一個單獨的進程,也不是一個單獨的線程,它與activity一起在同一個進程中。
關於android的sevice,網上這篇文章對service做了比較詳細的介紹,並通過啟動音樂播放器的例子來講解service:http://www.cnblogs.com/allin/archive/2010/05/15/1736458.html
Service的生命周期
既然service和activity一樣重要,則和activity類似,它也有自己的生命周期。它的生命周期與啟動service的方式不同與不同,比如在activity中啟動service時,如果采用的是 activity.startService()啟動,則該service的生命周期一般為:
onCreate()->onStart()/onStartCommand()->service running->onDestroy().
如果是activity.bindService()啟動,則該service的生命周期為:
onCreate()->onBind()->service running->onUnbind()->onDestrop().
實驗部分
本次實驗主要是學習怎樣在activity中啟動一個service,啟動的service的生命周期順序是哪些,然后service通過廣播機制向特定的activity傳遞數據,傳送數據當然用的是intent,然后接收到該廣播的activity讀取intent中的數據,根據讀取到的數據來更新activity的UI。
關於怎樣通過service廣播機制來更新activity的UI,可以閱讀網上的這篇文章:http://www.pocketdigi.com/20110303/197.html
需要注意的是service類是繼承的android框架中的Service類,程序中需要將寫好的service在AndriodManiFest.xml中進行注冊,注冊方法和activity的注冊類似。
本程序的activity中有2個按鈕和1個TextView,2個按鈕分別用來啟動service和停止service,然后在activtiy和service的生命周期函數中各自在后台打印出相關語句,同時為了方便觀察,程序也直接將相關語句輸出到了textview中。
啟動程序后,界面如下:

單擊一次start service按鈕,然后單擊一次end service,再單擊一次start service按鈕后,界面輸出如下:

后台輸出如下:

程序主要部分代碼和注釋(附錄有實驗工程code下載鏈接):
MainActivity.java:
package com.example.service; 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.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private TextView text = null; private Button start = null; private Button end = null; MyReceiver receiver; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); start = (Button)findViewById(R.id.start); start.setOnClickListener(new StartOnClickListener()); end = (Button)findViewById(R.id.end); end.setOnClickListener(new EndOnClickListener()); System.out.println("Activity onCreate"); text.append("\nActivity onCreate..."); //因為該activity要接收廣播消息,所以先頂一個一個接收器對象 //該對象自己實現,是繼承BroadcastReceiver的 receiver=new MyReceiver(); //定義一個IntentFilter的對象,來過濾掉一些intent IntentFilter filter = new IntentFilter(); //只接收發送到action為"android.intent.action.MAIN"的intent //"android.intent.action.MAIN"是在MainFest中定義的 filter.addAction("android.intent.action.MAIN"); //啟動廣播接收器 MainActivity.this.registerReceiver(receiver, filter); } public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if(bundle.getInt("i") == 1) text.append("\nService onBind..."); else if(bundle.getInt("i") == 2) text.append("\nService onCreate..."); else if(bundle.getInt("i") == 3) text.append("\nService onStartCommand..."); else if(bundle.getInt("i") == 4) text.append("\nService onDestroy..."); } } private class StartOnClickListener implements OnClickListener { public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); //跳轉到service用startService,以前跳轉到activity用的是startactivity intent.setClass(MainActivity.this, FisrtService.class); //啟動service startService(intent); } } private class EndOnClickListener implements OnClickListener { public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(MainActivity.this, FisrtService.class); //結束service stopService(intent); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
FirstService.java:
package com.example.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; //從Service類繼承而來 public class FisrtService extends Service{ Intent intent = new Intent(); //intent.setAction("android.intent.action.MAIN"); @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub System.out.println("Service onBind"); intent.putExtra("i", 1); //service設置需要接收廣播intent的activity intent.setAction("android.intent.action.MAIN"); //service通過廣播發送intent sendBroadcast(intent); return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); System.out.println("Service onCreate"); intent.putExtra("i", 2); intent.setAction("android.intent.action.MAIN"); sendBroadcast(intent); } //onStartCommand與onStart類似,多了一個參數而已 @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub System.out.println("flags---->"+flags); System.out.println("startId---->"+startId); System.out.println("Service onStartCommand"); //不懂為什么這里要重新開一個intent,它的activity才能接收到它 Intent intent1 = new Intent(); intent1.putExtra("i", 3); intent1.setAction("android.intent.action.MAIN"); sendBroadcast(intent1); // //很奇怪為什么這里這樣用,在activity中竟然接收不到該intent,一定要重新開一個intent? // intent.putExtra("i", 3); // intent.setAction("android.intent.action.MAIN"); // sendBroadcast(intent); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); System.out.println("Service onDestroy"); intent.putExtra("i", 4); intent.setAction("android.intent.action.MAIN"); sendBroadcast(intent); } }
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" > <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello_service" android:layout_alignParentTop="true" /> <Button android:id="@+id/end" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="@string/end" /> <Button android:id="@+id/start" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@id/end" android:text="@string/start" /> </RelativeLayout>
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.service" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".FisrtService"></service> </application> </manifest>
總結:使用service可以在主界面運行的時候也能在后台運行多個服務,並且結合廣播機制可以完成一些常見的功能。
附錄:
