1.在需要提供数据给应用程序的目录中编写服务
frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/MyService.java
2.在源码该模块中如果某个目录已经有aidl文件的话可以直接在该目录下新建你的aidl文件,并编写接口
frameworks/base/packages/SystemUI/src/com/test/IMyAidlInterface.aidl
如果没有现成的目录的话那么可以查看该目录下的Andrioid.mk文件,看看其定义的src文件如下,模块中已经定义了只要是src目录下的aidl文件都会编译,所以不管放src下的哪个地方都可以
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
3.将编写的aidl文件copy一份到test中对应目录
frameworks/base/packages/SystemUI/tests/src/com/test/IMyAidlInterface.aidl
这一步非常关键,如果缺少这一步,你将发现单独编译这个模块可以编译过,但是当你全编源码时会报错,提示找不到这个类,这里非常奇怪,困扰很久的问题,因为特别奇怪,你发现这个接口ide都已经能识别了,引用也正确,而且编译模块没有问题,只有全编代码不行,最后仔细查看了下编译失败报错,原来是test里面的错误,最后发test里面确实没有这个aidl文件,源码里面并不会像AS中写应用那样,会自动帮我们做好这一步.
4.在我们的服务中去编写代码,将我们定义的接口中的stub作为binder在onbind方法中返回给我们的应用,或则说返回给源码其他地方(需要通信,bind我们服务的地方)
package com.android.systemui.keyguard;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.test.IMyAidlInterface;
public class MyService extends Service {
private String mStr = null;
@Override
public void onCreate() {
Log.d("liuquanquan", "MyService onCreate: -----");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("liuquanquan", "MyService onStartCommand: -----");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.d("liuquanquan", "onBind:======= ");
return mBinder;
}
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public String saveString(String str) throws RemoteException {
Log.d("liuquanquan", "saveString: str = "+str);
return str;
}
@Override
public String getString() throws RemoteException {
return "come from SystemUI info";
}
};
}
5.在我们的应用程序(需要通信,bind我们服务的地方),以bindService的形式去启动我们的服务.
package com.test.systemuiclient;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
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.TextView;
import com.test.IMyAidlInterface;
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IMyAidlInterface.Stub.asInterface(service);
try {
mTextView.setText(mService.getString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IMyAidlInterface mService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.mytext);
}
public void click(View view) {
Intent intent = new Intent();
ComponentName componentName = new ComponentName("com.android.systemui"
,"com.android.systemui.keyguard.MyService");
intent.setComponent(componentName);
Log.d("liuquanquan", "click: bindService");
this.bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
// this.startService(intent);
}
public void send(View view) {
try {
mService.saveString("come form client");
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
这样就能在onServiceConnected中得到我们在之前源码中定义的MyServer里面定义的binder对象,
这样整个通信通道就建立成功了,aidl是基于底层binder通信的,其效率,性能开销和可靠性远高于广播.