1. 概念理解
Service运行在后台back键,应用退出,不会停止
Service生命周期方法在主线程执行
2. 启动Service和绑定Service声明周期调用
2.1. 启动
Intent intent=new Intent(MainActivity.this,MyService.class);
startService(intent);
startService:
第一次调用:构造方法->onCreate -> onStart -> onStartCommand
后面每次调用:onStartCommand
stopService:
onDestroy销毁
2.2. 绑定Service
ServiceConnection connection=null;
public void bindService(View view){
// 绑定服务器的理解 Activity作为宿组和Service进行绑定
// 可以都有多个Activity绑定同一个Service,
// 所有的Activity 断开以后才会调用Service 的onUnbind 回调方法
Intent intent=new Intent(MainActivity.this,MyService.class);
if(connection==null){
connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
// Context.BIND_AUTO_CREATE 模式 绑定并且启动
bindService(intent,connection, Context.BIND_AUTO_CREATE);
}else {
Log.e(TAG,"服务已经绑定");
}
}
@Override
protected void onDestroy() {
// 如果应用退出不解绑,会内存泄露
if(connection!=null){
unbindService(connection);
connection=null;
}
super.onDestroy();
}
bindService:
第一次调用:构造方法->onCreate -> onBind -> ServiceConnection(A)
解绑:
unbindService: onUnbind -> onDestroy
必须调用解绑,绑定是以为Activity作为宿主,否则Activity销毁的时候会泄露,抛异常
3. AIDL 远程调用
在A App 中 调用 B App 的服务器暴露出来的方法
aldi 的目的就是 调用 B 服务中暴露的方法
server端:
1. 通过aidl暴露接口,传递自定义需要打包,实现Parcelable 接口
IStudentInterface.aidl
// IStudentInterface.aidl
package com.example.myremote;
// 导入包
import com.example.myremote.Student;
// Declare any non-default types here with import statements
interface IStudentInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*1. 接口名称和返回值相同
*2. 不能你有访问修饰符修饰
*3. 实体类必须要实现Parcelable接口
*
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
Student getStudentById(int id);
}
Student.aidl
package com.example.myremote;
parcelable Student;
生产的aidl源码在: build/generated/source/aidl/包名下
2. 通过Binder 暴露服务中方法
package com.example.myremote;
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 {
public RemoteService() {
}
String TAG="denganzhi1";
// 3. Binder 返回客户端,返回给A 应用
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.e(TAG,"onBind");
// return null;
return new StudentSevice();
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG,"onUnbind");
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
// 1. 在服务中定义方法
public Student getStudentNewById(int i){
return new Student(100,"xiaohei");
}
// 2. 暴露服务中方法,通过Binder包装
/**
* public static abstract class Stub extends android.os.Binder implements com.example.myremote.IStudentInterface
* 继承关系
*/
class StudentSevice extends IStudentInterface.Stub{
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public Student getStudentById(int id) throws RemoteException {
Log.e(TAG,"getStudentById:"+id);
return getStudentNewById(1);
}
}
}
AndroidManifest.xml
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true">
<!-- 指定意图,用于Client调用找到 Service端口, 唯一 -->
<intent-filter>
<action android:name="com.example.myremote.RemoteService.Action"></action>
</intent-filter>
</service>
client端:
1. 客户端,拷贝服务端的aidl,实体类,包名要和服务器端一致到客户端项目
2. 客户端绑定服务端,服务端返回Bindder,把Binder转化为接口IStudentInterface
ServiceConnection serviceConnection2=null;
IStudentInterface iStudentInterface=null;
public void bindRemoteServicce(View view){
// 指定隐式意图
Intent intent=new Intent("com.example.myremote.RemoteService.Action");
/**
* bindService方法在5.0以后做出改变,隐式意图需要设置Package 或者 Commponent,直接定义一个action是报异常的。
*/
intent.setPackage("com.example.myremote");
if(serviceConnection2==null){
serviceConnection2=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iStudentInterface= IStudentInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindService(intent,serviceConnection2,Context.BIND_AUTO_CREATE);
}else {
Log.e(TAG,"已经绑定");
}
}
3. 调用AIDL的方法,获取B App传递过来的, 调用方法获取返回值
// 调用AIDL的方法
btn_diaoyong.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(iStudentInterface!=null){
try {
com.example.myremote.Student student = iStudentInterface.getStudentById(1);
Log.e("denganzhi","student..."+student);
} catch (RemoteException e) {
Log.e("denganzhi",e.getMessage());
e.printStackTrace();
}
}
}
});
4. 资源释放
public void unbindRemoteServicce(View view){
if(serviceConnection2!=null){
unbindService(serviceConnection2);
serviceConnection2=null;
iStudentInterface=null;
}else{
Log.e(TAG,"尚未绑定");
}
}
@Override
protected void onDestroy() {
// 如果应用退出不解绑,会内存泄露,抛异常,但是本会奔溃,没有关系
unbindRemoteServicce(null);
super.onDestroy();
}