Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制)。首先明确一点,尽管Service是进行后台计算的,但它仍然是运行在主线程中,处理耗时造作仍然需要在子线程处理。
Service的分类,根据调用者和service在不在同一个进程里,Service可以分为:本地服务(LocalService)、远程服务(RemoteService)。
它的作用:1.耗时操作的执行:ANR对Activity和BroadcastReceiver响应时间的限制(Activity对事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不适合执行较耗时操作,这样像网络、数据库、复杂计算这类耗时操作的执行就需要一个组件来承担。Service作为Android四大组件之一,其功能之一就是耗时操作的执行另外相对于Thread的耗时操作。
2.Service的可控性。任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例。Service可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,而新产生的Thread在销毁了它的Activity仍然可以运行,但已经没有办法对这可Thread操控。。
3.应用内或应用间数据通信(IPC通信):Android每个应用程序都在自己的dalvik虚拟机中运行,一个应用是不允许访问其他应用的内存信息的,为此Android引入了Content Provider在不同应用间共享数据,BroadcastReceiver广播信息给不同应用程序,但Content Provider更多用于数据的共享,BroadcastReceiver广播的信息会被所有应用接收较耗费系统资源,对于两个应用间动态的进行交互还需要通过Service来完成。
本地服务(LocalService)
调用者和service在同一个进程里,所以运行在主进程的main线程中。所以不能进行耗时操作,可以采用在service里面创建一个Thread来执行任务,service影响的是进程的生命周期。Service有两种启动状态,Service这两种状态可以共存。
第一种是直接start方式开启service,主要用于执行后台的计算。
使用service的步骤:
1,定义一个类继承service
2,manifest.xml文件中配置service
3,使用context的startService(Intent)方法启动service
4,不在使用时,调用stopService(Intent)方法停止服务
使用start方式启动的生命周期:onCreate() -- > onStartCommand() -- > onDestory()
注意:如果服务已经开启,不会重复回调onCreate()方法,如果再次调用context.startService()方法,service而是会调用onStart()或者onStartCommand()方法。停止服务需要调用context.stopService()方法,服务停止的时候回调onDestory被销毁。
特点:一旦服务开启就跟调用者(开启者)没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行,开启者不能调用服务里面的方法。
第二种是绑定状态bind的方式启动,主要用于和其他组件交互。
使用service的步骤:
1,定义一个类继承Service
2,在manifest.xml文件中注册service
3,使用context的bindService(Intent,ServiceConnection,int)方法启动service
4,不再使用时,调用unbindService(ServiceConnection)方法停止该服务
使用这种start方式启动的service的生命周期如下:onCreate() -- > onBind() --> onUnbind() -- > onDestory() (注意:绑定服务不会调用onStart()或者onStartCommand()方法)
特点:bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可以调用服务里面的方法。
DEMO:ServiceLifeCycle类中的两个静态方法是为了在验证启动模式的,主动关闭当前服务的效果,也可以通过广播的形式来关闭开启的服务。
public class ServiceLifeCycle extends Service {
private static ApkActivity m;
private String TAG = "ServiceLifeCycle";
public static void startService(Context context) {
if (null != context) {
m = (ApkActivity) context;
Intent intent = new Intent(context, ServiceLifeCycle.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(intent);
}
}
public static void stopService(Context context) {
if (null != context) {
Intent intent = new Intent(context, ServiceLifeCycle.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.stopService(intent);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate()");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.e(TAG, "onStart(...)");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy()");
if (m != null) {
m.finish();
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind(...)");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind(...)");
return super.onUnbind(intent);
}
public class MyBinder implements IBinder {
@Override
public String getInterfaceDescriptor() throws RemoteException {
return null;
}
@Override
public boolean pingBinder() {
return false;
}
@Override
public boolean isBinderAlive() {
return false;
}
@Override
public IInterface queryLocalInterface(String descriptor) {
return null;
}
@Override
public void dump(FileDescriptor fd, String[] args) throws RemoteException {
}
@Override
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
}
@Override
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
return false;
}
@Override
public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException {
}
@Override
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return false;
}
}
}
public class TestActivity extends Activity {
MyServiceConnection myServiceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_apk);
initView();
}
private void initView() {
myServiceConnection = new MyServiceConnection();
TextView mStart = (TextView) findViewById(R.id.start_service);
TextView mStop = (TextView) findViewById(R.id.stop_service);
mStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ServiceLifeCycle.startService(ApkActivity.this);
bindService(new Intent(TestActivity.this, ServiceLifeCycle.class), myServiceConnection, BIND_AUTO_CREATE);
}
});
mStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//静态方法关闭
// ServiceLifeCycle.stopService(ApkActivity.this);
unbindService(myServiceConnection);
}
});
}
private void testStartService() {
Intent mService = new Intent(this, ServiceLifeCycle.class);
startService(mService);
}
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ServiceLifeCycle.MyBinder myBinder = (ServiceLifeCycle.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
xml布局简单就不在提供了。
注册列表:
<service android:name=“.downloadApk.ServiceLifeCycle"/>
startService启动打印结果:
05-17 04:03:17.216 19745-19745/com.algorithm.algorithm E/ServiceLifeCycle: onCreate()
05-17 04:03:17.216 19745-19745/com.algorithm.algorithm E/ServiceLifeCycle: onStartCommand()
05-17 04:03:17.216 19745-19745/com.algorithm.algorithm E/ServiceLifeCycle: onStart(...)
bindService打印:
05-17 08:25:02.112 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onCreate()
05-17 08:25:02.112 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onBind(…)
点击unbindService,打印:
05-17 08:26:15.408 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onUnbind(...)
05-17 08:26:15.408 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onDestroy()
2.远程服务
调用者和service不在同一个进程中,service在单独的进程中的main线程,是一种垮进程通信方式.
绑定远程服务的步骤:
a.在服务的内部创建一个内部类,提供一个方法,可以间接调用服务的方法
b.把暴露的接口文件的扩展名改为.aidl文件 去掉访问修饰符
c.实现服务的onbind方法,继承Bander和实现aidl定义的接口,提供给外界可调用的方法
d.在activity 中绑定服务。bindService()
e.在服务成功绑定的时候会回调 onServiceConnected方法 传递一个 IBinder对象
f. AIDL定义的接口.Stub.asInterface(binder) 调用接口里面的方法
具体的内容可以参照我之后的文章:android AIDL
========================================