我们要做一个Launcher,Launcher上面要显示apk的界面,但是的话,如果使用widget的方式没法进行复杂的交互,所以要想办法把第三方的apk里的View,动态地加载进来。
怎么实现呢?
Android原生的Launcher其实也是个框架,去遍历孩子,然后显示出来。这里也一样,定好相关的接口,然后各自己的应用需要去实现,再根据条件去遍历/system/app下的应用,然后加载相关的View出来。当对应的View绑定到窗口以后,就去绑定对应的服务,由服务来对这个View进行数据交互。这样子的互动,会比较好一点。
如果说是音乐这些还比较简单,要是地图的控制就比较复杂了。用Widget实现不了。如果能用绘制的View那就么是比较好实现的。
这里是Demo,也就是前期的技术预言,所以不需要做一个完整的项目。
要点:能够加载到第三方apk里面的View,并且显示出来,同时可以操作,进行数据交互。
- 有宿主,和第三方APK
- 第三方apk已经安装,所在目录是/system/app/
- 能够进行数据交互,除了简单的点击以外,还可以进行复杂的操作。
还是先看效果吧:
就是实现上效果,可是,这个项目只有一个类,那就是MainActivity.
而且可以进行操作哦,可以点击下一首,上一首,播放!
那是怎么做到的呢?
创建一个宿主项目,对应的也是我们以后的Launcer,我们暂且起名为PretendLauncherDemo
我们加载一个界面需要上下文吧,所以就有了:
//获取TestB的Context
private Context getRemoteContext(String packageName) throws PackageManager.NameNotFoundException {
return createPackageContext(packageName,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
}
这个方法就是通过包名获取到对应app的上下文对象。
但是要注意的时,通过这个上下文获取到的ApplicationContext是空的呢?也就是说,部分的图片加载工具,比如说ImageLoader,比如说毕加索这些可能拿不到图片,直接崩溃掉,因为context.getApplicationContext拿不到,返回的内容为null。
有了上下文以后,做什么事情都好说,如果只是获取资源文件,这是非常简单的事情:
/**
* 获取资源对应的编号
*
* @param res
* @param resName
* @param resType layout、drawable、string
* @return
*/
private int getId(Resources res, String resType, String resName, String packageName) {
return res.getIdentifier(resName, resType, packageName);
}
有了id,你啥不能拿到呢对吧!
获取View
/**
* 获取View
*
* @param context
* @param resId
* @return
*/
public View getView(Context context, int resId) {
return ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(resId, null);
}
获取颜色值:
/**
* 获取颜色
*
* @param context
* @param colorId
* @return 颜色值
*/
public int getColor(Context context, int colorId) {
return context.getResources().getColor(colorId);
}
其他的获取方式都是一样的。
给大家一个思路:如果遇到问题,就一个一个地去解决即可!哈哈哈!!!!
欢迎关注微信公众号