1. 程式人生 > >Android中Service的意義及用法

Android中Service的意義及用法

1、下面介紹Service和AsyncTask的用法和比較。

Service沒有介面,用於執行一個需要在後臺長期執行的任務。AsyncTask用於執行短時間的非同步任務,並跟UI執行緒互動,用於替代Thread和Handler。

1) MainActivity.java

public class MainActivity extends Activity {
	private static final String TAG = MainActivity.class.getSimpleName();
	/**便於多次、多地呼叫,生命週期伴隨Activity*/
	Intent intent;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.i(TAG, "onCreate");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
//		mAsyncTask.execute("http://www.qinuli.com:83/picture/thumb.jpg", "http://www.qinuli.com:83/picture/hand_in_hand.jpg");
		intent = new Intent(this, MyService.class);
	}
	protected void onDestroy() {
		Log.d(TAG, "onDestroy");
		super.onDestroy();
	};
	/**
	 * 定義一個AsyncTask的子類;例項化並在UI執行緒呼叫其execute方法
	 * <li>3個引數:Params、Progress、Result
	 * <li>4 steps:onPreExecute->doInBackground->onProgressUpdate->onPostExecute
	 * <li>功能:用於後臺執行前臺顯示的任務
	 * <li>意義:代替或封裝Thread和Handler,方便後臺執行緒和UI執行緒互動
	 */
	AsyncTask<String, Integer, CharSequence> mAsyncTask = new AsyncTask<String, Integer, CharSequence>() {
		@Override
		protected void onPreExecute() {
			Log.d(TAG, "onPreExecute");
		};
		@Override
		protected CharSequence doInBackground(String... params) {
			//perform a computation on a background thread
			for(int i=0;i<params.length;i++){
				publishProgress(Integer.valueOf(i));
			}
			return "加油!";
		}
		@Override
		protected void onProgressUpdate(Integer... values) {
			Log.d(TAG, "onProgressUpdate-"+values[0]);
		};
		@Override
		protected void onPostExecute(CharSequence result) {
			Log.d(TAG, "onPostExecute-"+result);
		};
	};
	private ServiceConnection mServiceConnection = new ServiceConnection() {
		@Override
		public void onServiceDisconnected(ComponentName name) {
			Log.d(TAG, "onServiceDisconnected-"+name.getClassName());
		}
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//由bindService觸發,在onBind之後
			MyService myService = ((MyBinder)service).getService();
			Log.d(TAG, "onServiceConnected-"+name.getClassName()+"-"+myService.name);
		}
	};
	public void onClick(View v){
		switch (v.getId()) {
		case R.id.btn_startService:
			//呼叫Service的空參構造
			startService(intent);
			break;
		case R.id.btn_stopService:
			stopService(intent);
			break;
		case R.id.btn_bindService:
			bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
			break;
		case R.id.btn_unbindService:
			unbindService(mServiceConnection);
		}
	}
}
2) activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <Button 
        android:id="@+id/btn_startService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="startService"/>
    <Button 
        android:id="@+id/btn_stopService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="stopService"/>
    <Button 
        android:id="@+id/btn_bindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="bindService"/>
    <Button 
        android:id="@+id/btn_unbindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="unbindService"/>
</LinearLayout>
3) MyService.java,講解startService和bindService的原理
/**
 * <li>Service的意義:perform a longer running operation
 * <li>Service和AsyncTask的區別:Service執行在主執行緒,不會結束
 */
public class MyService extends Service {
	private static final String TAG = MyService.class.getSimpleName();
	private MyBinder myBinder = new MyBinder();
	public String name = "ShiXin";
	
	public MyService(){
		super();
		Log.d(TAG, "MyService");
	}
	
	/**繼承Binder類,Binder類實現IBinder介面。例項化該類供onBind使用*/
	public class MyBinder extends Binder{
		/**返回Service的例項,進而呼叫其方法和屬性,實現一些資料通訊和功能操作*/
		public MyService getService(){
			return MyService.this;
		}
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		Log.d(TAG, "onBind");
		//由bindService觸發
		return myBinder;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log.d(TAG, "onUnbind");
		return super.onUnbind(intent);
	}
	
