package com.tws.plugin.servicemanager;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Process;
import com.tws.plugin.servicemanager.compat.BundleCompat;
import com.tws.plugin.servicemanager.compat.ContentProviderCompat;
import com.tws.plugin.servicemanager.local.ServicePool;
/**
* @author yongchen
*/
public class ServiceManager {
public static final String ACTION_SERVICE_DIE_OR_CLEAR = "com.limpoxe.support.action.SERVICE_DIE_OR_CLEAR";
public static Application sApplication;
public static void init(Application application) {
sApplication = application;
Bundle argsBundle = new Bundle();
int pid = Process.myPid();
argsBundle.putInt(ServiceProvider.PID, pid);
//为每个进程发布一个binder
BundleCompat.putBinder(argsBundle, ServiceProvider.BINDER, new ProcessBinder(ProcessBinder.class.getName() + "_" + pid));
ContentProviderCompat.call(ServiceProvider.buildUri(),
ServiceProvider.REPORT_BINDER, null, argsBundle);
ServiceManager.sApplication.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//服务进程挂掉以后 或者服务进程主动通知清理时,移除客户端的代理缓存
ServicePool.unRegister(intent.getStringExtra(ServiceProvider.NAME));
}
}, new IntentFilter(ACTION_SERVICE_DIE_OR_CLEAR));
}
public static Object getService(String name) {
return getService(name, ServiceManager.class.getClassLoader());
}
/**
*
* @param name
* @param interfaceClassloader
* @return
*/
public static Object getService(String name, ClassLoader interfaceClassloader) {
//首先在当前进程内查询
Object service = ServicePool.getService(name);
if (service == null) {
//向远端器查询
Bundle bundle = ContentProviderCompat.call(ServiceProvider.buildUri(),
ServiceProvider.QUERY_INTERFACE, name, null);
if (bundle != null) {
String interfaceClassName = bundle.getString(ServiceProvider.QUERY_INTERFACE_RESULT);
if (interfaceClassName != null) {
service = RemoteProxy.getProxyService(name, interfaceClassName, interfaceClassloader);
//缓存Proxy到本地
if (service != null) {
ServicePool.registerInstance(name, service);
}
}
}
}
return service;
}
/**
* 给当前进程发布一个服务, 发布后其他进程可使用此服务
*/
public static void publishService(String name, String className) {
publishService(name, className, ServiceManager.class.getClassLoader());
}
/**
* 给当前进程发布一个服务, 发布后其他进程可使用此服务
*/
public static void publishService(String name, final String className, final ClassLoader classloader) {
publishService(name, new ServicePool.ClassProvider() {
@Override
public Object getServiceInstance() {
try {
return classloader.loadClass(className).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public String getInterfaceName() {
try {
return classloader.loadClass(className).getInterfaces()[0].getName();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
});
}
/**
* 给当前进程发布一个服务, 发布后其他进程可使用此服务
*/
public static void publishService(String name, final ServicePool.ClassProvider provider) {
//先缓存到本地
ServicePool.registerClass(name, provider);
int pid = Process.myPid();
Bundle argsBundle = new Bundle();
argsBundle.putInt(ServiceProvider.PID, pid);
//classLoader
String serviceInterfaceClassName = provider.getInterfaceName();
argsBundle.putString(ServiceProvider.INTERFACE, serviceInterfaceClassName);
//再发布到远端
ContentProviderCompat.call(ServiceProvider.buildUri(),
ServiceProvider.PUBLISH_SERVICE, name, argsBundle);
}
/**
* 清理当前进程发布的所有服务
*/
public static void unPublishAllService() {
int pid = Process.myPid();
Bundle argsBundle = new Bundle();
argsBundle.putInt(ServiceProvider.PID, pid);
ContentProviderCompat.call(ServiceProvider.buildUri(),
ServiceProvider.UNPUBLISH_SERVICE, null, argsBundle);
}
public static void unPublishService(String name) {
int pid = Process.myPid();
Bundle argsBundle = new Bundle();
argsBundle.putInt(ServiceProvider.PID, pid);
argsBundle.putString(ServiceProvider.NAME, name);
ContentProviderCompat.call(ServiceProvider.buildUri(),
ServiceProvider.UNPUBLISH_SERVICE, null, argsBundle);
}
}