介绍:
Service是一种不提供用户交互页面但是可以在后台长时间运行的组件,可以通过在AndroidManifest.xml设置Service的android:process=":remote"
属性,让Service运行另一个进程中,也就是说,虽然你是在当前应用启动的这个Service,但是这个Service和这个应用并不是同一个进程。因为Service可以运行在不同的进程,这里说一下Android中几种进程的优先级,当系统内存不足时候,系统会从优先级低的进程开始回收,下面根据优先级由高到低列出Android中几种进程。
service配置:
<manifest ... >
...
<application ... >
<service android:name=".DemoService" />
...
</application>
</manifest>
Service是一个抽象类,使用需要我们去实现它的抽象方法onBind()
,Service有且仅有这一个抽象方法,还有一些其他的生命周期回调方法需要复写帮助我们实现具体的功能。
- onCreate(),在创建服务时候,可以在这个方法中执行一些的初始化操作,它在
onStartCommand()
和onBind()
之前被调用。如果服务已经存在,调用startService()
启动服务时候这个方法不会调用,只会调用onStartCommand()
方法。 - onStartCommand(),其他组件通过
startService()
启动服务时候会回调这个方法,这个方法执行后,服务会启动被在后台运行,需要调用stopSelf()
或者stopService()
停止服务。 - onBind(),其他组件通过
bindService()
绑定服务时候会回调的方法,这是Service的一个抽象方法,如果客户端需要与服务交互,需要在这个方法中返回一个IBinder
实现类实例化对象,如果不想其他客户端与服务绑定,直接返回null。 - onDestroy(),当服务不在还是用且即将被销毁时,会回调这个方法,可以在这个方法中做一些释放资源操作,这是服务生命周期的最后一个回调。
// 启动服务
Intent intent = new Intent(this, DemoService.class);
startService(intent);
// 停止服务
stopService(intent)
// 绑定服务
ServiceConnection mConnection = ServiceConnection() { ... };
Intent intent = new Intent(this, DemoService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
// 解除绑定
unbindService(mConnection);
Service生命周期:
(从创建到销毁)跟它被启动的方式有关系,这里只介绍startService
和bindService
两种启动方法时候Service的生命周期。startService
启动方式,其他组件用这种方式启动服务,服务会在后台一直运行,只有服务调用本身的stopSelf()
方法或者其他组件调用stopService()
才能停止服务。bindService
启动方式,其他组件用这种方法绑定服务,服务通过IBinder与客户端通信,客户端通过unbindService
接触对服务的绑定,当没有客户端绑定到服务,服务会被系统销毁。
这两种生命周期不是独立的,组件可以同时用startService
启动服务同时用bindService
绑定服务,例如跨页面的音乐播放器,就可以在多个页面同时绑定同一个服务,这种情况下需要调用stopService()
或者服务本身的stopSelf()
并且没有客户端绑定到服务,服务才会被销毁。
AIDL
AIDL全称Android Interface Definition Language,是Android提供的一种进程间通信机制。
数据类型
- Java四种数据类型(int,string,byte,char)
- list和Map类型,集合中元素需为支持的数据类型
- 其他AIDL生成的接口
- Parcelable 序列化的对象
AIDL的使用主要包括三个部分:
- 定义一个AIDL接口。
- 为远程服务(Service)实现对应Stub。
- 将服务“暴露”给客户程序使用。
新建service,在service中创建AIDL对应的Stub对象,工onBinder()方法中返回。相关代码如下:
package com.xiaoyao.aidl_demo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
* 对应AIDL服务端
*/
public class TestService extends Service {
public TestService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public IBinder onBind(Intent intent) {
//返回Binder对象,此对象为对应AIDL文件生成的Java文件中的Stub对象
return new TestAidl.Stub() {
@Override
public int getCount(int a, int b) throws RemoteException {
return a+b;
}
};
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
在activity中绑定服务,并开启服务。相关代码如下:
package com.xiaoyao.aidl_demo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TestAidl mAidl;
private TextView mTv;
private MyServiceConnection mConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv =findViewById(R.id.tv);
initService();
}
private void initService(){
mConnection = new MyServiceConnection();
Intent intent = new Intent(this,TestService.class);
bindService(intent,mConnection,BIND_AUTO_CREATE);
};
class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//通过binder转化成AIDL对象
mAidl= TestAidl.Stub.asInterface(iBinder);
Log.d("xxx", "onServiceConnected: maidl=" +mAidl);
int count = 0;
try {
//此处用到AIDL接口中的方法,方法的具体实现在service端
count = mAidl.getCount(1,2);
Log.d("xxx", "onServiceConnected: count="+count);
} catch (RemoteException e) {
e.printStackTrace();
}
mTv.setText(Integer.valueOf(count).toString());
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mAidl = null;
}
}
}