日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android自带中文字体,Android更换系统默认显示的字体使用自定义字体

發布時間:2023/12/18 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android自带中文字体,Android更换系统默认显示的字体使用自定义字体 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

序言

上一篇Android 自定義字體,更換系統默認顯示的字體使用自定義字體有講到怎樣指定控件顯示指定字體,怎樣整個軟件顯示指定字體,怎樣WebView加載指定字體,但是還留下一個怎樣修改整個系統的默認字體,由于內容較多,所以單獨抽離出來講,由于要操作系統文件,因此需要Root權限或系統簽名,自己在操作前建議先備份下字體配置文件/system/etc/system_fonts.xml和/system/etc/fallback_fonts.xml,否則操作失敗有可能開機后無法進入桌面,此時就需要將備份的system_fonts.xml推送到對應目錄下并修改為對應的權限。

1、字體加載原理

① Android 系統的字體文件:位于 /system/fonts/ 文件夾下,我們可以到對應的目錄下進行查看,可以看出,Android的字體文件都是ttf文件,命令順序:adb shell ——>cd /system/fonts/ ——>ll,查看結果如下圖所示:

image.png

② 在/system/etc/目錄下有兩個字體配置文件,分別是system_fonts.xml 和 fallback_fonts.xml ,當系統需要加載字體時,會優先從 system_fonts.xml 文件開始查找,如果沒有找到再進入 fallback_fonts.xml 查找。

system_fonts.xml示范文件

sans-serif

arial

helvetica

tahoma

verdana

Roboto-Regular.ttf

Roboto-Bold.ttf

Roboto-Italic.ttf

Roboto-BoldItalic.ttf

sans-serif-light

Roboto-Light.ttf

Roboto-LightItalic.ttf

sans-serif-thin

Roboto-Thin.ttf

Roboto-ThinItalic.ttf

sans-serif-condensed

RobotoCondensed-Regular.ttf

RobotoCondensed-Bold.ttf

RobotoCondensed-Italic.ttf

RobotoCondensed-BoldItalic.ttf

serif

times

times new roman

palatino

georgia

baskerville

goudy

fantasy

cursive

ITC Stone Serif

DroidSerif-Regular.ttf

DroidSerif-Bold.ttf

DroidSerif-Italic.ttf

DroidSerif-BoldItalic.ttf

Droid Sans

DroidSans.ttf

DroidSans-Bold.ttf

monospace

courier

courier new

monaco

DroidSansMono.ttf

fallback_fonts.xml 示范文件

DroidNaskh-Regular.ttf

DroidNaskhUI-Regular.ttf

DroidSansEthiopic-Regular.ttf

DroidSansHebrew-Regular.ttf

DroidSansHebrew-Bold.ttf

NotoSansThai-Regular.ttf

NotoSansThai-Bold.ttf

NotoSansThaiUI-Regular.ttf

NotoSansThaiUI-Bold.ttf

DroidSansArmenian.ttf

DroidSansGeorgian.ttf

NotoSansDevanagari-Regular.ttf

NotoSansDevanagari-Bold.ttf

NotoSansDevanagariUI-Regular.ttf

NotoSansDevanagariUI-Bold.ttf

NotoSansTamil-Regular.ttf

NotoSansTamil-Bold.ttf

NotoSansTamilUI-Regular.ttf

NotoSansTamilUI-Bold.ttf

NotoSansMalayalam-Regular.ttf

NotoSansMalayalam-Bold.ttf

NotoSansMalayalamUI-Regular.ttf

NotoSansMalayalamUI-Bold.ttf

NotoSansBengali-Regular.ttf

NotoSansBengali-Bold.ttf

NotoSansBengaliUI-Regular.ttf

NotoSansBengaliUI-Bold.ttf

NotoSansTelugu-Regular.ttf

NotoSansTelugu-Bold.ttf

NotoSansTeluguUI-Regular.ttf

NotoSansTeluguUI-Bold.ttf

NotoSansKannada-Regular.ttf

NotoSansKannada-Bold.ttf

NotoSansKannadaUI-Regular.ttf

NotoSansKannadaUI-Bold.ttf

NotoSansKhmer-Regular.ttf

NotoSansKhmer-Bold.ttf

NotoSansKhmerUI-Regular.ttf

NotoSansKhmerUI-Bold.ttf

NotoSansLao-Regular.ttf

NotoSansLao-Bold.ttf

NotoSansLaoUI-Regular.ttf

NotoSansLaoUI-Bold.ttf

NanumGothic.ttf

Padauk-book.ttf

Padauk-bookbold.ttf

NotoSansSymbols-Regular.ttf

AndroidEmoji.ttf

NotoColorEmoji.ttf

DroidSansFallback.ttf

MTLmr3m.ttf

2、為系統添加一個默認字體

