代码实现:
1.添加字体资源文件到fonts中
frameworks/base/data/fonts/
例如:Ndot-55.otf
2.修改fonts.xml文件
frameworks/base/data/fonts/fonts.xml
例如:
Ndot-55.ttf
3.修改编译文件,把字体资源文件编译进系统
frameworks/base/data/fonts/Android.mk
追加字体资源文件
例如:
PRODUCT_PACKAGES := \
Ndot-55.otf
如果是dp文件
frameworks/base/data/fonts/Android.dp
prebuilt_font {
name: "Ndot-55.otf",
src: "Ndot-55.otf",
}
4.新增根据prop值动态修改Typeface.java
frameworks/base/graphics/java/android/graphics/Typeface.java
在create方法中去读取prop,如果有值则替换返回的familyName
5.编译刷机
然后通过adb命令更改
机器需要先 adb root && adb remoun
1.adb push Ndot-55.ttf /system/fonts
2.修改fonts.xml文件
在文件中添加
Ndot-55.ttf
adb pull /system/etc/fonts.xml
adb push fonts.xml /system/etc/
3.修改prop值,如果无效试着重启机器
adb shell setprop persist.sys.cus_font ndot-55
adb reboot
参考
不重启使得字体生效
/frameworks/base/core/java/android/graphics/fonts/FontManager.java
需要权限
<uses-permission android:name="android.permission.UPDATE_FONTS"/>
1)getFontConfig()
mIFontManager.getFontConfig();
2)updateFontFamily()
mIFontManager.updateFontFamily()
/frameworks/base/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
interface IFontManager {
@EnforcePermission("UPDATE_FONTS")
FontConfig getFontConfig();
int updateFontFamily(in List<FontUpdateRequest> request, int baseVersion);
}
/frameworks/base/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java /frameworks/base/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
FontManagerService extends IFontManager.Stub
private static final String FONT_FILES_DIR = "/data/fonts/files";
private static final String CONFIG_XML_FILE = "/data/fonts/config/config.xml";
方法initialize() mUpdatableFontDir.loadFontFileMap();
addFileToMapIfSameOrNewer(); putFontFileInfo(fontFileInfo); mFontFileInfoMap.put(info.getPostScriptName(), info);
方法updateFontFamily()
1)update(List<FontUpdateRequest> requests)
mUpdatableFontDir.update(requests);
-->
backupMap = new ArrayMap<>(mFontFileInfoMap);
curConfig = readPersistentConfig(); //该方法是读取config中的参数
familyMap = new HashMap<>(); 遍历curConfig和requests,put到familyMap中 newConfig.fontFamilies.addAll(familyMap.values());
writePersistentConfig(newConfig);//将newConfig写入config.xml中
mConfigVersion++;
2)updateSerializedFontMap();
SharedMemory serializedFontMap = serializeFontMap(getSystemFontConfig());
-- >
SystemFonts.buildSystemFallback();
SystemFonts.buildSystemTypefaces();
return Typeface.serializeFontMap(typefaceMap);
-- >
setSerializedFontMap(serializedFontMap);
mSerializedFontMap = serializedFontMap;
getCurrentFontMap()返回的就是mSerializedFontMap
public static final class Lifecycle extends SystemService {
private final FontManagerService mService;
public Lifecycle(@NonNull Context context, boolean safeMode) {
super(context);
mService = new FontManagerService(context, safeMode);
}
@Override public void onStart() {
LocalServices.addService(FontManagerInternal.class,
new FontManagerInternal() {
@Override
@Nullable
public SharedMemory getSerializedSystemFontMap() {
if (!Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
return null;
}
return mService.getCurrentFontMap();
}
});
publishBinderService(Context.FONT_SERVICE, mService);
}
}
系统是如何发生改变的
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
SharedMemory serializedSystemFontMap = null;
final FontManagerInternal fm = LocalServices.getService(FontManagerInternal.class);
if (fm != null) {
serializedSystemFontMap = fm.getSerializedSystemFontMap();
}
thread.bindApplication(serializedSystemFontMap)
source.android.google.cn/docs/core/a…
对接接口:
import android.graphics.fonts.FontFamilyUpdateRequest;
import android.graphics.fonts.FontFileUpdateRequest;
import android.graphics.fonts.FontManager;
import android.graphics.fonts.FontStyle;
import android.os.ParcelFileDescriptor;
import android.text.FontConfig;
import java.nio.file.Files;
import java.io.File;
import java.nio.file.Paths;
import java.util.Arrays;
import java.io.IOException;
import java.util.List;
import static android.graphics.fonts.FontStyle.FONT_SLANT_UPRIGHT;
import static android.graphics.fonts.FontStyle.FONT_WEIGHT_BOLD;
import static android.graphics.fonts.FontStyle.FONT_WEIGHT_NORMAL;
import static android.graphics.fonts.FontStyle.FONT_WEIGHT_MEDIUM;
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import
com.android.compatibility.common.util.SystemUtil;
familyName = xml 标签中的 <family name="ndot-55">
private static final String OPPO_SANS_REGULAR_POSTSCRIPT_NAME = "OPPOSans-Regular";
private static final String OPPO_SANS_REGULAR_TTF = "/data/local/tmp/OPPOSans-Regular.ttf";
为字体文件签名
由于字体文件是存在风险的资源,因此必须通过可信的密钥对其进行验证。请仔细检查所有要更新的字体文件,然后使用您的私钥对其签名。此签名必须符合 fs-verity 的要求
private static final String OPPO_SANS_REGULAR_SIG = "/data/local/tmp/OPPOSans-Regular.sig";
private int onChangeFont(String familyName) throws IOException { List<FontFamilyUpdateRequest.Font> fonts =
Arrays.asList( new FontFamilyUpdateRequest.Font.Builder(OPPO_SANS_REGULAR_POSTSCRIPT_NAME,
new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT)).build()
);
FontFamilyUpdateRequest.FontFamily fontFamily = new FontFamilyUpdateRequest.FontFamily.Builder(familyName, fonts).build();
byte[] regularSig = Files.readAllBytes(Paths.get(OPPO_SANS_REGULAR_SIG));
try (ParcelFileDescriptor regularFd = ParcelFileDescriptor.open(
new File(OPPO_SANS_REGULAR_TTF), MODE_READ_ONLY); )
{
return SystemUtil.runWithShellPermissionIdentity(() -> {
FontConfig fontConfig = mFontManager.getFontConfig();
return mFontManager.updateFontFamily(new FontFamilyUpdateRequest.Builder() .addFontFileUpdateRequest(
new FontFileUpdateRequest(regularFd, regularSig))
.addFontFamily(fontFamily)
.build(), fontConfig.getConfigVersion());
});
}
}