AndroidStudio 和 EclipseADT 创建项目时的 aidl 通信
Eclipse 用的人不多,在使用 aidl 实现进程间通信的时候,studio 和 eclipse 还是有点儿区别的。比如现在我们要实现一个求和功能,client 只负责输入,service 负责计算功能。
client 界面:
1.使用 Eclipse 编写 Service 代码
service 目录结构:
Calculate.aidl:
package com.demo.aidl;
interface Calculate{
double doCalculate(double a,double b);
}
CalculateService:
package com.demoserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.demo.aidl.Calculate;
public class CalculateService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
private final Calculate.Stub mBinder = new Calculate.Stub() {
@Override
public double doCalculate(double a, double b) throws RemoteException {
return a + b;
}
};
}
注意:CalculateService 需要在清单文件里注册并设置 action
<service
android:name="com.demoserver.CalculateService"
android:exported="true" >
<intent-filter>
<action android:name="com.demoserver.CalculateService" />
</intent-filter>
</service>
2.使用 Eclipse 编写 client:
这里的 Calculate.aidl 都必须和 Service 端一样,界面太简单,不再贴出,MainActivity 代码:
public class MainActivity extends Activity {
private EditText numEt1, numEt2;
private Button calculateBtn;
private Calculate mService;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
mService = null;
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
mService = Calculate.Stub.asInterface(arg1);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
numEt1 = (EditText) findViewById(R.id.numEt1);
numEt2 = (EditText) findViewById(R.id.numEt2);
calculateBtn = (Button) findViewById(R.id.calculateBtn);
calculateBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
gotoCalculate();
}
});
Intent intent = new Intent("com.demoserver.CalculateService");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
private void gotoCalculate() {
double num1 = Double.parseDouble(numEt1.getText().toString());
double num2 = Double.parseDouble(numEt2.getText().toString());
try {
String text = "Sum=" + mService.doCalculate(num1, num2);
Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
隐式启动服务,可以完成计算求和功能。
3.使用 Android Studio 编写 client 代码的不同之处:
目录结构:
需要建一个文件夹,名为 aidl
,和java
文件夹同级,这里面的Calculate.aidl
的包名和内容都和 service 端相同。然后手动 rebuild 一下,可以看到自动生成的 java 文件:
启动服务时,5.0 以上的系统会报错:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{lpj.com.tests/lpj.com.tests.MainActivity}:
java.lang.IllegalArgumentException: Service Intent must be explicit: Intent {
act=com.demoserver.CalculateService }
因为隐式启动服务需要告诉 Intent 包名:
Intent intent = new Intent("com.demoserver.CalculateService");
intent.setPackage("com.demoserver");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
多加这句intent.setPackage("com.demoserver")
就 OK 了。