前言
Android动态加载(下)——加载已安装APK中的类和资源。
Android中文Wiki:http://wikidroid.sinaapp.com
正文
一、目标
注意被调用的APK在Android系统中是已经安装的。
上篇文章:Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类
从当前APK中调用另外一个已安装APK的字符串、颜色值、图片、布局文件资源以及Activity。
二、实现
2.1 被调用工程
基本沿用上个工程的,添加了被调用的字符串、图片等,所以这里就不贴了,后面有下载工程的链接。
2.2 调用工程代码
/** TestB包名 */
private static final String PACKAGE_TEST_B = "com.nmbb.b";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final Context ctxTestB = getTestBContext();
Resources res = ctxTestB.getResources();
// 获取字符串string
String hello = res.getString(getId(res, "string", "hello"));
((TextView) findViewById(R.id.testb_string)).setText(hello);
// 获取图片Drawable
Drawable drawable = res
.getDrawable(getId(res, "drawable", "testb"));
((ImageView) findViewById(R.id.testb_drawable))
.setImageDrawable(drawable);
// 获取颜色值
int color = res.getColor(getId(res, "color", "white"));
((TextView) findViewById(R.id.testb_color))
.setBackgroundColor(color);
// 获取布局文件
View view = getView(ctxTestB, getId(res, "layout", "main"));
LinearLayout layout = (LinearLayout) findViewById(R.id.testb_layout);
layout.addView(view);
// 启动TestB Activity
findViewById(R.id.testb_activity).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
try {
@SuppressWarnings("rawtypes")
Class cls = ctxTestB.getClassLoader()
.loadClass("com.nmbb.TestBActivity");
startActivity(new Intent(ctxTestB, cls));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取资源对应的编号
*
* @param testb
* @param resName
* @param resType
* layout、drawable、string
* @return
*/
private int getId(Resources testb, String resType, String resName) {
return testb.getIdentifier(resName, resType, PACKAGE_TEST_B);
}
/**
* 获取视图
*
* @param ctx
* @param id
* @return
*/
public View getView(Context ctx, int id) {
return ((LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,
null);
}
/**
* 获取TestB的Context
*
* @return
* @throws NameNotFoundException
*/
private Context getTestBContext() throws NameNotFoundException {
return createPackageContext(PACKAGE_TEST_B,
Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
}
代码说明:
基本原理:通过package获取被调用应用的Context,通过Context获取相应的资源、类。
注意:
a). 网上许多文章是通过当前工程的R.id来调用被调用工程的资源 ,这是错误的,即使不报错那也是凑巧,因为R是自动生成的,两个应用的id是没有办法对应的,所以需要通过getIdentifier来查找。
b). Context.CONTEXT_INCLUDE_CODE一般情况下是不需要加的,如果layout里面包含了自定义控件,就需要加上。注意不能在当前工程强制转换获得这个自定义控件,因为这是在两个ClassLoader中,无法转换。
c). 获取这些资源是不需要shareUserId的。
三、总结
与上篇文章相比,获取资源更加方便,但也存在一些限制:
3.1 被调用的apk必须已经安装,降低用户体验。
3.2 style是无法动态设置的,即使能够取到。
3.3 从目前研究结果来看,被调用工程如果使用自定义控件,会受到比较大的限制,不能强制转换使用(原因前面已经讲过)。
3.4 由于一个工程里面混入了两个Context,比较容易造成混淆,取资源也比较麻烦。这里分享一下批量隐射两个apk id的办法,可以通过反射获取两个apk的R类,一次获取每一个id和值,通过名称一一匹配上,这样就不用手工传入字符串了。
private static HashMap<String, Integer> getR(Class cls) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
HashMap<String, Integer> result = new HashMap<String, Integer>();
for (Class r : cls.getClasses()) {
if (!r.getName().endsWith("styleable")) {
Object owner = r.newInstance();
for (Field field : r.getFields()) {
result.put(field.getName(), field.getInt(owner));
}
}
}
return result;
}
四、下载
五、文章
结束
如果是做大面积的换肤,还比较复杂,这种方式也不是很方便,这也是为什么现在市面上做换肤的很少,有也是很简单的换肤。这几天想到的另外一个方案,还没有实践,有效果了再拿出来分享,欢迎大家交流 :)
相关推荐
本文将深入探讨如何在已安装的APK中加载类和资源,这在提高用户体验和减少版本迭代成本方面具有重要意义。 动态加载的核心在于对Android系统的ClassLoader的扩展和理解。Android系统默认使用DexClassLoader来加载...
在本资源包中,我们探讨的是使用C#语言和Mono for Android框架开发Android应用程序的方法。 Mono for Android是Xamarin公司(现已被微软收购)推出的一个工具,它允许开发者利用.NET Framework和C#来构建原生的...
总的来说,实现皮肤打包成APK在Android开发中是一项实用技术,它能够提高用户体验,同时降低应用更新带来的负担。通过理解上述步骤,开发者可以为自己的应用添加个性化的皮肤功能,提升产品的吸引力。
综上所述,"安卓Android源码——更换软件主题(apk方式).rar"这个压缩包很可能是提供了一个实际的项目实例,用于教学如何在Android应用中实现主题更换。通过对源码的分析和学习,开发者可以掌握这一功能的实现原理...
通过动态加载APK中的资源,应用可以在不重启的情况下实现界面皮肤的实时切换,提供更好的用户体验。 总结起来,这个源码demo涵盖了Android应用皮肤打包的核心技术,包括APK结构的理解、资源管理、构建流程的掌握...
完成动态壁纸的开发后,将其打包成APK,用户可以通过安装APK将动态壁纸添加到系统中。在设置界面,用户可以选择已安装的动态壁纸作为当前桌面背景。 六、进一步学习 开发动态壁纸涉及到OpenGL ES、动画框架、多...
【Android课程设计——背单词软件】是一个典型的移动应用开发项目,展示了如何利用Android Studio这一强大的集成开发环境(IDE)来创建一个实用的教育类应用程序。这个项目的核心目标是帮助用户学习和记忆单词,可能...
【Android应用开发新路线——用HTML5开发Android应用】 在当今快速发展的移动应用领域,开发者们正在寻找更高效、更具跨平台能力的开发方式。HTML5作为一种强大的网页开发语言,正逐渐被引入到Android应用开发中,...
用户安装这些主题apk后,应用可以通过读取已安装的主题apk来动态加载相应的资源。 6. **主题管理**:为了让用户方便地选择和切换主题,可以开发一个主题管理界面,展示可用主题,并提供选择和切换的功能。这需要...
这个项目提供了实现无限滚动、软缓存和懒加载的实际示例,对于学习Android应用开发,特别是数据加载和性能优化方面,是非常有价值的参考。开发者可以通过分析这些源代码,理解如何在实际项目中应用这些技术。
在本资源中,我们拥有一个名为"安卓Android源码——完美版的拼图游戏APK和工程源码.zip"的压缩包,它包含了构建一个功能完整的Android拼图游戏所需的所有内容。这个项目对于想要深入理解Android应用开发,尤其是游戏...
在Android平台上,插件化技术是一种先进的开发策略,它允许应用程序在运行时动态加载和卸载功能模块,而无需用户重新安装整个应用。这个过程通常涉及到动态加载、进程通信、资源管理和安全控制等多个方面。本篇文章...
这个压缩包文件"安卓Android源码——douBanList(滚动到底部加载新的,软缓存,懒加载).7z"显然包含了开发一个特定安卓应用的源代码,特别是涉及到豆瓣(douban)列表的展示,具备下拉刷新和上拉加载更多功能,以及...
【标题】"安卓开发框架工具类相关-Android快速开发系列10个常用工具类.rar" 涉及的是Android应用程序开发中的一个关键方面——工具类的集合。在Android开发中,工具类通常包含一系列静态方法,用于执行常见的、重复...
【摘要】中提到的面向动态加载的Android恶意行为动静态检测方法,主要针对的是Android平台上的一种新型执行体分类的运行时加载机制——动态加载。动态加载允许程序在运行时加载和执行新的代码,增强了应用程序的灵活...
这个压缩包文件"安卓Android源码——FBReader修改epub快速加载.zip"显然包含了FBReader源代码的修改版,专门针对EPUB格式电子书的快速加载进行了优化。下面我们将深入探讨这个主题,了解相关知识点。 1. **EPUB格式...
本资源"安卓Android源码——几行代码实现动态图片.rar"提供了一个简单的解决方案,通过几行代码就能在Android应用中轻松实现动态GIF的展示。 首先,我们需要了解在Android中如何加载和显示GIF。Android原生SDK并不...
在深入解析这个"Android源码——笑话故事android应用源码.zip"之前,我们需要了解Android应用的基本结构和开发流程。Android应用主要由Java或Kotlin语言编写,通常包括Activity、Service、BroadcastReceiver、...