Android LOCAL_JAVA_RESOURCE_FILES 的妙用
来源:互联网 发布:倩女幽魂联赛对战算法 编辑:程序博客网 时间:2024/05/16 01:27
简介
在研究Android系统开机流程的时候,看到preloaded-classes被用来做预加载类的载体,但没明白它是怎么编译到系统中的。因此,特意去研究了下,特此记录下来。
将preloaded-classes编译到framework.jar中
frameworks/base/Android.mk
include $(CLEAR_VARS)LOCAL_MODULE := frameworkLOCAL_MODULE_CLASS := JAVA_LIBRARIESLOCAL_NO_STANDARD_LIBRARIES := trueLOCAL_STATIC_JAVA_LIBRARIES := framework-baseLOCAL_DX_FLAGS := --core-library# Packages to include, use \* wildcard to include descendants.LOCAL_JAR_PACKAGES := android\*# List of classes and interfaces which should be loaded by the Zygote.LOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/preloaded-classesinclude $(BUILD_JAVA_LIBRARY)
LOCAL_JAVA_RESOURCE_FILES
将文件编译到对应的jar文件中。例如上面的preloaded-classes就会被编译到framework.jar中。如图:
out/target/product/xxx/system/framework/framework.jar
读取framework.jar中preloaded-classes的内容
那我们要怎么调用这个jar包中的文件呢?系统framework中给出了调用方法,代码如下:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static final String PRELOADED_CLASSES = "preloaded-classes";private static void preloadClasses() { InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream( PRELOADED_CLASSES); if (is == null) { Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); } else { ... try { BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); int count = 0; String line; while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } ... } } catch (IOException e) { Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); } finally { IoUtils.closeQuietly(is); ... } } }
通过上面的代码我们知道,主要的读取的代码是这段
ClassLoader.getSystemClassLoader().getResourceAsStream(PRELOADED_CLASSES);
通过这段代码,我们可以获取到preloaded-classes的输入流,这样我们就可以读取其中的内容了。那问题来了,ClassLoader有什么怎么去读取的呢?这个放到下一篇文章来讲解,这里暂不讲解,只讲它的实现和调用。下面我们来看下怎么添加自己的文件到jar包,并去读取其内容呢,其实通过上面的分析,我们要添加自定义文件到framework.jar中也是非常简单的了。
添加自定义资源文件到framework.jar中
第一步 修改Android.mk
我们要添加自定义资源文件到jar中,我们只需要在mk文件,将LOCAL_JAVA_RESOURCE_FILES
添加上我们的文件名即可,当然路径要一致。
frameworks/base/Android.mk
include $(CLEAR_VARS)LOCAL_MODULE := framework...# List of classes and interfaces which should be loaded by the Zygote.LOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/preloaded-classesLOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/test.txtLOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/image.jpginclude $(BUILD_JAVA_LIBRARY)
上面我们通过LOCAL_JAVA_RESOURCE_FILES
将test.txt和image.jpg添加到了framework.jar中。我们先看test.txt和image.jpg的内容。
frameworks/base/test.txt
“你知道吗,总有一天,你终将会变成你讨厌的人。”“谢谢吉言,我讨厌有钱人。”
frameworks/base/image.jpg
第二步 编译framework.jar
在framework/base目录直接执行mm命令即可。
第三步 检查生成的framework.jar是否编译成功
打开out/target/product/xxx/system/framework/framework.jar,结果如图:
第四步 测试结果
先上测试结果,如下:
完美!!!
实现代码
TestActivity.java
@Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.test_layout); TextView mTV = (TextView) findViewById(R.id.id_tv); ImageView mIV = (ImageView) findViewById(R.id.id_iv); String text = ""; InputStream isText = ClassLoader.getSystemResourceAsStream("test.txt"); if (isText != null) { BufferedReader br = new BufferedReader(new InputStreamReader(isText)); String line; try { while ((line = br.readLine()) != null) { Log.d("TAG", "line:"+line); text += line + "\n"; } } catch (IOException e) { e.printStackTrace(); } finally { try { isText.close(); isText = null; } catch (IOException e) { e.printStackTrace(); } } mTV.setText(text); } InputStream isImage = ClassLoader.getSystemResourceAsStream("image.jpg"); if (isImage != null) { Bitmap bitmap = BitmapFactory.decodeStream(isImage); if (bitmap != null) { mIV.setImageBitmap(bitmap); } try { isImage.close(); isImage = null; } catch (IOException e) { e.printStackTrace(); } } }
test_layout.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/id_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium"/> <ImageView android:id="@+id/id_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /></LinearLayout>
注:我这里使用的是ClassLoader.getSystemResourceAsStream,其实跟ClassLoader.getSystemClassLoader().getResourceAsStream是一样的,只不过系统已经将封装好了。看下代码你就明白了。
public static InputStream getSystemResourceAsStream(String resName) { return SystemClassLoader.loader.getResourceAsStream(resName);}public static ClassLoader getSystemClassLoader() { return SystemClassLoader.loader;}
所以它们调用的是同一个方法。有源码的同学可以实际操作一把,理解就深刻了。争取下一篇文章写一下ClassLoader getSystemResourceAsStream的调用流程。
总结
Read The Fucking Source Code
- Android LOCAL_JAVA_RESOURCE_FILES 的妙用
- android image level的妙用
- Android BuildConfig.DEBUG的妙用
- Android view.setTag的妙用。
- Android BuildConfig.DEBUG的妙用
- android BuildConfig Debug的妙用
- Android Gradle BuildConfig的妙用
- Android Gradle manifestPlaceholders 的妙用
- android BuildConfig.DEBUG的妙用
- Android BuildConfig.DEBUG的妙用
- ANDROID BUILDCONFIG.DEBUG的妙用
- Android学习之Service命令的妙用
- Android学习之Service命令的妙用
- android系统中sendevent的妙用
- android系统中sendevent的妙用
- Android中Is library配置的妙用
- Android UI 之TextView的妙用
- Android UI 之CheckBox的妙用
- 又到年底了,你的拖延症治愈了吗
- CODEVS 1023 C++ 青铜
- js设置li高度与前面内容同高
- 好好学习技术
- Java String 面试题以及答案
- Android LOCAL_JAVA_RESOURCE_FILES 的妙用
- 惨!美团程序员的年终奖金可能没了
- Android 混淆:proguard实践
- python3 文件复制、延迟文件复制任务
- 2017年朋友圈最爆笑新闻,哈哈哈哈哈哈哈哈哈
- 来仿一仿retrofit
- Selenium+Python进行web自动化测试(Demo+API)
- 从一个普通程序猿到CTO,要经历哪几个阶段?
- 好好学些技术啊啊啊啊啊啊