Android Pie (9.0) WebView 多进程
Android Pie (9.0) WebView in multi-process
正在启动 Android Pie (API 28),Google 不允许在 2 个不同的进程中使用单个 WebView 实例。
根据需要,我调用了 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.access00(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
class onCreate()
中调用了 MobileAds.initialize()
方法。广告初始值设定项加载 WebView
现在禁止在调用 WebView.setDataDirectorySuffix("dir_name_no_separator")
方法之前在新进程中执行此操作。
创建第二个进程时,它也通过相同的应用程序创建流程,这意味着它在 Application
class 中调用相同的 onCreate()
,后者调用 MobileAds.initialize()
试图创建一个新的 WebView
实例并由此导致崩溃。
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;
}
应用程序class 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
class 到 onCreate()
方法中。
请注意,这只会解决最多 2 个进程的问题。如果您的应用使用更多,则必须为每个应用提供不同的 WebView 后缀。
当由于广告导致错误时,然后在应用程序中 class
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)
}
正在启动 Android Pie (API 28),Google 不允许在 2 个不同的进程中使用单个 WebView 实例。
根据需要,我调用了 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.access00(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
class onCreate()
中调用了 MobileAds.initialize()
方法。广告初始值设定项加载 WebView
现在禁止在调用 WebView.setDataDirectorySuffix("dir_name_no_separator")
方法之前在新进程中执行此操作。
创建第二个进程时,它也通过相同的应用程序创建流程,这意味着它在 Application
class 中调用相同的 onCreate()
,后者调用 MobileAds.initialize()
试图创建一个新的 WebView
实例并由此导致崩溃。
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;
}
应用程序class 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
class 到 onCreate()
方法中。
请注意,这只会解决最多 2 个进程的问题。如果您的应用使用更多,则必须为每个应用提供不同的 WebView 后缀。
当由于广告导致错误时,然后在应用程序中 class
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)
}