由于一直在做上层App,与AIDL接触的真心很少,上层应用之间的交互使用AIDL不多,可以使用Broadcast、ContentProvider等等。但是最近确实被AIDL摆了一道,决定认真调试一下。
AIDL其实是一个IPC通信机制, 即进程之间也可以相互通信,传递有效数据,那么怎么创建或者说需要什么呢?首先交互需要服务端和客户端,其次主要的方式创建aidl文件,其实质还是通过service进行交互。
1.AIDLServer
1.1 Person的创建
package com.example.edwardadmin.aidlmodel;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by EdwardAdmin on 2017/9/24.
*/
public class Person implements Parcelable {
private String mUserName;
private String mUserAge;
public Person(String username, String userage) {
mUserName = username;
mUserAge = userage;
}
public String getmUserName() {
return mUserName;
}
public String getmUserAge() {
return mUserAge;
}
@Override
public String toString() {
return super.toString();
}
protected Person(Parcel in) {
mUserName = in.readString();
mUserAge = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mUserName);
dest.writeString(mUserAge);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
注意点:
Model类需要实现 Parcelable,重写重要方法
1.2 IPersonAidlInterface.aidl创建
// IPersonAidlInterface.aidl
package com.example.edwardadmin.aidl;
parcelable Person;
注意点:
parcelable 是小写
1.3 IRomteAidlInterface.aidl创建
// IRomteAidlInterface.aidl
package com.example.edwardadmin.aidl;
// Declare any non-default types here with import statements
interface IRomteAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
String getPersonUserName();
String getPersonUserAge();
}
1.4 RmoteService的创建
package com.example.edwardadmin.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import com.example.edwardadmin.aidl.IRomteAidlInterface;
import com.example.edwardadmin.aidlmodel.Person;
/**
* Created by EdwardAdmin on 2017/9/24.
*/
public class RmoteService extends Service {
private static final String TAG = "RmoteService";
private Person mPerson;
private String mUserName;
private String mUserAge;
@Override
public void onCreate() {
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind Service success!");
mPerson = new Person("Edward", "24");
return new RomteBinder();
}
class RomteBinder extends IRomteAidlInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String getPersonUserName() throws RemoteException {
mUserName = mPerson.getmUserName();
Log.d(TAG, "Person mUserName = " + mUserName);
return mUserName;
}
@Override
public String getPersonUserAge() throws RemoteException {
mUserAge = mPerson.getmUserAge();
Log.d(TAG, "Person mUserAge = " + mUserAge);
return mUserAge;
}
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
1.5 AndroidManifest.xml创建
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.edwardadmin.aidlserver">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.example.edwardadmin.service.RmoteService">
<intent-filter>
<action android:name="android.intent.action.RESPOND_AIDL_MESSAGE"></action>
</intent-filter>
</service>
</application>
</manifest>
1.6 AIDLServer项目结构
AIDLServer项目结构图2.AIDLClient创建
2.1 copy aidl to client.
2.2 Connect & Acquire
package com.example.edwardadmin.aidl;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final String BIND_SERVICE_ACTION = "android.intent.action.RESPOND_AIDL_MESSAGE";
private IRomteAidlInterface iRomteAidlInterface;
private Button mConnectButton;
private Button mAcquireButton;
private String mUsername;
private String mUserage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mConnectButton = (Button) this.findViewById(R.id.connect);
mAcquireButton = (Button) this.findViewById(R.id.acquire_info);
mConnectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bindService();
}
});
mAcquireButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (null != iRomteAidlInterface) {
try {
mUsername = iRomteAidlInterface.getPersonUserName();
mUserage = iRomteAidlInterface.getPersonUserAge();
Toast.makeText(getApplicationContext(), "mUsername = " + mUsername + ",mUserage = " + mUserage, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iRomteAidlInterface = IRomteAidlInterface.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
iRomteAidlInterface = null;
}
};
private void bindService() {
Intent serviceIntent = new Intent();
serviceIntent.setAction(BIND_SERVICE_ACTION);
//serviceIntent.setComponent(new ComponentName("com.example.edwardadmin.aidlserver", "com.example.edwardadmin.service.RmoteService"));
final Intent eintent = new Intent(achieveExplicitFromImplicitIntent(this, serviceIntent));
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
Log.d(TAG, "bindService");
}
private void unBindSevice() {
unbindService(serviceConnection);
Log.d(TAG, "unbindService");
}
@Override
protected void onDestroy() {
super.onDestroy();
unBindSevice();
}
public Intent achieveExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
Log.d(TAG,"packageName = " + packageName);
Log.d(TAG,"className = " + className);
ComponentName component = new ComponentName(packageName, className);
Intent explicitIntent = new Intent(implicitIntent);
explicitIntent.setComponent(component);
return explicitIntent;
}
}
2.3 AIDLClient项目结构
AIDLClient项目结构图Question1.当AIDLClient创建成功之后,Service连接不上?
Answer:
1).Intent 除了必要的Action,还需要ComponentName,参数packageName:"AIDLServer->AndroidMainfest.xml->package",参数className:"AIDLServer->Service完整的包名+ServiceName"
2).如果第一点不清楚的,调用achieveExplicitFromImplicitIntent方法,获取正确的Intent。
Github地址:
AIDLServer:https://github.com/EricWinner/AIDLServer
AIDLClient:https://github.com/EricWinner/AIDLClient
有任何问题,欢迎指出.
网友评论