– layout: post title: “android AIDL” description: category: android tags: [android, app] mathjax: chart: comments: false —
###1. AIDL
AIDL(Android Interface Definition Language)是一种接口定义语言,编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码, AIDL可以处理多线程、多客户端并发访问
###2. 定义AIDL文件
package com.android.example;
Interface IRemoteService {
String hello(String someone);
}
AIDL 会被翻译成对应的 java 文件, 例如, 在 Android Studio 中, 上述的 AIDL 文件会被翻译成 “app/build/generated/source/aidl/debug/com/android/example/IRemoteService.java”
###3. 实现service端
package com.example.service;
import com.example.android.IRemoteService;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class DDService extends Service {
private static final String TAG = "AIDLService";
@Override
public void onCreate() {
super.onCreate();
System.out.println("DDService onCreate........" + "Thread: " + Thread.currentThread().getName());
}
@Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "onBind() called");
return mStub;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind() called");
return true;
}
private final IRemoteService.Stub mStub = new IRemoteService.Stub() {
public String hello(String someone) throws RemoteException {
Log.i(TAG, "hello() called");
return "hello, " + someone;
}
};
}
然后在AndroidManifest 中添加如下配置
<service android:name=".AIDLService"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.AIDLService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
AndroidManaifest.xml 里 Service 元素的常见选项
- android:name service name
- android:label 显示的服务名, 若不设置则显示为类名
- android:icon service 的图标
- android:permission 申明service的权限, 只有获取了该权限的应用才能链接此服务
- android:process 表示该服务是否运行在另外一个进程
- android:enabled 如果设置为true, 该service会默认被系统启动, 默认值为false
- android:exported 表示该服务是否能被外部的应用或者组件连接, 默认为false, 则只能被同一应用程序/组件或者具有同一UID的应用程序才能连接该应用
###4. 实现client端
package com.example.client;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.example.android.IRemoteService;
public class MainActivity extends Activity {
private Button bindBtn;
private Button helloBtn;
private Button unbindBtn;
private IRemoteService remoteService;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("ServiceConnection", "onServiceConnected() called");
remoteService = IRemoteService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("ServiceConnection", "onServiceDisconnected() called");
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bindBtn = (Button) findViewById(R.id.bindBtn);
bindBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("android.intent.action.AIDLService");
intent.setPackage("com.example.service");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
bindBtn.setEnabled(false);
greetBtn.setEnabled(true);
unbindBtn.setEnabled(true);
}
});
helloBtn = (Button) findViewById(R.id.helloBtn);
helloBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String retVal = remoteService.hello("AIDL");
Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
}
}
});
unbindBtn = (Button) findViewById(R.id.unbindBtn);
unbindBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
unbindService(conn);
bindBtn.setEnabled(true);
greetBtn.setEnabled(false);
unbindBtn.setEnabled(false);
}
});
}
###5. bindService() 与 startService()
service通过Context.startService()方法开始,通过Context.stopService()方法停止;也可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己。只要调用一次stopService()方法便可以停止服务,无论之前它被调用了多少次的启动服务方法
客户端建立一个与Service的连接,并使用此连接与Service进行通话,通过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务, 这个时候调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出, 多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务, 但是只有通过startService()方法启动service服务时才会调用onStart()方法
如果一个service允许别人绑定,那么需要实现以下额外的方法:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
bindService() 与 startService()可以同时使用, 可以绑定到一个通过startService()启动的服务, 如一个intent想要播放音乐,通过startService() 方法启动后台播放音乐的service, 然后,也许用户想要操作播放器或者获取当前正在播放的乐曲的信息,一个activity就会通过bindService()建立一个到此service的连接. 这种情况下 stopService() 在全部的连接关闭后才会真正停止service