修改系統默認字體的原理:根據系統字體加載原理可知,我們只需要在路徑 /system/fonts/ 下添加我們自定義的ttf字體文件,然后修改 /system/etc/system_fonts.xml 字體配置文件,按照響應的格式添加一個節點,由于需要系統默認使用該字體,因此該節點需要是根節點familyset下的第一個子節點,系統在system_fonts.xml中找到了該字體的配置,故不會去fallback_fonts.xml 尋找,因此也只需要修改這一個配置文件即可,文件修改成功后需要注意已修改文件的讀寫權限(否則會沒有效果),為了方便,我們設置全部用戶可讀可寫。

① 判斷系統字體庫是否已有需要添加的字體文件

/**

* 檢查字體文件是否存在系統目錄中

* @param fontName 字體文件名稱

* @return ture:已存在

*/

private boolean checkFontTTFFile(String fontName) {

File dir = new File(systemFontsDir);

File[] files = dir.listFiles(); //字庫列表

if (files != null && files.length > 0) {

for (int i = 0; i < files.length; i++) {

File file = files[i];

if (file.exists() && file.getName().equals(fontName)) {

return true;

}

}

}

return false;

}

② 若①判斷后沒有則需要拷貝字體文件到對應路徑下

/**

* 拷貝字體文件

*

* @param fontName 字體文件名

* @param destDir 目標目錄

*/

private void copyFontTTF(String fontName, String destDir) {

try {

//將Assets文件夾中的字體文件讀出來

InputStream inputStream = getAssets().open("fonts/" + fontName);

//將字體文件寫入到sd卡中 ,不能直接寫入 /system/fonts/下,因為沒有寫文件的權限

File file = new File(getCacheDir(), fontName);

FileOutputStream fos = new FileOutputStream(file);

int leng = 0;

byte[] buffer = new byte[1024];

while (-1 != (leng = inputStream.read(buffer))) {

fos.write(buffer, 0, leng);

}

fos.flush();

fos.close();

inputStream.close();

runRootCommand("cp " + file.getAbsolutePath() + " " + destDir); //使用命令進行文件拷貝

Log.e(TAG, "copyFontTTF: 字體文件拷貝成功");

} catch (Exception e) {

e.printStackTrace();

}

}

③ 判斷字體配置文件 system_fonts.xml 是否已有該節點,若有則不進行操作,若無進行步驟④

/**

* 檢查指定的XML文件中是否有節點名稱為 refNodeName 的值為 compareNodeValue 的節點

*

* @param refNodeName 參考的節點名稱

* @param compareNodeValue 被比較的節點名稱下的值

* @param file XML文件

* @return ture存在該節點

*/

private boolean checkXmlNode(String refNodeName, String compareNodeValue, File file) {

boolean result = false;

try {

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

Document doc = builder.parse(file); // 解析XML到內存中

NodeList nodeList = doc.getElementsByTagName(refNodeName);

for (int i = 0; i < nodeList.getLength(); i++) { //判斷有沒有該節點

Node item = nodeList.item(i);

String itemValue = item.getFirstChild().getNodeValue();

if (itemValue.equals(compareNodeValue)) {

result = true;

}

}

} catch (Exception e) {

e.printStackTrace();

}

Log.e(TAG, "checkXmlNode: 檢查是否存在該節點 refNodeName=" + refNodeName + ",compareNodeValue=" + compareNodeValue + ",result=" + result);

return result;

}

④ 若③中沒有該節點,則在根節點familyset下的第一位置添加該節點并保存

/**

* 向system_fonts.xml文件增加一個節點

*

* @param nodeValue 節點的值

*/

