Platform: Hi3751V350
OS: Android 9.0
Kernel: v4.9.127_s5
需求:
客户要求系统添加某个指定的TTF文件作为系统默认的字库;
源码文件:
frameworks\base\graphics\java\android\graphics\Typeface.java
frameworks\base\data\fonts\fonts.mk
frameworks\base\data\fonts\Android.mk
frameworks\base\data\fonts\fonts.xml
实现:
Typeface 这个类会在 Android 应用程序启动的过程中,通过反射的方式被加载;打开Typeface.java,可以看到里面有一个static代码块;
static {
final ArrayMap<String, Typeface> systemFontMap = new ArrayMap<>();
final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", systemFontMap,
systemFallbackMap);
sSystemFontMap = Collections.unmodifiableMap(systemFontMap);
sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
setDefault(sSystemFontMap.get(DEFAULT_FAMILY));
// Set up defaults and typefaces exposed in public API
DEFAULT = create((String) null, 0);
DEFAULT_BOLD = create((String) null, Typeface.BOLD);
SANS_SERIF = create("sans-serif", 0);
SERIF = create("serif", 0);
MONOSPACE = create("monospace", 0);
sDefaults = new Typeface[] {
DEFAULT,
DEFAULT_BOLD,
create((String) null, Typeface.ITALIC),
create((String) null, Typeface.BOLD_ITALIC),
};
}
关键代码:
setDefault(sSystemFontMap.get(DEFAULT_FAMILY));
private static final String DEFAULT_FAMILY = "sans-serif";
继续看fonts.xml
<!-- first font is default -->
<family name="sans-serif">
<font weight="100" style="normal">Roboto-Thin.ttf</font>
<font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
<font weight="300" style="normal">Roboto-Light.ttf</font>
<font weight="300" style="italic">Roboto-LightItalic.ttf</font>
<font weight="400" style="normal">Roboto-Regular.ttf</font>
<font weight="400" style="italic">Roboto-Italic.ttf</font>
<font weight="500" style="normal">Roboto-Medium.ttf</font>
<font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
<font weight="900" style="normal">Roboto-Black.ttf</font>
<font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
<font weight="700" style="normal">Roboto-Bold.ttf</font>
<font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
</family>
weight 表示字重,也就是字体粗细的程度;
style表示字体风格,一般来说是常规的和斜体的两种;
在不考虑weight和style可按照如下更改:
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -22,18 +22,7 @@
<familyset version="23">
<!-- first font is default -->
<family name="sans-serif">
- <font weight="100" style="normal">Roboto-Thin.ttf</font>
- <font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
- <font weight="300" style="normal">Roboto-Light.ttf</font>
- <font weight="300" style="italic">Roboto-LightItalic.ttf</font>
- <font weight="400" style="normal">Roboto-Regular.ttf</font>
- <font weight="400" style="italic">Roboto-Italic.ttf</font>
- <font weight="500" style="normal">Roboto-Medium.ttf</font>
- <font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
- <font weight="900" style="normal">Roboto-Black.ttf</font>
- <font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
- <font weight="700" style="normal">Roboto-Bold.ttf</font>
- <font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
+ <font weight="400" style="normal">Fonts.ttf</font>
</family>
<!-- Note that aliases must come after the fonts they reference. -->
只需要把fonts放置到system/fonts/即可,在不考虑版本管理的情况下,可按照如下更改:
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
old mode 100644
new mode 100755
index 76eb4e67..6be1723d
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -74,7 +74,8 @@ $(eval include $(BUILD_PREBUILT))
endef
font_src_files := \
- AndroidClock.ttf
+ AndroidClock.ttf \
+ Fonts.ttf
$(foreach f, $(font_src_files), $(call build-one-font-module, $(f)))
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
old mode 100644
new mode 100755
index e884f2fe..c48f848b
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -17,4 +17,5 @@
PRODUCT_PACKAGES := \
DroidSansMono.ttf \
AndroidClock.ttf \
+ Fonts.ttf \
fonts.xml
调试:
把fonts.ttf 复制到system/fonts/目录下,并修改fonts.xml;
cp /mnt/media_rw/sda1/1.ttf system/fonts/Fonts.ttf
busybox vi system/etc/fonts.xml
重启之后无法启动系统,日志如下:
12-31 18:00:35.799 E/Typeface( 2108): Error mapping font file /system/fonts/Fonts.ttf
12-31 18:00:35.800 E/Typeface( 2108): Unable to load Family: sans-serif : null
12-31 18:00:35.925 E/Typeface( 2108): Unable to load Family: sans-serif : nul
相关的代码如下:
private static @Nullable ByteBuffer mmap(String fullPath) {
try (FileInputStream file = new FileInputStream(fullPath)) {
final FileChannel fileChannel = file.getChannel();
final long fontSize = fileChannel.size();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
} catch (IOException e) {
Log.e(TAG, "Error mapping font file " + fullPath);
return null;
}
}
看下是否是权限有差异:
-rw-r--r-- 1 root root 108128 2008-12-31 10:00 DroidSansMono.ttf
-rwx------ 1 root root 2678868 1969-12-31 18:08 Fonts.ttf
-rw-r--r-- 代表0644,手动给予权限再重启即可;
chmod 0644 Fonts.ttf
其他:
Linux的文件基本上分为三个属性:可读(r=4),可写(w=2),可执行(x=1);