一、Service 簡(jiǎn)介
首先我們先了解一下Service
的繼承關(guān)系,方便我們更好的了解Service
。Service
繼承關(guān)系如下:
java.lang.Object
? android.content.Context
? android.content.ContextWrapper
? android.app.Service
Service
是Android
四大組件之一(Activity
活動(dòng),Service
服務(wù),ContentProvider
內(nèi)容提供者,BroadcastReceiver
廣播),與Activity
相比,Service
是運(yùn)行在后臺(tái),無(wú)用戶界面,用戶無(wú)法看到,Activity
則是運(yùn)行在前臺(tái),用戶可以看得見(jiàn)。
Service
主要用于組件之間交互(例如:與Activity
、ContentProvider
、BroadcastReceiver
進(jìn)行交互)、執(zhí)行后臺(tái)任務(wù)等(例如下載文件,播放音樂(lè)等)。
注意:Service
在主線程運(yùn)行時(shí)長(zhǎng)不能超過(guò)20s
,否則會(huì)出現(xiàn)ANR
,耗時(shí)操作一般建議在子線程或工作線程中進(jìn)行操作。
二、Service 的注冊(cè)
Service
是四大組件之一,必現(xiàn)在AndroidMainfest.xml
中注冊(cè)。Service
注冊(cè)方法如下:
... >
...
... >
android:name=".ServiceMethods" />
...
>
>
注意:Service
如不注冊(cè) ,不會(huì)像Activity
那樣會(huì)導(dǎo)致App Crash
,Service
不注冊(cè) 不會(huì)報(bào)異常信息,但是服務(wù)會(huì)起不來(lái),如不注意很容易迷惑。
三、Service 的啟動(dòng)模式
Service
啟動(dòng)模式主要分兩種:1. 啟動(dòng)模式。2. 綁定模式。
-
1.啟動(dòng)模式
此模式通過(guò)startService()
方法啟動(dòng),此服務(wù)可以在后臺(tái)一直運(yùn)行,不會(huì)隨啟動(dòng)組件的消亡而消亡。
但是,此種啟動(dòng)模式只能執(zhí)行單一操作,并且無(wú)法返回結(jié)果給調(diào)用方,主要常用于網(wǎng)絡(luò)下載、上傳文件,播放音樂(lè)等。
-
2.綁定模式
此模式通過(guò)綁定組件(Activity
等)調(diào)用bindService()
啟動(dòng),此服務(wù)隨綁定組件的消亡而解除綁定。
如果此時(shí)沒(méi)有其它通過(guò)startService()
啟動(dòng),則此服務(wù)會(huì)隨綁定組件的消亡而消亡。
多個(gè)組件不僅可以同時(shí)綁定一個(gè)Service
,而且可以通過(guò)進(jìn)程間通信(IPC)
執(zhí)行跨進(jìn)程操作等。
-
3.兩種服務(wù)可以同時(shí)運(yùn)行
啟動(dòng)模式與綁定模式的服務(wù)可以同時(shí)運(yùn)行,在銷(xiāo)毀服務(wù)時(shí),只有兩種模式都不在使用Service
時(shí)候,才可以銷(xiāo)毀服務(wù),否則會(huì)引起異常。
四、Service的生命周期
Service
有兩種不同的啟動(dòng)模式 ,不同的啟動(dòng)模式對(duì)應(yīng)不同生命周期。兩種不同Service
模式的生命周期如下:
兩種 Service 模式生命周期圖
五、啟動(dòng)模式使用舉例
通過(guò)啟動(dòng)模式啟動(dòng)的Service
,如不主動(dòng)關(guān)閉,Service
會(huì)一直在。
1.啟動(dòng)模式啟動(dòng)服務(wù)的方法
Intent mBindIntent = new Intent(ServiceMethods.this, BindServiceMethods.class);
startService(mStartIntent);
2.啟動(dòng)模式啟動(dòng)服務(wù)的生命周期
下面是驗(yàn)證啟動(dòng)模式啟動(dòng)服務(wù)的生命周期的方法,詳細(xì)生命周期請(qǐng)查看上方Service
的生命周期圖。
01-03 17:16:36.147 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onCreate----
01-03 17:16:36.223 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onStartCommand----
01-03 17:16:38.174 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onDestroy----
3.啟動(dòng)模式 啟動(dòng)服務(wù)案例
此案例功能:?jiǎn)?dòng)服務(wù),在服務(wù)中創(chuàng)建通知
// Service 創(chuàng)建方法
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "----onCreate----");
}
// Service 啟動(dòng)方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "----onStartCommand----");
// 獲取NotificationManager實(shí)例
notifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 實(shí)例化NotificationCompat.Builder并設(shè)置相關(guān)屬性
NotificationCompat.Builder builder = new NotificationCompat.Builder(
this)
// 設(shè)置小圖標(biāo)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(
BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
// 設(shè)置通知標(biāo)題
.setContentTitle("我是通過(guò)StartService服務(wù)啟動(dòng)的通知")
// 設(shè)置通知不能自動(dòng)取消
.setAutoCancel(false).setOngoing(true)
// 設(shè)置通知時(shí)間,默認(rèn)為系統(tǒng)發(fā)出通知的時(shí)間,通常不用設(shè)置
// .setWhen(System.currentTimeMillis())
// 設(shè)置通知內(nèi)容
.setContentText("請(qǐng)使用StopService 方法停止服務(wù)");
// 通過(guò)builder.build()方法生成Notification對(duì)象,并發(fā)送通知,id=1
notifyManager.notify(1, builder.build());
return super.onStartCommand(intent, flags, startId);
}
// Service 銷(xiāo)毀方法
@Override
public void onDestroy() {
Log.i(TAG, "----onDestroy----");
notifyManager.cancelAll();
super.onDestroy();
}
六、 綁定服務(wù)介紹
綁定模式啟動(dòng)的服務(wù)會(huì)隨著綁定逐漸的消亡而解除Service
綁定,如果此時(shí)Service
沒(méi)有通過(guò)啟動(dòng)模式啟動(dòng),則此服務(wù)將會(huì)被銷(xiāo)毀。
1.啟動(dòng)綁定模式服務(wù)的方法
綁定模式,是通過(guò)其他組件調(diào)用bindService()
方法啟動(dòng)的Service
。
// 啟動(dòng)綁定服務(wù)處理方法
public void BtnStartBindService(View view) {
// 啟動(dòng)綁定服務(wù)處理方法
bindService(mBindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
isBindService = true;
Toast.makeText(ServiceMethod.this, "啟動(dòng) " + mBindCount + " 次綁定服務(wù)",
Toast.LENGTH_SHORT).show();
}
public void BtnSopBindService(View view) {
if (isBindService) {
// 解除綁定服務(wù)處理方法
unbindService(serviceConnection);
Toast.makeText(ServiceMethod.this, "解除 " + mUnBindCount + " 次綁定服務(wù)",
Toast.LENGTH_SHORT).show();
isBindService = false;
}
}
2.綁定服務(wù) 隨綁定組件的消亡而消亡
如果綁定服務(wù)的組件被destory
,這 bind 服務(wù)會(huì)走到onUnbind()
方法。
3. 綁定模式 生命周期回調(diào)代碼如下:
// Service 創(chuàng)建方法
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "----onCreate----");
}
// Service 綁定方法
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "----onBind----");
MyBinder myBinder = new MyBinder();
return myBinder;
}
// Service 解除綁定方法
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "----onUnbind----");
return super.onUnbind(intent);
}
// Service 銷(xiāo)毀方法
@Override
public void onDestroy() {
Log.i(TAG, "----onDestroy----");
super.onDestroy();
}
綁定服務(wù)的生命周期代碼打印Log
信息如下:
01-03 20:32:59.422 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onCreate----
01-03 20:32:59.423 13306-13306/com.android.program.programandroid I/BindService wjwj:: -----onBind-----
01-03 20:33:09.265 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onUnbind----
01-03 20:33:09.266 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onDestroy----
七、bind 服務(wù)舉例
功能:
獲取綁定模式啟動(dòng) 綁定服務(wù)及解除綁定服務(wù)的次數(shù)
1.綁定服務(wù)類(lèi)
package com.android.program.programandroid.component.Service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class BindServiceMethods extends Service {
private static final String TAG = "BindService wjwj:";
public BindServiceMethods() {
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "----onCreate----");
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "----onBind----");
MyBinder myBinder = new MyBinder();
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "----onUnbind----");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG, "----onDestroy----");
super.onDestroy();
}
}
2.組件與綁定服務(wù)類(lèi)之間的交互
// 啟動(dòng)綁定服務(wù)處理方法
public void BtnStartBindService(View view) {
bindService(mBindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
isBindService = true;
Toast.makeText(ServiceMethods.this,"啟動(dòng) "+mBindCount+" 次綁定服務(wù)",Toast.LENGTH_SHORT).show();
}
// 解除綁定服務(wù)處理方法
public void BtnSopBindService(View view) {
if (isBindService) {
unbindService(serviceConnection);
Toast.makeText(ServiceMethods.this,"解除 "+mUnBindCount+" 次綁定服務(wù)",Toast.LENGTH_SHORT).show();
isBindService=false;
}
}
3.組件之間交互所需的Binder
接口類(lèi)
/**
* 該類(lèi)提供 綁定組件與綁定服務(wù)提供接口
* */
public class MyBinder extends Binder {
private int count = 0;
public int getBindCount() {
return ++count;
}
public int getUnBindCount() {
return count> 0 ? count-- : 0;
}
}
八、服務(wù)的優(yōu)先級(jí)
服務(wù)默認(rèn)啟動(dòng)方式是后臺(tái)服務(wù),但是可以通過(guò)設(shè)置服務(wù)為前臺(tái)服務(wù),提高服務(wù)的優(yōu)先級(jí),進(jìn)而避免手機(jī)內(nèi)存緊張時(shí),服務(wù)進(jìn)程被殺掉。
設(shè)置服務(wù)優(yōu)先級(jí)的方法如下:
1.設(shè)置為前臺(tái)服務(wù)
//設(shè)置為前臺(tái)服務(wù)
startForeground(int, Notification)
2.取消前臺(tái)服務(wù)
//取消為前臺(tái)服務(wù)
stopForeground(true);
3.startForeground 前臺(tái)服務(wù)案例
功能:前臺(tái)服務(wù)綁定通知信息,提高服務(wù)進(jìn)程優(yōu)先級(jí),否則取消通知信息
package com.android.program.programandroid.component.Service;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import com.android.program.programandroid.R;
public class MyStartForcegroundService extends Service {
public MyStartForcegroundService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals("start_forceground_service")) {
// 獲取NotificationManager實(shí)例
NotificationManager notifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 實(shí)例化NotificationCompat.Builder并設(shè)置相關(guān)屬性
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
// 設(shè)置小圖標(biāo)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
// 設(shè)置通知標(biāo)題
.setContentTitle("我是通過(guò)startForeground 啟動(dòng)前臺(tái)服務(wù)通知")
// 設(shè)置通知不能自動(dòng)取消
.setAutoCancel(false)
.setOngoing(true)
// 設(shè)置通知時(shí)間,默認(rèn)為系統(tǒng)發(fā)出通知的時(shí)間,通常不用設(shè)置
// .setWhen(System.currentTimeMillis())
// 設(shè)置通知內(nèi)容
.setContentText("請(qǐng)使用stopForeground 方法改為后臺(tái)服務(wù)");
//通過(guò)builder.build()方法生成Notification對(duì)象,并發(fā)送通知,id=1
// 設(shè)置為前臺(tái)服務(wù)
startForeground(1, builder.build());
} else if (intent.getAction().equals("stop_forceground_service")) {
stopForeground(true);
}
return super.onStartCommand(intent, flags, startId);
}
}
審核編輯 :李倩
-
Service
+關(guān)注
關(guān)注
0文章
30瀏覽量
13763 -
組件
+關(guān)注
關(guān)注
1文章
504瀏覽量
17787 -
線程
+關(guān)注
關(guān)注
0文章
504瀏覽量
19636
原文標(biāo)題:八、服務(wù)的優(yōu)先級(jí)
文章出處:【微信號(hào):哆啦安全,微信公眾號(hào):哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論