在上一篇文章中介紹了可以有效解決WebView多進(jìn)程崩潰的辦法菩混,但隔了兩個(gè)版本后這個(gè)問題竟然死灰復(fù)燃糖埋,這究竟是怎么回事呢?
《涼州詞》
葡萄美酒夜光杯蓉冈,欲飲琵琶馬上催。
醉臥沙場君莫笑轩触,古來征戰(zhàn)幾人回寞酿?
-王翰
問題原因
使用上一篇文章中提供的解決方案上線后取得了不錯(cuò)的效果,但最近這個(gè)問題又出現(xiàn)了脱柱,使用debug包查看webview數(shù)據(jù)目錄發(fā)現(xiàn)系統(tǒng)默認(rèn)添加了進(jìn)程名后綴伐弹,這是由于用戶更新了手機(jī)系統(tǒng)導(dǎo)致,使用華為mate20X測試調(diào)用WebView.setDataDirectorySuffix
自定義后綴已不生效榨为,會默認(rèn)強(qiáng)制指定后綴為進(jìn)程名惨好,另外還發(fā)現(xiàn)部分華為手機(jī)直接將webview目錄名app_webview改為了app_hws_webview。
oppo手機(jī)OPPO PDNM00
華為mate30pro
榮耀10手機(jī)榮耀 HRY AL00A
解決方案
綜上所述随闺,我們需要針對不同手機(jī)系統(tǒng)遍歷可能的文件路徑日川,最新解決代碼如下:
private static void handleWebviewDir(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
return;
}
try {
Set<String> pathSet = new HashSet<>();
String suffix = "";
String dataPath = context.getDataDir().getAbsolutePath();
String webViewDir = "/app_webview";
String huaweiWebViewDir = "/app_hws_webview";
String lockFile = "/webview_data.lock";
String processName = getProcessName(context);
if (!TextUtils.equals(context.getPackageName(), processName)) {//判斷不等于默認(rèn)進(jìn)程名稱
suffix = TextUtils.isEmpty(processName) ? context.getPackageName() : processName;
WebView.setDataDirectorySuffix(suffix);
suffix = "_" + suffix;
pathSet.add(dataPath + webViewDir + suffix + lockFile);
if (RomUtils.INSTANCE.checkIsHuaweiRom()) {
pathSet.add(dataPath + huaweiWebViewDir + suffix + lockFile);
}
}else{
//主進(jìn)程
suffix = "_" + processName;
pathSet.add(dataPath + webViewDir + lockFile);//默認(rèn)未添加進(jìn)程名后綴
pathSet.add(dataPath + webViewDir + suffix + lockFile);//系統(tǒng)自動(dòng)添加了進(jìn)程名后綴
if (RomUtils.INSTANCE.checkIsHuaweiRom()) {//部分華為手機(jī)更改了webview目錄名
pathSet.add(dataPath + huaweiWebViewDir + lockFile);
pathSet.add(dataPath + huaweiWebViewDir + suffix + lockFile);
}
}
for (String path : pathSet) {
File file = new File(path);
if (file.exists()) {
tryLockOrRecreateFile(file);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@TargetApi(Build.VERSION_CODES.P)
private static void tryLockOrRecreateFile(File file) {
try {
FileLock tryLock = new RandomAccessFile(file, "rw").getChannel().tryLock();
if (tryLock != null) {
tryLock.close();
} else {
createFile(file, file.delete());
}
} catch (Exception e) {
e.printStackTrace();
boolean deleted = false;
if (file.exists()) {
deleted = file.delete();
}
createFile(file, deleted);
}
}
private static void createFile(File file, boolean deleted){
try {
if (deleted && !file.exists()) {
file.createNewFile();
}
} catch (Exception e) {
e.printStackTrace();
}
}