private void addSystemFontNote(String nodeValue) {

try {

File file = new File(system_fonts);

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

Document doc = builder.parse(file); // 解析XML到內存中

Node nodeFamilyset = doc.getElementsByTagName("familyset").item(0);

Element elementFamily = doc.createElement("family");

Element elementNameset = doc.createElement("nameset");

Element elementName = doc.createElement("name");

elementName.setTextContent(nodeValue);

elementNameset.appendChild(elementName);//將name節點設置為nameset的子節點

Element elementFileset = doc.createElement("fileset");

Element elementFile = doc.createElement("file");

elementFile.setTextContent(nodeValue + ".ttf");

elementFileset.appendChild(elementFile);

elementFamily.appendChild(elementNameset);

elementFamily.appendChild(elementFileset);

Node nodeFamily = doc.getElementsByTagName("family").item(0);

nodeFamilyset.insertBefore(elementFamily, nodeFamily); //將節點elementFamily插入到節點nodeFamily之前

// 保存到文件中

saveXmlFile(doc, system_fonts);

Log.e(TAG, "addSystemFontNote: 節點添加成功");

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 保存xml文件到指定路徑

* @param doc 要保存的XML文檔對象

* @param destFile 目標路徑

* @throws TransformerException

*/

private void saveXmlFile(Document doc, String destFile) throws TransformerException {

Transformer transformer = TransformerFactory.newInstance().newTransformer();//創建一個用來轉換DOM對象的工廠對象并獲得轉換器對象

DOMSource domSource = new DOMSource(doc); //定義要轉換的源對象

File temFile = new File(getCacheDir(), "tem.xml");

StreamResult streamResult = new StreamResult(temFile); //定義要轉換到的目標文件

transformer.transform(domSource, streamResult); //開始轉換 ,

// runRootCommand("rm " + system_fonts);

runRootCommand("cat " + temFile.getAbsolutePath() + " > " + destFile);//復制文件內容

Log.e(TAG, "saveXmlFile: 保存文件成功," + destFile);

}

⑤ 完整的調用流程

private String system_fonts = "/system/etc/system_fonts.xml";

private String fallback_fonts = "/system/etc/fallback_fonts.xml";

private String systemFontsDir = "/system/fonts/";//系統存放字體文件的路徑

public void ywsflsjtForSystem(View view) {

String fontName = "ywsflsjt.ttf";

runRootCommand("mount -o remount rw /system"); //重新掛載該路徑為可讀寫模式

//以下操作建議在線程中執行

if (!checkFontTTFFile(fontName)) {

copyFontTTF(fontName, systemFontsDir);

}

runRootCommand("chmod 777 " + new File(systemFontsDir, fontName).getAbsolutePath());//修改字體文件的權限

String compareNodeValue = fontName.split("\\.")[0];

boolean node = checkXmlNode("name", compareNodeValue, new File(system_fonts));

if (node == false) { //沒有該節點,在頭部插入該節點

addSystemFontNote(compareNodeValue);

runRootCommand("chmod 777 " + system_fonts);

}

runRootCommand("reboot"); //要使修改后的字體生效需要重啟系統

}

⑥ 運行Root指令的方法

/**

* 請求ROOT權限后執行命令(最好開啟一個線程)

*

* @param cmd (pm install -r *.apk)

* @return

*/

public boolean runRootCommand(String cmd) {

Process process = null;

DataOutputStream os = null;

BufferedReader br = null;

StringBuilder sb = null;

try {

process = Runtime.getRuntime().exec("su");

os = new DataOutputStream(process.getOutputStream());

os.writeBytes(cmd + "\n");

os.writeBytes("exit\n");

br = new BufferedReader(new InputStreamReader(

process.getInputStream()));

sb = new StringBuilder();

String temp = null;

while ((temp = br.readLine()) != null) {

sb.append(temp + "\n");

if ("Success".equalsIgnoreCase(temp)) {

return true;

}

}

process.waitFor();

} catch (Exception e) {

Log.e(TAG, "異常:" + e.getMessage());

} finally {

try {

if (os != null) {

os.flush();

os.close();

}

if (br != null) {

br.close();

}

process.destroy();

} catch (Exception e) {

return false;

}

}

return false;

}

3、刪除已添加的系統默認字體

和添加字體相對應,需要先刪除字體文件,然后再刪除 system_fonts.xml和fallback_fonts.xml兩文件中的對應節點,由于我們沒有修改過fallback_fonts.xml文件因此不需要做刪除操作

① 刪除節點是需要調用checkXmlNode方法堅持節點是否存在,若存在則刪除數據

/**

* 刪除 system_fonts.xml文件中的節點名稱name值為 nodeValue的節點

*

* @param nodeValue

*/

private void deleteSystemFontNote(String nodeValue) {

Log.e(TAG, "deleteSystemFontNote: 刪除文件" + system_fonts + "中的節點:" + nodeValue);

try {

File file = new File(system_fonts);

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

Document doc = builder.parse(file); // 解析XML到內存中

NodeList nodeListName = doc.getElementsByTagName("name");

for (int i = 0; i < nodeListName.getLength(); i++) {

Node item = nodeListName.item(i);

String value = item.getFirstChild().getNodeValue();

if (value != null && nodeValue.equals(value)) {

Node nodenameset = item.getParentNode();

Node nodefamily = nodenameset.getParentNode();

Node nodefamilyset = nodefamily.getParentNode();

nodefamilyset.removeChild(nodefamily);

saveXmlFile(doc, system_fonts);

Log.e(TAG, "刪除節點成功,nodeValue=" + nodeValue);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

② 完整的刪除流程

public void deleteYwsflsjtForSystem(View view) {

String fontName = "ywsflsjt.ttf";

String nodeName = fontName.split("\\.")[0];

runRootCommand("mount -o remount rw /system"); //重新掛載該路徑為可讀寫模式

runRootCommand("rm " + systemFontsDir + fontName); //刪除字體文件

if (checkXmlNode("name", nodeName, new File(system_fonts))) {

deleteSystemFontNote(nodeName);

runRootCommand("chmod 777 " + system_fonts);

}

runRootCommand("reboot"); //要使修改后的字體生效需要重啟系統

}

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的android自带中文字体,Android更换系统默认显示的字体使用自定义字体的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。