一、基本概念
(1)远程服务:运行在其他应用里面的服务
(2)本地服务:运行在自己应用里面的服务
(3)进行进程间通信IPC
(4)aidl Android interface Defination Language Android 接口定义语言,是专门是用来解决进程间通信的
二、aidl的使用
(1)先把远程服务用于暴露方法的.java接口文件的后缀名改为.aidl
(2)在远程服务上右击选择刷新,此时远程服务的gen的目录对应的包名下会自动生成java接口文件
(3)将刚才修改的.aidl文件中的类和方法的修饰符public去掉,因为aidl语言不用public修饰
(4)修改远程服务类中的自定义实现Binder和接口的内部类使其继承自Stub即可
(5)在本地服务上新建个和远程服务一样的包名,并把远程服务的aidl文件拷贝到该包下
(6)在本地服务上右击选择刷新,此时本地服务的gen的目录会自动生成远程服务的包和对应的java接口文件
(7)在本地服务中使用Stub.asInterface(service)获取远程服务返回的IBinder对象
(8)通过第7步获得的对象完成对进程间方法的调用,即完成进程间通信
三、远程服务
①项目目录结构图
②RemoteService.java代码
package com.zgs.RemoteService;
import com.zgs.RemoteService.Iservice.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class RemoteService extends Service {
//[2]把我们定义的中间人对象返回
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
//在服务里面定义一个方法
public void testMethod(){
System.out.println("我是远程服务里面的方法");
}
//[1]定义中间人对象
private class MyBinder extends Stub{
//调用testMethod方法
@Override
public void callTestMethod() {
testMethod();
}
}
}
③Iservice.aidl代码
package com.zgs.RemoteService;
interface Iservice {
// 把想暴露的方法暴露出来
void callTestMethod();
}
④AndroidManifest.xml代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zgs.RemoteService"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.zgs.RemoteService.RemoteService">
<intent-filter >
<action android:name="com.zgs.remoteservice"/>
</intent-filter>
</service>
</application>
</manifest>
四、远程服务①项目目录截图
②activity_main.xml界面
③activity_main.xml代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.zgs.LocalService.MainActivity" >
<Button
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="调用远程服务里面的方法" />
</RelativeLayout>
④新建com.zgs.RemoteService包名,然后拷贝Iservice.aidl,然后在本地服务项目上右击选择刷新
⑤MainActivity.java代码
package com.zgs.LocalService;
import com.zgs.RemoteService.Iservice;
import com.zgs.RemoteService.Iservice.Stub;
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.os.RemoteException;
import android.view.View;
public class MainActivity extends Activity {
private Iservice iservice; //中间人对象
private MyConn conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]调用bindservice 获取我们定义的中间人对象
Intent intent = new Intent();
//设置一个action
//Android 5.0一出来后,其中有个特性就是Service Intent must be explitict,
//也就是说从Lollipop开始,service服务必须采用显示方式启动
//但是可以通过以下两行代码搞定隐式方式启动
intent.setAction("com.zgs.remoteservice");
intent.setPackage("com.zgs.RemoteService");
conn = new MyConn();
//[2]目的是为了获取我们定义的中间人对象
bindService(intent, conn,BIND_AUTO_CREATE);
}
//当Activity销毁的时候调用
@Override
protected void onDestroy() {
//当Activity销毁的时候 取消绑定服务
//unbindService(conn);
super.onDestroy();
}
//监视服务的状态
private class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iservice = Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
//点击按钮 调用第8个应用程序服务里面的方法
public void click(View v) {
try {
iservice.callTestMethod();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
五、效果展示