	@Override
	public void onCreate() {
		Log.d(TAG, "onCreate");
		//重新例項化新的Service
		super.onCreate();
	}
	
	public void onDestroy() {
		Log.d(TAG, "onDestroy");
		super.onDestroy();
	};
	
	@Override
	public void onStart(Intent intent, int startId) {
		//deprecated 被onStartCommand代替
		super.onStart(intent, startId);
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		//每次startService都會觸發,bindService不會觸發
		//startId:unique integer token,標記每次startService,Service建立後從1開始計數
		//START_STICKY_COMPATIBILITY 0;Service.START_STICKY 1
		stopSelfResult(3);//onStartCommand執行3次
		int state = super.onStartCommand(intent, flags, startId);
		Log.d(TAG, "onStartCommand-"+intent.getComponent().getClassName()+"-"+flags+"-"+startId+"-"+state);
		return state;//1
	}
}
4) MyIntentService.java,IntentService用於在後臺執行緒執行非同步任務,執行完Service自動destroy
/**
 * handle asynchronous requests
 */
public class MyIntentService extends IntentService {

	private static final String TAG = MyIntentService.class.getSimpleName();
	
	public MyIntentService() {
		//name worker thread
		super("worker thread");
	}
	@Override
	protected void onHandleIntent(Intent intent) {
		//代替onStartCommand;執行完呼叫stopSelf()
		Log.d(TAG, Thread.currentThread().getName()+"-onHandleIntent");
	}
	@Override
	public void onCreate() {
		Log.d(TAG, "onCreate");
		super.onCreate();
	}
	@Override
	public void onDestroy() {
		Log.d(TAG, "onDestroy");
		super.onDestroy();
	}
}
5) AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.qinuli.testproject"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity android:name="com.qinuli.testproject.MainActivity">
            <intent-filter >
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service android:name="com.qinuli.testproject.MyService"></service>
        <service android:name="com.qinuli.testproject.MyIntentService"></service>
    </application>

</manifest>

2、如何讓服務永久執行

本示例介紹了TIME_TICK和BOOT_COMPLETED廣播的用法

public class MainActivity extends Activity {
	private static final String TAG = MainActivity.class.getSimpleName();
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.d(TAG, "onCreate");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	@Override
	protected void onDestroy() {
		Log.d(TAG, "onDestroy");
		super.onDestroy();
	}
	public void onClick(View v){
		switch(v.getId()){
		case R.id.btn_killProcess:
			Process.killProcess(Process.myPid());
		}
	}
}
MyService.java
public class MyService extends Service {

	private static final String TAG = MyService.class.getSimpleName();
	private MyBinder myBinder = new MyBinder();
	public class MyBinder extends Binder{
		public MyService getService(){
			return MyService.this;
		}
	}
	@Override
	public IBinder onBind(Intent intent) {
		return myBinder;
	}
	@Override
	public void onCreate() {
		Log.d(TAG, "onCreate");
		super.onCreate();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(TAG, "onStartCommand");
		//程序被殺死,服務會重建
		return Service.START_STICKY;
	}
	@Override
	public void onDestroy() {
		Log.d(TAG, "onDestroy");
		super.onDestroy();
	}
}
MyApplication.java
public class MyApplication extends Application {
	private static final String TAG = MyApplication.class.getSimpleName();
	MyService myService;
	Intent intent;
	@Override
	public void onCreate() {
		Log.d(TAG, "onCreate");
		super.onCreate();
		
		intent = new Intent(this, MyService.class);
		startService(intent);
		bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
		
		registerReceiver(new TimeTickReceiver(), new IntentFilter(Intent.ACTION_TIME_TICK));
	}
	@Override
	public void onTerminate() {
		Log.d(TAG, "onTerminate");
		super.onTerminate();
		stopService(intent);
		//禁用一個manifest receiver,可禁用清單檔案裡註冊的四大元件
		ComponentName componentName = new ComponentName(this, BootCompletedReceiver.class);
		PackageManager pm = getPackageManager();
		pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
				PackageManager.DONT_KILL_APP);
	}
	private ServiceConnection mServiceConnection = new ServiceConnection() {
		@Override
		public void onServiceDisconnected(ComponentName name) {
			myService = null;
		}
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			Log.d(TAG, "onServiceConnected");
			myService = ((MyBinder)service).getService();
		}
	};
}
BootCompleteReceiver.java
public class BootCompletedReceiver extends BroadcastReceiver {
	private static final String TAG = BootCompletedReceiver.class.getSimpleName();

