嘗試在運行時修改 res/xml/ 下的 XML 文件屬性(如 android:requiredDeviceUnlock),發現 getResources().getXml() 返回 XmlResourceParser 僅支持解析,不支持寫入。
res/ 目錄下的所有資源在打包時被編譯進 APK,屬於只讀資產。Android 安全模型禁止應用在運行時修改自身安裝包內的文件。
| 方案 | 適用場景 | 實現要點 |
|---|---|---|
| SharedPreferences | 鍵值對配置、啟用/禁用標志 | getSharedPreferences("config", MODE_PRIVATE).edit().putBoolean("require_unlock", true).apply() |
| 內部存儲文件 | 結構化配置、需保持 XML 格式 | context.getFilesDir() 讀寫私有文件,首次從 assets 複製模板 |
| DataStore (Jetpack) | 現代異步配置存儲、類型安全 | PreferencesDataStore 或 ProtoDataStore 替代 SharedPreferences |
| 遠程配置 | 動態下發、A/B 測試 | Firebase Remote Config 或自建配置中心 |
File xmlFile = new File(context.getFilesDir(), "device_config.xml");
if (!xmlFile.exists()) {
// 首次從 assets 複製默認配置
try (InputStream in = context.getAssets().open("device_config.xml");
FileOutputStream out = new FileOutputStream(xmlFile)) {
byte[] buf = new byte[1024]; int len;
while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
}
}
// 修改
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse(xmlFile);
Element root = doc.getDocumentElement();
root.setAttribute("requiredDeviceUnlock", "true");
// 保存
TransformerFactory.newInstance().newTransformer()
.transform(new DOMSource(doc), new StreamResult(xmlFile));
拋棄修改 res/xml 的想法,改用應用沙箱內的可寫存儲方案,符合 Android 安全模型且靈活可控。