占位式插件化二Service的启动

系列文章

占位式插件化一Activity的跳转
占位式插件化二Service的启动
占位式插件化三BroadcastReceive的注册与接收
占位式插件化四静态BroadcastReceiver的注册

占位式插件化的本质,就是用代理Activity或者Service使用插件app中的资源或者方法,从而达到执行插件APP的目的。

仿照Activity的跳转,可以知道启动插件APP中的Service,需要新增以下几个类,ServiceInterface做协议支持,BaseService实现ServiceInterface接口,ProxyService在宿主APP中占位,通过ProxyService即可启动插件APP中的Service,与其说启动了插件APP中的Service,不如说调用了插件APP中Service的方法。这时候插件APP中的Service也就只是一个普通的类,而不是安卓的四大组件之一的Service。

接口协议

public interface ServiceInterface {
    void insertAppService(Service appService);

    int onStartCommand(Intent intent, int flags, int startId);

    void onCreate();
}

插件APP的BaseService

public class BaseService implements ServiceInterface {
    protected Service appService;

    @Override
    public void insertAppService(Service appService) {
        this.appService = appService;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return 0;
    }

    @Override
    public void onCreate() {

    }
}

通过insertAppService这个方法,将宿主APP的Service注入,从而能够使用这个对象执行功能。

插件APP的TestService

public class TestService extends BaseService {
    private static final String TAG = TestService.class.getSimpleName();

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(2000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        Log.i(TAG, "插件中的Service正在执行.....");
                    }

                }
            }
        }).start();

        return super.onStartCommand(intent, flags, startId);
    }
}

TestService中写了一个死循环打印log,如果启动了这个Service之后能打印出Log,即启动插件Service成功。

宿主APP的ProxyService

public class ProxyService extends Service {
    public ProxyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String className = intent.getStringExtra("className");

        try {
            Class<?> clazz = PluginManager.getInstance().getDexClassLoder().loadClass(className);
            Object o = clazz.newInstance();
            ServiceInterface serviceInterface = (ServiceInterface) o;
            // 注入
            serviceInterface.insertAppService(this);

            Bundle bundle = new Bundle();
            bundle.putString("appName", "我是宿主传递过来的信息");

            // 执行插件里面的onStartCommand方法
            serviceInterface.onStartCommand(intent, flags, startId);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.onStartCommand(intent, flags, startId);
    }
}

使用插件APP的类加载器加载指定的Service.class,然后构造其对象,转换成标准ServiceInterface 对象之后,就可以调用注入方法,将本Service注入到插件APP中。 然后调用onStartCommand方法,执行插件APP的onStartCommand方法。

插件APP中启动插件APP的Service

在上篇文章中提到的PluginActivity增加按钮,并且增加点击事件

 findViewById(R.id.btn_service).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(appActivity, TestService.class);
                startService(intent);
            }
        });

代码要调用宿主APP的startService方法

public void startService(Intent intent) {
        Intent proxyIntent = new Intent();
        proxyIntent.putExtra("className", intent.getComponent().getClassName());
        appActivity.startService(proxyIntent);
    }

并且将要启动的Service的全限定名传过去,这样可以通过反射构造其对象。

@Override
    public ComponentName startService(Intent service) {
        String className = service.getStringExtra("className");
        Intent proxyIntent = new Intent(this, ProxyService.class);
        proxyIntent.putExtra("className", className);
        return super.startService(proxyIntent);
    }

宿主APP的ProxyActivity重写startService方法,将启动宿主APP的ProxyService,并且将启动的插件APP的Service的全限定名传入。最后由ProxyService执行插件APP中Service的方法。完成再插件APP中启动插件Service。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值