做者:苍王 时间:2018.6.1android
如下是我这个系列的相关文章,有兴趣能够参考一下,能够给个喜欢或者关注个人文章。git
[Android]如何作一个崩溃率少于千分之三噶应用app--章节列表github
1.经过grade插件完善AndroidManifest.xml配置文件bash
2.经过ContentProvider传输binder对象架构
3.活动binder.stub对象app
4.动态绑定进程service以及binder对象框架
5.多进程binder管理ide
其在利用自定义Gradle插件来插入DispatchService和DipatchProvider。 自定义的Gradle插件只会有app module上运行。 其会读取Manifest里面的内容并进行修改。 svg
1.查找遍历Manifest文件组件化
void injectStubServiceToManifest(Project project) {
println "injectStubServiceToManifest"
//主目录
rootDirPath = project.rootDir.absolutePath
def android = project.extensions.getByType(AppExtension)
this.dispatcher = project.extensions.getByType(DispatcherExtension)
project.afterEvaluate {
android.applicationVariants.all { variant ->
if (pkgName == null) {
//获取包名
pkgName = getPackageName(variant)
println "pkgName:" + pkgName
}
//查找遍历Mainfest文件
variant.outputs.each { output ->
output.processManifest.doLast {
println "manifestOutputDirectory:" + output.processManifest.manifestOutputDirectory.absolutePath
//output.getProcessManifest().manifestOutputDirectory
output.processManifest.outputs.files.each { File file ->
//在gradle plugin 3.0.0以前,file是文件,且文件名为AndroidManifest.xml
//在gradle plugin 3.0.0以后,file是目录,且不包含AndroidManifest.xml,须要本身拼接
//除了目录和AndroidManifest.xml以外,还可能会包含manifest-merger-debug-report.txt等不相干的文件,过滤它
if ((file.name.equalsIgnoreCase("AndroidManifest.xml") && !file.isDirectory()) || file.isDirectory()) {
if (file.isDirectory()) {
//3.0.0以后,本身拼接AndroidManifest.xml
injectManifestFile(new File(file, "AndroidManifest.xml"))
} else {
//3.0.0以前,直接使用
injectManifestFile(file)
}
}
}
}
}
}
}
}
复制代码
其内会写入三种文件
def static final STUB_SERVICE = 'org.qiyi.video.svg.stub.CommuStubService$CommuStubService'
xml.application {
int index = 0
//每一个进程都声明使用这个CommuStubService文件
customProcessNames.each {
//加上序号,$CommuStuService会替换成数字
String serviceName = "${STUB_SERVICE}" + index.toString()
service("${NAME}": serviceName,
"${ENABLED}": "${TRUE}",
"${EXPORTED}": "${FALSE}",
"${PROCESS}": it
)
if (matchedServices == null) {
matchedServices = new HashMap<>()
}
matchedServices.put(it, serviceName)
++index
}
复制代码
这里DipatcherService和DipatchProvider是binder的中转管理控件,默认配置到主进程。
//配置进程地址
this.dispatcher = project.extensions.getByType(DispatcherExtension)
//以后,写入DispatcherService和DispatcherProvider
def dispatcherProcess = dispatcher.process
println "dispatcher.process:" + dispatcher.process
if (dispatcherProcess != null && dispatcherProcess.length() > 0) {
service("${NAME}": DISPATCHER_SERVICE,
"${ENABLED}": "${TRUE}",
"${EXPORTED}": "${FALSE}",
"${PROCESS}": dispatcherProcess
)
provider(
"${AUTHORITIES}": getAuthority(),
"${EXPORTED}": "${FALSE}",
"${NAME}": DISPTACHER_PROVIDER,
"${ENABLED}": "${TRUE}",
"${PROCESS}": dispatcherProcess
)
} else {
service("${NAME}": DISPATCHER_SERVICE,
"${ENABLED}": "${TRUE}",
"${EXPORTED}": "${FALSE}"
)
provider(
"${AUTHORITIES}": getAuthority(),
"${EXPORTED}": "${FALSE}",
"${NAME}": DISPTACHER_PROVIDER,
"${ENABLED}": "${TRUE}"
)
}
复制代码
正如通讯所涉及的必要的几个步骤 1.注册 2.发其通讯 3.binder间的相互绑定 4.binder间传输数据
首先注册,经过公共的Andromeda入口注册提供远程沟通的服务
Andromeda.getInstance().registerRemoteService(IBuyApple.class, BuyAppleImpl.getInstance());
//RemoteTransfer
public static <T extends IBinder> void registerRemoteService(Class serviceClass, T stubBinder) {
if (null == serviceClass || null == stubBinder) {
return;
}
RemoteTransfer.getInstance().registerStubService(serviceClass.getCanonicalName(), stubBinder);
}
//RemoteServiceTransfer
public void registerStubServiceLocked(String serviceCanonicalName, IBinder stubBinder,
Context context, IDispatcher dispatcherProxy, IRemoteTransfer.Stub stub) {
stubBinderCache.put(serviceCanonicalName, stubBinder);
if (dispatcherProxy == null) {
BinderWrapper wrapper = new BinderWrapper(stub.asBinder());
Intent intent = new Intent(context, DispatcherService.class);
intent.setAction(Constants.DISPATCH_REGISTER_SERVICE_ACTION);
intent.putExtra(Constants.KEY_REMOTE_TRANSFER_WRAPPER, wrapper);
intent.putExtra(Constants.KEY_BUSINESS_BINDER_WRAPPER, new BinderWrapper(stubBinder));
intent.putExtra(Constants.KEY_SERVICE_NAME, serviceCanonicalName);
setProcessInfo(intent, context);
ServiceUtils.startServiceSafely(context, intent);
} else {
try {
dispatcherProxy.registerRemoteService(serviceCanonicalName,
ProcessUtils.getProcessName(context), stubBinder);
} catch (RemoteException ex) {
ex.printStackTrace();
}
}
}
复制代码
启动Service注册到DispatcherService当中
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
return super.onStartCommand(intent, flags, startId);
}
Logger.d("DispatcherService-->onStartCommand,action:" + intent.getAction());
if (Constants.DISPATCH_REGISTER_SERVICE_ACTION.equals(intent.getAction())) {
//注册远程服务
registerRemoteService(intent);
} else if (Constants.DISPATCH_UNREGISTER_SERVICE_ACTION.equals(intent.getAction())) {
//注销远程服务
unregisterRemoteService(intent);
} else if (Constants.DISPATCH_EVENT_ACTION.equals(intent.getAction())) {
//传递数据
publishEvent(intent);
}
return super.onStartCommand(intent, flags, startId);
}
private void registerRemoteService(Intent intent) {
BinderWrapper wrapper = intent.getParcelableExtra(Constants.KEY_REMOTE_TRANSFER_WRAPPER);
BinderWrapper businessWrapper = intent.getParcelableExtra(Constants.KEY_BUSINESS_BINDER_WRAPPER);
String serviceCanonicalName = intent.getStringExtra(Constants.KEY_SERVICE_NAME);
int pid = intent.getIntExtra(Constants.KEY_PID, -1);
String processName = intent.getStringExtra(Constants.KEY_PROCESS_NAME);
try {
if (TextUtils.isEmpty(serviceCanonicalName)) {
//注意:RemoteTransfer.sendRegisterInfo()时,serviceCanonicalName为null,这是正常的,此时主要目的是reigsterAndReverseRegister()
Logger.e("service canonical name is null");
} else {
//注册到分发器上管理
Dispatcher.getInstance().registerRemoteService(serviceCanonicalName,
processName, businessWrapper.getBinder());
}
} catch (RemoteException ex) {
ex.printStackTrace();
} finally {
if (wrapper != null) {
registerAndReverseRegister(pid, wrapper.getBinder());
}
}
}
复制代码
ServiceDipatcher负责管理服务信息
@Override
public void registerRemoteServiceLocked(final String serviceCanonicalName, String processName,
IBinder binder) throws RemoteException {
Log.d(TAG, "ServiceDispatcher-->registerStubServiceLocked,serviceCanonicalName:" + serviceCanonicalName + ",pid:" + android.os.Process.myPid() + ",thread:" + Thread.currentThread().getName());
if (binder != null) {
binder.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Logger.d("ServiceDispatcher-->binderDied,serviceCanonicalName:" + serviceCanonicalName);
BinderBean bean = remoteBinderCache.remove(serviceCanonicalName);
//实际上这里是还没实现线程同步,可是并不会影响执行结果,因此其实下面这句就没有同步的必要。
if (bean != null) {
emergencyHandler.handleBinderDied(Andromeda.getAppContext(), bean.getProcessName());
}
}
}, 0);
remoteBinderCache.put(serviceCanonicalName, new BinderBean(binder, processName));
Logger.d("ServiceDispatcher-->registerRemoteServiceLocked(),binder is not null");
} else {
Log.d(TAG, "ServiceDispatcher-->registerRemoteServiceLocked(),binder is null");
}
}
复制代码
最后须要完成反向绑定,意思是Dispatcher注册能够传输的binder对象,传输中心也须要绑定Dispatcher对象
/**
* 注册和反向注册
*
* @param pid
* @param transterBinder
*/
private void registerAndReverseRegister(int pid, IBinder transterBinder) {
Logger.d("DispatcherService-->registerAndReverseRegister,pid=" + pid + ",processName:" + ProcessUtils.getProcessName(pid));
IRemoteTransfer remoteTransfer = IRemoteTransfer.Stub.asInterface(transterBinder);
Dispatcher.getInstance().registerRemoteTransfer(pid, transterBinder);
if (remoteTransfer != null) {
Logger.d("now register to RemoteTransfer");
try {
remoteTransfer.registerDispatcher(Dispatcher.getInstance().asBinder());
} catch (RemoteException ex) {
ex.printStackTrace();
}
} else {
Logger.d("IdspatcherRegister IBinder is null");
}
}
复制代码
在调用远程的时候getRemoteSevice获取目标的binder对象
IBuyApple buyApple = IBuyApple.Stub.asInterface(Andromeda.with(this).getRemoteService(IBuyApple.class));
复制代码
远程管理RemoteManager
@Override
public IBinder getRemoteService(Class<?> serviceClass) {
if (null == serviceClass) {
return null;
}
return getRemoteService(serviceClass.getCanonicalName());
}
@Override
public synchronized IBinder getRemoteService(String serviceCanonicalName) {
Logger.d(this.toString() + "-->getRemoteService,serviceName:" + serviceCanonicalName);
if (TextUtils.isEmpty(serviceCanonicalName)) {
return null;
}
BinderBean binderBean = RemoteTransfer.getInstance().getRemoteServiceBean(serviceCanonicalName);
String commuStubServiceName = ConnectionManager.getInstance().bindAction(appContext, binderBean.getProcessName());
commuStubServiceNames.add(commuStubServiceName);
return binderBean.getBinder();
}
复制代码
RemoteDispatcher会调用DipatchProvider来获取远程的binder对象
@Override
public synchronized BinderBean getRemoteServiceBean(String serviceCanonicalName) {
Logger.d("RemoteTransfer-->getRemoteServiceBean,pid=" + android.os.Process.myPid() + ",thread:" + Thread.currentThread().getName());
//获取binder包装的对象
BinderBean cacheBinderBean = serviceTransfer.getIBinderFromCache(context, serviceCanonicalName);
if (cacheBinderBean != null) {
return cacheBinderBean;
}
if (null == dispatcherProxy) {
IBinder dispatcherBinder = getIBinderFromProvider();
if (null != dispatcherBinder) {
Logger.d("the binder from provider is not null");
dispatcherProxy = IDispatcher.Stub.asInterface(dispatcherBinder);
registerCurrentTransfer();
}
}
if (null == dispatcherProxy) {
sendRegisterInfo();
try {
wait(MAX_WAIT_TIME);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
if (serviceTransfer == null || dispatcherProxy == null) {
return null;
}
return serviceTransfer.getAndSaveIBinder(serviceCanonicalName, dispatcherProxy);
}
private IBinder getIBinderFromProvider() {
Logger.d("RemoteTransfer-->getIBinderFromProvider()");
Cursor cursor = null;
try {
//查询出cursor对象
cursor = context.getContentResolver().query(getDispatcherProviderUri(), DispatcherProvider.PROJECTION_MAIN,
null, null, null);
if (cursor == null) {
return null;
}
//使用DispatcherCursor解包
return DispatcherCursor.stripBinder(cursor);
} finally {
IOUtils.closeQuietly(cursor);
}
}
复制代码
DispatcherProvider使用的查询返回
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Logger.d("DispatcherProvider-->query,uri:" + uri.getAuthority());
//DispatcherCursor封装binder
return DispatcherCursor.generateCursor(Dispatcher.getInstance().asBinder());
}
//经过
public static DispatcherCursor generateCursor(IBinder binder) {
try {
DispatcherCursor cursor;
cursor = cursorCache.get(binder.getInterfaceDescriptor());
if (cursor != null) {
return cursor;
}
cursor = new DispatcherCursor(DEFAULT_COLUMNS, binder);
cursorCache.put(binder.getInterfaceDescriptor(), cursor);
return cursor;
} catch (RemoteException ex) {
return null;
}
}
//经过BinderWrapper来封装binder
public DispatcherCursor(String[] columnNames, IBinder binder) {
super(columnNames);
binderExtras.putParcelable(KEY_BINDER_WRAPPER, new BinderWrapper(binder));
}
复制代码
@Override
public synchronized IBinder getRemoteService(String serviceCanonicalName) {
Logger.d(this.toString() + "-->getRemoteService,serviceName:" + serviceCanonicalName);
if (TextUtils.isEmpty(serviceCanonicalName)) {
return null;
}
//获取binder信息
BinderBean binderBean = RemoteTransfer.getInstance().getRemoteServiceBean(serviceCanonicalName);
//在binder绑定启动的进程service
String commuStubServiceName = ConnectionManager.getInstance().bindAction(appContext, binderBean.getProcessName());
commuStubServiceNames.add(commuStubServiceName);
return binderBean.getBinder();
}
复制代码
一开始介绍插入了CommuStubService对象,这里经过StubServiceMatcher经过进程名来找到启动的进程的service,而后将binder和service绑定到一块儿
//这里不能按照serviceCanonicalName来区分,而是要按照target service来划分,若是targetService同样,那就不必再绑定
public synchronized String bindAction(Context context, String serverProcessName) {
Logger.d("ConnectionManager-->bindAction,serverProcessName:" + serverProcessName);
//匹配对应的binder对应的Service(CommuStubService$0)
Intent intent = StubServiceMatcher.matchIntent(context, serverProcessName);
if (null == intent) {
Logger.d("match intent is null");
return null;
}
String commuStubServiceName = getCommuStubServiceName(intent);
ConnectionBean bean = connectionCache.get(commuStubServiceName);
if (null == bean) {
//服务链接
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Logger.d("onServiceConnected,name:" + name.getShortClassName());
}
@Override
public void onServiceDisconnected(ComponentName name) {
Logger.d("onServiceDisconnected,name:" + name.getShortClassName());
}
};
bean = new ConnectionBean(connection);
connectionCache.put(commuStubServiceName, bean);
Logger.d("really start to bind");
//启动服务
context.bindService(intent, connection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
} else {
bean.increaseRef();
}
return commuStubServiceName;
}
复制代码
1.经过gradle插件来动态添加配置的四大组件资料
2.经过分发DispatchService服务来管理binder对象
3.经过Parcelable序列化传输binder
4.活用IBinder.Stub对象