Service和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的请求或者动作。你可以在服务中开一一个线程,在线程中做耗时动作。
一.基础知识
服务一般分为两种:1:本地服务, Local Service 用于应用程序内部。在Service可以调用Context.startService()启动,调用Context.stopService()结束。在内部可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。无论调用了多少次startService(),都只需调用一次stopService()来停止。
2:远程服务, Remote Service 用于android系统内部的应用程序之间。可以定义接口并把接口暴露出来,以便其他应用进行操作。客户端建立到服务对象的连接,并通过那个连接来调用服务。调用Context.bindService()方法建立连接,并启动,以调用 Context.unbindService()关闭连接。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。提供给可被其他应用复用,比如定义一个天气预报服务,提供与其他应用调用即可。
3、生命周期
context.startService() ->onCreate()- >onStart()->Service running--调用context.stopService() ->onDestroy()
context.bindService()->onCreate()->onBind()->Service running--调用>onUnbind() ->onDestroy()
二.本地服务演示
1、startService的demo
(1)服务端
package com.example.localserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class DataService extends Service {
public static final String TAG = "LocalService";
@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 super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "onStart");
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return null;
}
}
(2)客户端
package com.example.localserver;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
public static final String TAG = "MainActivity";
private Button mbtn1;
private Button mbtn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn1 = (Button) findViewById(R.id.start_service);
mbtn2 = (Button) findViewById(R.id.stop_service);
mbtn1.setOnClickListener(this);
mbtn2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent mIntent = new Intent(this, DataService.class);
switch (v.getId()) {
case R.id.start_service:
Log.d(TAG, "click Start Service button");
startService(mIntent);
break;
case R.id.stop_service:
Log.d(TAG, "click Stop Service button");
stopService(mIntent);
break;
default:
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
【实验结果】
06-10 05:56:54.182: D/MainActivity(2084): click Start Service button
06-10 05:56:54.216: D/LocalService(2084): onCreate
06-10 05:56:54.228: D/LocalService(2084): onStartCommand
06-10 05:56:54.228: D/LocalService(2084): onStart
06-10 05:57:08.123: D/MainActivity(2084): click Start Service button
06-10 05:57:08.186: D/LocalService(2084): onStartCommand
06-10 05:57:08.186: D/LocalService(2084): onStart
06-10 05:57:13.865: D/MainActivity(2084): click Stop Service button
06-10 05:57:13.880: D/LocalService(2084): onDestroy
【分析】
startService的特点是activity与service没有共存亡,当退出activity时,service仍在后台运行,所以,当再次进入activity时,点击开始按钮,就没有再使用onCreate方法了,而是直接调用onStartCommand方法。
2、bindService的demo
bindservice实现的关键之处,在于 onBind(Intent) 这个方法 返回了一个实现了 IBinder 接口的对象,这个对象将用于绑定 Activity 与 Service 通信。
【实现方法】
(1)Service中,创建一个 Binder实体,重载onBind(Intent intent)方法,返回Binder实例给Activity,然后执行onCreate()函数。
(2)Activity中,通过private ServiceConnection sc = new ServiceConnection() 建立一个Service连接,onServiceConnected()获取Service实例,onServiceDisconnected()释放连接;并通过IBinder接口,调用service中的方法。
(3)Activity中,Intent intent = new Intent("******"); 构建一个service的action,然后bindService(intent, sc, BIND_AUTO_CREATE)绑定服务
【demo】
(1)service端
package com.example.localserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class DataService extends Service {
public static final String TAG = "LocalService";
private DataDownloadBinder mBinder = new DataDownloadBinder();
@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 super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
}
}
package com.example.localserver;
import android.os.Binder;
import android.util.Log;
public class DataDownloadBinder extends Binder{
public static final String TAG = "Binder";
public void startDownload() {
Log.d(TAG, "startDownload() executed");
}
public int add(int a, int b) {
Log.d(TAG, "add() executed");
return a + b;
}
// 执行具体的下载任务
}
(2)clinet端
package com.example.localserver;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
public static final String TAG = "MainActivity";
private Button mbtn1;
private Button mbtn2;
private Button mbtn3;
private Button mbtn4;
private DataDownloadBinder mbinder;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mbinder = (DataDownloadBinder) service;
mbinder.startDownload();
int sum = mbinder.add(3, 5);
Log.d(TAG, "sum = " + sum);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn1 = (Button) findViewById(R.id.start_service);
mbtn2 = (Button) findViewById(R.id.stop_service);
mbtn3 = (Button) findViewById(R.id.bind_service);
mbtn4 = (Button) findViewById(R.id.unbind_service);
mbtn1.setOnClickListener(this);
mbtn2.setOnClickListener(this);
mbtn3.setOnClickListener(this);
mbtn4.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent mIntent = new Intent(this, DataService.class);
switch (v.getId()) {
case R.id.start_service:
Log.d(TAG, "click Start Service button");
startService(mIntent);
break;
case R.id.stop_service:
Log.d(TAG, "click Stop Service button");
stopService(mIntent);
break;
case R.id.bind_service:
bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(mServiceConnection);
break;
default:
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
【实验结果】
06-10 06:03:27.322: D/MainActivity(2195): click Start Service button
06-10 06:03:27.376: D/LocalService(2195): onCreate
06-10 06:03:27.388: D/LocalService(2195): onStartCommand
06-10 06:03:27.388: D/LocalService(2195): onStart
06-10 06:03:39.088: D/LocalService(2195): onBind
06-10 06:03:39.132: D/Binder(2195): startDownload() executed
06-10 06:03:39.132: D/Binder(2195): add() executed
06-10 06:03:39.132: D/MainActivity(2195): sum = 8
06-10 06:03:52.363: D/LocalService(2195): onUnbind
06-10 06:04:08.229: D/MainActivity(2195): click Start Service button
06-10 06:04:08.243: D/LocalService(2195): onStartCommand
06-10 06:04:08.243: D/LocalService(2195): onStart
06-10 06:04:19.284: D/MainActivity(2195): click Stop Service button
06-10 06:04:19.307: D/LocalService(2195): onDestroy
三、远程服务演示
需要使用aidl与bindService共同实现远程服务。
(1)client
package com.example.client;
import com.example.service.ICom;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "Client";
private ICom mICom;
private Button mbtn1;
private Button mbtn2;
private TextView mTV;
private String url;
private boolean isBind = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn1 = (Button) findViewById(R.id.btn_bind);
mbtn2 = (Button) findViewById(R.id.btn_allinfo);
mbtn2.setOnClickListener(this);
mbtn1.setOnClickListener(this);
mTV = (TextView) findViewById(R.id.textView);
}
ServiceConnection mSC = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected...");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "Client onServiceConnected");
mICom = ICom.Stub.asInterface(service);
if (mICom == null) {
Log.d(TAG, "Failed");
} else {
isBind = true;
mbtn1.setText("断开");
mTV.setText("已连接");
try {
url = mICom.getWebSite();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind:
if (isBind == false) {
Intent mIntent = new Intent();
mIntent.setAction("com.example.remote");
mIntent.setPackage("com.example.service");
mbtn2.setEnabled(true);
bindService(mIntent, mSC, Context.BIND_AUTO_CREATE);
} else {
mbtn2.setEnabled(false);
mbtn1.setText("连接");
isBind = false;
mTV.setText("已断开连接!");
unbindService(mSC);
}
break;
case R.id.btn_allinfo:
mTV.setText(url);
break;
default:
break;
}
}
}
(2)server
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class RemoteService extends Service {
private static final String TAG = "Remote Service";
private Com mtest = new Com();
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.d(TAG, "Oncreate");
super.onCreate();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, "OnDestroy");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return mtest;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
}
private class Com extends ICom.Stub {
@Override
public String getWebSite() throws RemoteException {
String url = "www.baidu.com";
return url;
}
}
}
(3)aidl文件
package com.example.service;
interface ICom{
String getWebSite();
}