	public BootCompletedReceiver(){
		super();
		Log.d(TAG, "BootCompletedReceiver");
	}
	
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		Log.d(TAG, action);
		if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
			//清單檔案註冊,開機可收到廣播
			boolean isServiceRunning = false;
			ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
			for(RunningServiceInfo runningServiceInfo:activityManager.getRunningServices(Integer.MAX_VALUE)){
				if(MyService.class.getName().equals(runningServiceInfo.service.getClassName())){
					isServiceRunning = true;
				}
			}
			if(!isServiceRunning){
				ComponentName comp = new ComponentName(context.getPackageName(), MyService.class.getName());
				context.startService(new Intent().setComponent(comp));
			}
		}else if(ConnectivityManager.CONNECTIVITY_ACTION.equals(action)){
			//在清單檔案註冊,退出APP或殺死程序依然能收到廣播,但清掉記憶體就收不到了
			ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo = cm.getActiveNetworkInfo();
			if(networkInfo!=null)
				Log.d(TAG, "networkstate:"+networkInfo.isConnectedOrConnecting()+"-"+(networkInfo.getType()==ConnectivityManager.TYPE_MOBILE));
		}
	}
}
TimeTickReceiver.java
public class TimeTickReceiver extends BroadcastReceiver {
	private static final String TAG = TimeTickReceiver.class.getSimpleName();

	public TimeTickReceiver(){
		super();
		Log.d(TAG, "TimeTickReceiver");
	}
	
	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		Log.d(TAG, action);
		if (Intent.ACTION_TIME_TICK.equals(action)) {
			boolean isServiceRunning = false;
			//拿到所有正在執行的服務
			ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
			for(RunningServiceInfo runningServiceInfo:activityManager.getRunningServices(Integer.MAX_VALUE)){
				if(MyService.class.getName().equals(runningServiceInfo.service.getClassName())){
					isServiceRunning = true;
				}
			}
			Log.d(TAG, "isServiceRunning="+isServiceRunning);
			if(!isServiceRunning){
				ComponentName comp = new ComponentName(context.getPackageName(), MyService.class.getName());
				context.startService(new Intent().setComponent(comp));
			}
		}
	}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.qinuli.servicetest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
    <application
        android:name="com.qinuli.servicetest.MyApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity android:name="com.qinuli.servicetest.MainActivity">
            <intent-filter >
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service android:name="com.qinuli.servicetest.MyService"
            android:enabled="true"
            android:exported="false"/>
        <receiver
            android:name="com.qinuli.servicetest.BootCompletedReceiver"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
            android:enabled="true" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

相關推薦

