Service
Android開發(fā)者文檔里這樣定義:
A service is a component that runs in the background to perform long-running operations or to perform work for remote processes. A service does not provide a user interface. For example, a service might play music in the background while the user is in a different app, or it might fetch data over the network without blocking user interaction with an activity.Another component, such as an activity, can start the service and let it run or bind to it in order to interact with it.
Service是Android提供的四大組件之一流济,我們可以認為它是一個沒有用戶界面、開發(fā)者創(chuàng)建的組件腌闯,它可以用來執(zhí)行長久的操作绳瘟,可以超出單個Activity的范圍。Service可以作為客戶端/服務(wù)器開發(fā)模式的服務(wù)器姿骏,通過進程間通信(IPC)提供遠程調(diào)用服務(wù)糖声。
如果一個任務(wù)需要使用worker線程,可能會影響應(yīng)用的響應(yīng)速度和性能分瘦,而這個任務(wù)對處理時間并不敏感蘸泻,那就考慮使用Service,在主要應(yīng)用程序和任何單獨的Activity生命周期外處理任務(wù)嘲玫。
常見應(yīng)用
- 天氣悦施、電子郵件或者社交網(wǎng)絡(luò)的App,可以定期檢查網(wǎng)絡(luò)上更新的服務(wù)去团。
- 一個游戲歼争,可以在用戶需要的時候創(chuàng)建一個Service下載并處理相關(guān)內(nèi)容。
- 一個照片或者多媒體應(yīng)用保持數(shù)據(jù)的在線同步渗勘。
- 一個視頻編輯軟件沐绒,可以將繁重的處理工作放置在服務(wù)隊列,降低系統(tǒng)能耗旺坠。
- 一個新聞應(yīng)用乔遮,可以實現(xiàn)預(yù)加載內(nèi)容的服務(wù),當用戶啟動時取刃,提前下載相應(yīng)新聞蹋肮,提高性能和相應(yīng)能力出刷。
開啟Service的兩種方式:
- startService(Intent serviceIntent) 一個組件可以通過startService的方式來開啟Service服務(wù)。這種方式開啟的Service可以調(diào)用stopSelf()來停止服務(wù)坯辩,也可以通過在其他組件中調(diào)用stopService()方法來停止馁龟。
Intent serviceIntent = new Intent(this, FirstStartedService.class);
startService(serviceIntent);
FirstStartedService就是開啟的繼承自Service的服務(wù)。
public class FirstStartedService extends Service {
private CustomHanlder ch;
public FirstStartedService() {
}
@Override
public void onCreate() {
super.onCreate();
Log.w("service created:","flag");
HandlerThread ht=new HandlerThread("handler.thread.name");
ht.start();
ch=new CustomHanlder(ht.getLooper());
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w("service started:","flag");
Log.w("main thread id:",""+Thread.currentThread().getName()+Thread.currentThread().getId());
//do service task;
//stopSelf();
ch.sendEmptyMessage(0);
return Service.START_STICKY;
}
private class CustomHanlder extends Handler{
public CustomHanlder(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.w("handler thread id:",""+Thread.currentThread().getName()+Thread.currentThread().getId());
}
}
}
2.bindService(Intent service ,ServiceConnection conn ,Int flags) 參數(shù)service是指要綁定的Service漆魔,conn是ServiceConnection對象坷檩,這個對象不能為null,flags為binding的類型改抡,可以為0矢炼。 這種方式開啟的Service會一直運行,直到?jīng)]有組件綁定這個Service的時候系統(tǒng)才會停止Service阿纤。一般情況下句灌,一個組件在不需要Service服務(wù)后要調(diào)用unBindService(ServiceConnection conn)來解綁Service。
一個簡單示例:Activity作為客戶端使用bindService的方式開啟一個Service服務(wù)欠拾,并向服務(wù)端發(fā)送一個字符串胰锌,服務(wù)端接收字符串后向客戶端返回一個字符串。這也是一個簡單的進程間通信(IPC)的例子
客戶端代碼:
public class ServiceTestScreen extends AppCompatActivity {
private TextView tv;
public ServiceTestScreen() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_test_screen);
tv = (TextView) findViewById(R.id.reply_text);
}
public void onClickButton(View v) {
int id = v.getId();
switch (id) {
case R.id.start_service: {
Intent serviceIntent = new Intent(this, FirstStartedService.class);
startService(serviceIntent);
break;
}
case R.id.bind_service: {
Intent serviceIntent = new Intent(this, FirstBinderService.class);
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
break;
}
case R.id.start_intent_service: {
Intent serviceIntent = new Intent(this, FirstIntentService.class);
startService(serviceIntent);
break;
}
case R.id.send_msg: {
if (serviceBound) {
if (serverMsger != null) {
Message msg = new Message();
Bundle data = new Bundle();
data.putString("send", "client msg");
msg.setData(data);
msg.replyTo = clientMsger;
try {
serverMsger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
break;
}
}
}
private boolean serviceBound = false;
private Messenger serverMsger;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.w("component name:", name.getClassName());
serverMsger = new Messenger(binder);
serviceBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
serverMsger = null;
serviceBound = false;
}
};
private Handler h = new Handler() {
@Override
public void handleMessage(Message msg) {
tv.setText(msg.getData().getString("reply"));
}
};
private Messenger clientMsger = new Messenger(h);
@Override
protected void onStop() {
super.onStop();
if (serviceBound) {
unbindService(serviceConnection);
serviceBound = false;
serverMsger = null;
}
}
}
服務(wù)端代碼:
public class FirstBinderService extends Service {
private final Messenger serverMsger = new Messenger(new MessageHandler());
public FirstBinderService() {
}
@Override
public IBinder onBind(Intent intent) {
return serverMsger.getBinder();
}
private class MessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Message replyMsg = new Message();
Bundle data = new Bundle();
data.putString("reply", msg.getData().getString("send") + "--server msg");
replyMsg.setData(data);
try {
msg.replyTo.send(replyMsg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
示例效果圖:
![Activity獲取Service的返回字符串](https://github.com/xinhehappy/Images/blob/master/Service.png?raw=true)
總結(jié)
本文主要總結(jié)了Android中啟動Service的兩種方式藐窄,并用了具體示例來進行演示资昧,完成了使用bindService的方式進行進程間通信。如果總結(jié)的有錯誤或不足的地方枷邪,歡迎大家批評指正榛搔。
示例代碼
個人主頁
GitHub