从Android Pie(API 28(开始,Google不允许在2个不同的进程中使用单个WebView实例。
文档:https://developer.android.com/reference/android/webkit/WebView.html#setDataDirectorySuffix(java.lang.String(
按照要求,我打电话给WebView.setDataDirectorySuffix("dir_name_no_separator")
但不幸的是,我得到了一个例外。 我尝试在第二个进程服务 onCreate(( 中调用此方法。
java.lang.RuntimeException: Unable to create service com.myapp.service.MyService: java.lang.IllegalStateException: Can't set data directory suffix: WebView already initialized
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3544)
at android.app.ActivityThread.access$1300(ActivityThread.java:199)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1666)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.IllegalStateException: Can't set data directory suffix: WebView already initialized
at android.webkit.WebViewFactory.setDataDirectorySuffix(WebViewFactory.java:136)
at android.webkit.WebView.setDataDirectorySuffix(WebView.java:2165)
at com.myapp.service.MyService.onCreate(MyService.java:134)
我找不到任何例外的原因。我没有两次调用此方法,也没有在主进程中调用它。有什么想法吗?
已解决。
我的项目托管了 AdMob 广告,我在Application
类中调用了MobileAds.initialize()
方法onCreate()
。ads 初始值设定项加载一个WebView
现在禁止在新进程中执行该WebView.setDataDirectorySuffix("dir_name_no_separator")
,然后再调用 方法。
创建第二个进程时,它还会经历相同的应用程序创建流,这意味着它会调用Application
类中的相同onCreate()
,该类调用尝试创建新的WebView
实例的MobileAds.initialize()
,从而导致崩溃。
IllegalStateException: Can't set data directory suffix: WebView already initialized
我是如何解决这个问题的?
我使用以下方法获取进程名称并检查它是否是我的主进程 - 调用 MobileAds.initialize(( 方法,如果这是我的第二个进程,请调用WebView.setDataDirectorySuffix("dir_name_no_separator")
方法。
获取进程名称:
public static String getProcessName(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
if (processInfo.pid == android.os.Process.myPid()) {
return processInfo.processName;
}
}
return null;
}
应用程序类 onCreate((:
if (!Utils.getProcessName(this).equals("YOUR_SECOND_PROCESS_NAME")) {
MobileAds.initialize(this);
} else {
WebView.setDataDirectorySuffix("dir_name_no_separator")
}
总结修复程序的所有改进,这是 Kotlin 中的代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (packageName != Application.getProcessName()) {
WebView.setDataDirectorySuffix(Application.getProcessName())
}
}
将其添加到Application
类中以onCreate()
方法。
请注意,这只会解决最多 2 个进程的问题。如果你的应用使用更多,则必须为每个应用提供不同的 WebView 后缀。
当由于广告导致错误时,则在应用程序类中
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val process = getProcessName()
if (packageName != process) WebView.setDataDirectorySuffix(process)
}
MobileAds.initialize(this)
AudienceNetworkAds.initialize(this)
} catch (e: Error) {
Timber.e(e)
} catch (e: Exception) {
Timber.e(e)
}