static修飾符 (在類意義用法

(以下內容參考C++static的用法總結 這裡講的不會很詳細,主要是幾點: static的意義 為什麼要用static修飾符? 大家都知道,函式內部定義的變數在函式結束時就會釋放掉,然而要想

AndroidService意義用法

1、下面介紹Service和AsyncTask的用法和比較。 Service沒有介面,用於執行一個需要在後臺長期執行的任務。AsyncTask用於執行短時間的非同步任務,並跟UI執行緒互動,用於替代Thread和Handler。 1) MainActivity.java

python\r的意義用法

\r的意義 \r 表示將游標的位置回退到本行的開頭位置  \b表示將游標的位置回退一位  在python裡print會預設進行換行,可以通過修改引數讓其不換行   (1) python2中可以在print語句的末尾加上逗號,程式碼如下: print "

Android Service 和Activity之間傳值。(涉及BroadCast的基本用法

首先先建立一個Android工程(名字自定義)這裡我命名為MyActivity 包名為:package org.hm.myactivity; 再最後給自己的activity命名(名字自定義)此處我命名為MyTestActivity public class MyTestA

AndroidCalendar類的用法總結

jsb ews 寫法 需要 key data- minute bar 來講 Calendar是Android開發中需要獲取時間時必不可少的一個工具類,通過這個類可以獲得的時間信息還是很豐富的,下面做一個總結,以後使用的時候就不用總是去翻書或者查資料了。 在獲取時間之前要先獲

(轉)AndroidParcelable接口用法

string date 場景 應用 用法 反序列化 數組 auth 序列化對象 1. Parcelable接口 Interface for classes whose instances can be written to and restored from a Parce

AndroidService和IntentService的差別

前言: ServiceTimeout(20 seconds)小概率型別Service在特定的時間內無法處理完成,會造成ANR — 應用程式無響應(ANR:Application Not Responding)的情況 ▲ 分析 : 避免ANR最核心的一點就是在主執行緒減少耗時操作。這時我們

AndroidService的使用方法

  目錄 Service 介紹 Service兩種啟動方式 使用 測試 IntentService Activity與Service之間的通訊 繼承Binder類 Messenger AIDL Service 介紹

Android 常用 mimeType 表用法

  常用mimeType表: 檔案型別 mime名稱  

AndroidService的工作過程

我們知道,Service有兩種工作狀態,一種是啟動狀態,主要用於執行後臺計算; 另一種是繫結狀態,主要用於和其它元件的互動。而且這兩種狀態是可以共存的,關於Service的使用可以看之前的文章《Android裡服務Service的使用》。今天主要是對Service的啟動狀態和

EOF的意義用法(while(scanf("%d",&n) != EOF))

EOF,為End Of File的縮寫,通常在文字的最後存在此字元表示資料結束。 在微軟的DOS和Windows中,讀取資料時終端不會產生EOF。此時,應用程式知道資料來源是一個終端(或者其它“字元裝置”),並將一個已知的保留的字元或序列解釋為檔案結束的指明;最

AndroidAsyncTask的簡單用法

在開發Android移動客戶端的時候往往要使用多執行緒來進行操作,我們通常會將耗時的操作放在單獨的執行緒執行,避免其佔用主執行緒而給使用者帶來不好的使用者體驗。但是在子執行緒中無法去操作主執行緒(UI 執行緒),在子執行緒中操作UI執行緒會出現錯誤。因此android提供

android layer-list的用法

1.可以將多個圖片按照順序層疊起來 2.在drawable下建立一個xml檔案 [xhtml:showcolumns] view plaincopyprint? <?xml version="1.0" encoding="UTF-8"?>    

Android的Selector的用法

Android中的Selector主要是用來改變ListView和Button控制元件的預設背景。其使用方法可以按一下步驟來設計: (以在mylist_view.xml為例) 1.建立mylist_view.xml檔案 首先在res目錄下新建drawable資料夾,再在

Android控制元件介紹用法

第一部分 個性化控制元件(View) 主要介紹那些不錯個性化的View,包括ListView、ActionBar、Menu、ViewPager、Gallery、GridView、ImageView、ProgressBar及其他如Dialog、Toast、EditText、TableView、Activi

Android string-array的用法

本人小菜一枚,第一次寫部落格,從網上查到的一些知識點自己總結吧。總覺得部落格是一個很多好的記錄知識點的地方,歡迎指正,謝謝。 1、使用string-array的原因         在實際開發中,當資

AndroidService與Activity資料互動的簡單理解

Service跟Activity是最相似的元件,都代表可執行的程式,區別在於:Service一直在後臺執行,沒有跟使用者互動的介面。 啟動與停止Service有兩種方法: 第一種通過startService()與stopService()啟動和停止服務,Se

AndroidService(服務)詳解

Service是Android中四大元件之一,在Android開發中起到非常重要的作用,先來看一下官方對Service的定義: A  is an application component that can perform long-running operation

AndroidService的使用詳解和注意點(LocalService)

開始,先稍稍講一點android中Service的概念和用途吧~ Service分為本地服務(LocalService)和遠端服務(RemoteService): 1、本地服務依附在主程序上而不是獨立的程序,這樣在一定程度上節約了資源,另外Local服務因為是在同一程序因此

AndroidService使用bindService

前面已經對Service的startServer方式啟動一個服務瞭解過了,現在來看一下Service的另一種啟動方式→bindServer bindServer使用場景 1、在同個app之間呼叫(即是同一個程序中) 2、在不同app之間呼叫(即是跨程序間通訊) 同個app