Android WebView在系统进程中无法使用

android app内置webview,随android版本升级进程关系的变化 Q 最近遇到一个问题:多个应用打不开,闪退。 A 调查发现闪退的应用都在首屏加载了webview,而在android p上webview的渲染是在另外一个进程上进行的,进程名字类似webview:sandboxed_process0,这个进程是由webview_zygote这样一个进程fork出来的,而webview_zygote由于缺少... 阅读详情

因为最近有个需求是在系统应用中使用 WebView,所以配置了 android:sharedUserId="android.uid.system", 让应用共享系统进程。

错误日志是这样的:

java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes
  at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:96)
  at android.webkit.WebView.getFactory(WebView.java:2194)
  at android.webkit.WebView.ensureProviderCreated(WebView.java:2189)
  at android.webkit.WebView.setOverScrollMode(WebView.java:2248)
  at android.view.View.<init>(View.java:3588)
  at android.view.View.<init>(View.java:3682)
  at android.view.ViewGroup.<init>(ViewGroup.java:497)
  at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55)
  at android.webkit.WebView.<init>(WebView.java:544)
  at android.webkit.WebView.<init>(WebView.java:489)
  at android.webkit.WebView.<init>(WebView.java:472)
  at android.webkit.WebView.<init>(WebView.java:459)
  at android.webkit.WebView.<init>(WebView.java:449)
就是说为了安全性考虑,不允许在享有特权的进程也就是系统进程里面使用 WebView,异常是在 WebView 初始化的时候抛出的。

查看源码:

static WebViewFactoryProvider getProvider() {
        synchronized (sProviderLock) {
            // For now the main purpose of this function (and the factory abstraction) is to keep
            // us honest and minimize usage of WebView internals when binding the proxy.
            if (sProviderInstance != null) return sProviderInstance;

            final int uid = android.os.Process.myUid();
            if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID) {
                throw new UnsupportedOperationException(
                        "For security reasons, WebView is not allowed in privileged processes");
            }

            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
                loadNativeLibrary();
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);

                Class<WebViewFactoryProvider> providerClass;
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getFactoryClass()");
                try {
                    providerClass = getFactoryClass();
                } catch (ClassNotFoundException e) {
                    Log.e(LOGTAG, "error loading provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }

                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
                try {
                    try {
                        sProviderInstance = providerClass.getConstructor(WebViewDelegate.class)
                                .newInstance(new WebViewDelegate());
                    } catch (Exception e) {
                        sProviderInstance = providerClass.newInstance();
                    }
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    Log.e(LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                    StrictMode.setThreadPolicy(oldPolicy);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
            }
        }
    }

可以看出,首次使用时,系统会进行检查,如果 UID 是 root 进程或者系统进程,直接抛出异常。sProviderInstance 是 WebViewFactoryProvider 的对象,主要提供创建 WebView 内核的机制。WebView在 Android 4.4 之前使用的是 Webkit 内核,在 Android 4.4 以后切换到了 Chromium 内核。Google 使用了工厂方法模式,优雅地切换 WebView 内核的实现方式。我们注意到只有 sProviderInstance 为空的时候系统才去检查进程,然后创建 sProviderInstance对象。所以这给了我们一个启发 ---- 能不能一开始就主动创建 sProviderInstance 对象,把她塞到 WebViewFactory 类里面,从而欺骗 API 绕过系统检查呢?
下面就要用到 Hook 的思想了,首先要找到一个合适的点,静态变量、单例是最佳选择,刚刚好 sProviderInstance 是静态的。那就开始拿它开刀,看看系统是怎么创建 sProviderInstance 的,我们自己也模仿它这么做。其实系统也是通过反射来做的,这是 getFactoryClass 的源码,我们来看看。

private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
        Application initialApplication = AppGlobals.getInitialApplication();
        try {
            // First fetch the package info so we can log the webview package version.
            String packageName = getWebViewPackageName();
            sPackageInfo = initialApplication.getPackageManager().getPackageInfo(packageName, 0);
            Log.i(LOGTAG, "Loading " + packageName + " version " + sPackageInfo.versionName +
                          " (code " + sPackageInfo.versionCode + ")");

            // Construct a package context to load the Java code into the current app.
            Context webViewContext = initialApplication.createPackageContext(packageName,
                    Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
            initialApplication.getAssets().addAssetPath(
                    webViewContext.getApplicationInfo().sourceDir);
            ClassLoader clazzLoader = webViewContext.getClassLoader();
            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
            try {
                return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
                                                                     clazzLoader);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
            }
        } catch (PackageManager.NameNotFoundException e) {
            // If the package doesn't exist, then try loading the null WebView instead.
            // If that succeeds, then this is a device without WebView support; if it fails then
            // swallow the failure, complain that the real WebView is missing and rethrow the
            // original exception.
            try {
                return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
            } catch (ClassNotFoundException e2) {
                // Ignore.
            }
            Log.e(LOGTAG, "Chromium WebView package does not exist", e);
            throw new AndroidRuntimeException(e);
        }
    }
返回值是一个 WebViewFactoryProvider 的类,可以看到系统会首先加载 CHROMIUM_WEBVIEW_FACTORY,也就是使用 Chrome 内核的 WebView。这个方法是静态的,我们就可以用反射调用了。整个创建 sProviderInstance 的过程都可以用反射搞定,其他细节就不多说了。需要注意的是 API 21 以上在使用 WebView 时系统才会检查进程。但是 API 22 和 22 以上源码还是有差别,这里只是方法名字的改动,我们根据版本处理一下就好。

public static void hookWebView() {
        int sdkInt = Build.VERSION.SDK_INT;
        try {
            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
            Field field = factoryClass.getDeclaredField("sProviderInstance");
            field.setAccessible(true);
            Object sProviderInstance = field.get(null);
            if (sProviderInstance != null) {
                log.debug("sProviderInstance isn't null");
                return;
            }
            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
            } else {
                log.info("Don't need to Hook WebView");
                return;
            }
            getProviderClassMethod.setAccessible(true);
            Class<?> providerClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
            Constructor<?> providerConstructor = providerClass.getConstructor(delegateClass);
            if (providerConstructor != null) {
                providerConstructor.setAccessible(true);
                Constructor<?> declaredConstructor = delegateClass.getDeclaredConstructor();
                declaredConstructor.setAccessible(true);
                sProviderInstance = providerConstructor.newInstance(declaredConstructor.newInstance());
                log.debug("sProviderInstance:{}", sProviderInstance);
                field.set("sProviderInstance", sProviderInstance);
            }
            log.debug("Hook done!");
        } catch (Throwable e) {
            log.error(e);
        }
    }
在使用 WebView 之前,我们先 Hook WebViewFactory,创建 sProviderInstance 对象,从而绕过系统检查。


使用WebView出现java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed 在系统应用里面使用WebView出现java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes错误,看错误信息是授权问题。在webView加载网页前使用hook。把权限检查屏蔽掉,修改完成。 阅读详情

相关推荐

java.lang.UnsupportedOperationException异常(csdn)————程序.pdf

java.lang.UnsupportedOperationException异常(csdn)————程序

java.lang.UnsupportedOperationException WebView is not allowed in privileged processes

最近做一个项目,项目调试基础库的一个调试工具展示设备信息页面使用WebView。有一个应用集成调试基础库展示内容时出现 java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes 因为应用是系统级别的,在AndroidManif

SweetTool的专栏 8590

Android 兼容性问题:java.lang.UnsupportedOperationException解决办法

主要介绍了Android 兼容性问题:java.lang.UnsupportedOperationException解决办法的相关资料,需要的朋友可以参考下

处理For security reasons, WebView is not allowed in privileged processes崩溃问题

由于webView存在安全漏洞,谷歌从5.1开始全面禁止系统应用使用webview,使用会导致应用崩溃错误提示:Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes异常信息可以看出 是在 WebViewFactory.java 的getProvider 方法 抛出的。如果是系统id,就抛出异常!

weixin_45122125的博客 2244

Android webveiw 出现栈错误解决办法

主要介绍了Android webveiw 出现栈错误解决办法的相关资料,出现java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes,这里提供解决办法,需要的朋友可以参考下

uni踩坑笔记 - 离线打包调起微信分享后从微信返回APP时黑屏

apk能成功调起微信并进行分享操作,但分享完成后点击回到应用后应用出现黑屏的情况,并在约3-5秒后自动重启。

weixin_46737742的博客 5215

Android系统WebView无法安装,Android系统进程无法加载WebView

当系统进程加载WebView时会报错:UnsupportedOperationException:如下java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processesat android.webkit.WebViewFactory.getProv...

weixin_29021757的博客 3101

Halcon实战:5分钟搞定自定义直线卡尺工具(附完整代码下载)

本文详细介绍了如何使用Halcon快速开发自定义直线卡尺工具,通过交互式ROI绘制、边缘检测和直线拟合三个核心函数,实现高效工业视觉检测。文章包含完整代码下载,帮助开发者在5分钟内掌握这一实用工具的开发技巧,提升直线检测的精度和效率。

perl8的博客 252

android webview 返回异常,Android开发:系统进程中使用Webview引发异常的处理

我司开发的产品一般都是系统应用,即在 AndroidManifest.xml 中配置了android:sharedUserId="android.uid.system",最近在布局开发中使用了 Webview,然而程序在运行时直接 carsh 了,查看 log,报错信息如下:Caused by: java.lang.UnsupportedOperationException: For secur...

weixin_32954401的博客 1341

【教程】安装 iterm2 打造漂亮且高性能的 mac 终端

最近电脑重新安装系统,开发环境和软件都需要重新安装和配置,其中终端工具是必不可少的,正好利用这个机会,介绍一下 macOS 终端神器 iTerm2 的安装和配置,并推荐几款好用的插件和工具。在IT领域中,工具的选择和使用对于开发者和运维人员来说至关重要。而在众多终端模拟器中,ITerm2无疑是一个出色的选择,希望本篇的文章能对你有些帮助,感兴趣的朋友可以登录官网查看官方文档。我是刘大大,持续分享AI相关领域的知识和工具,喜欢点点关注。

刘大大AI的博客 3402

Win11 WSL2 Ubuntu 18.04 ROS Gazebo 图形渲染性能调优:从LLVM到NVIDIA GPU的完整指南

本文详细解决了在Win11 WSL2 Ubuntu 18.04环境中运行ROS Gazebo时图形渲染卡顿的问题。通过诊断默认LLVM软件渲染的瓶颈,指导用户更新Mesa驱动PPA源,并关键性地设置环境变量以强制启用NVIDIA GPU硬件加速,最终显著提升仿真性能与流畅度。

weixin_29204749的博客 284

Android Webview无法加载问题分析 (三)

正常webview加载的时候会有如下打印:表示webview进程启动当安装应用的时候,或者使用am force-stop 应用的时候,会有以下打印,表示webview进程被杀死且释放当使用pm clear 应用的时候,会有以下打印,表示webview进程被杀死且释放xxx/org.chromium.content.app.SandboxedProcessService进程被系统拦截,不能再次启动导致webview无法加载出来。

Red风信子的博客 608

从C-EPS到DP-EPS:手把手图解不同EPS类型怎么选,对你的车操控感影响有多大?

方向盘转动时那股细腻的阻尼感,高速过弯时令人安心的沉稳,或是狭窄车位里一根手指就能拨动的轻盈——这些看似微妙的差异,其实都源自转向系统电机那几厘米的安装位置变化。当我们谈论驾驶乐趣时,发动机参数和悬架调校总是占据C位,但真正连接驾驶者与车辆的神经末梢,恰恰是那套默默工作的电动助力转向系统(EPS)。不同EPS类型带来的操控特性差异,可能比马力数字更能定义一辆车的性格。

weixin_30920513的博客 532

学习分享-WebView不能使用在特权进程中

反射:Java 程序运行期间,动态获取类的构造器、方法、字段,并绕过访问权限直接调用 / 修改它们。问题:从Android11之后很多的功能都需要系统签名之后才能正常使用,比如录音,但是加了系统签名。Hook:不修改源码,靠反射在运行时找到目标方法 / 字段,拦截并篡改系统的行为。解决:在webview初始化之前加反射 Hook 绕过。

优快云Reader123456的博客 331

TC3XX - MCAL知识点(九):PWM EB-tresos配置说明及代码浅析

脉冲宽度调制(PWM)驱动器负责提供与AUTOSAR指定的PWM信号生成相关的标准服务。PWM通道的底层定时器驱动是GTM (TOM或ATOM片)或CCU6 (T12或T13片)定时器通道。软硬件匹配关系如下:PWM直接引用的是GTM与CCU6模块,然后GTM与CCU6再关联到Port的,根据软硬件匹配关系,也能调用中断来使用,本例子没使用中断。CCU6是一个高分辨率的16位捕获和比较单元,具有特定的应用模式,主要用于交流驱动控制。特殊的工作模式支持控制无刷直流电机使用霍尔传感器或反电动势检测。

梦想技术家 2889

PINN疲劳寿命预测优化

本项目基于物理信息神经网络(PINN)构建材料疲劳寿命预测模型,通过融合Paris裂纹扩展方程与实验数据,实现裂纹扩展行为的精准预测。核心方法包括:1)将Paris方程作为物理约束嵌入神经网络训练;2)生成含噪声的模拟数据并进行归一化处理;3)采用PINN-GA联合优化框架,以裂纹扩展速率最小化为目标优化材料参数。该方案通过物理规律与数据驱动的结合,显著提升预测模型的泛化能力,为工程材料寿命评估提供新思路。

huanghm88的专栏 147

android9系统webview崩溃,Android WebView已开始在Android 9上崩溃

您好专家Android开发人员:我们有一个android应用,我们的基本工作流程如下通过电子邮件或短信向用户发送了链接用户单击链接,然后在Chrome或Android默认浏览器上打开一个页面,并带有一个名为JOIN的按钮。用户单击此JOIN按钮,我们的应用程序启动,并在Webview中显示一个页面,要求用户输入名字,姓氏和电话/电子邮件,然后用户单击名为INITIATE的按钮我们验证信息-如果用户...

weixin_31313071的博客 4097

【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例(2023/12/1更新)

ShaderGraph是Unity中的一个可视化工具,用于创建和编辑图形着色器。其意义在于简化编写复杂着色器的过程,减少对具体编程语言的依赖,使艺术家和设计师可以更方便地创建各种美术效果。使用ShaderGraph可以通过图形界面设置着色器属性,包括颜色、纹理、光照等,并在视窗预览中即时显示结果,从而快速迭代和调整着色器。使用ShaderGraph需要先安装Unity 2018.1或以上版本,并添加ShaderGraph插件。打开ShaderGraph面板后,可以通过拖放节点并连接它们来创建着色器。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 4万+

android 不使用系统webview,解决 Android 系统应用无法使用WebView的问题

在 android 8.0 系统上,普通应用使用 WebView 时,正常使用没问题。如果是系统级应用,就会报错java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes解决办法有:1.使用 hookWebView() 方法欺骗系统;2.修...

weixin_28339527的博客 3468

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

安卓WebView的使用

WebView是Android中的原生UI控件,主要用于在app应用中方便地访问远程网页或本地html资源。同时,WebView也在Android中充当Java代码和JS代码之间交互的桥梁。实际上,也可以将WebView看做一个功能最小化的浏览器。

qq_40364278的博客 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Android上多进程中使用webview的问题

在Andrid P以上的系统中,如果使用了多个进程,而且在这些进程中使用到了webview,那么你可能遇到下面的异常提示 java.lang.RuntimeException: Using WebView from more than one process at once with the same data directory is not supported. https://crbug....

土匪头子的专栏 5872

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Android WebView独立进程解决方案

启动微信时进程列表打开微信公众号时进程列表image.png打开微信小程序时进程列表image.png以上是微信的进程list,简单分析一下各个进程的功能如下:com.tencent.mm :微信主进程,会话和朋友圈相关com.tencent.mm:push :微信push, 保活com.tencent.mm:tools 和 com.tencent.mm:support : 功能支持,比如微信中打开一个独立网页是在tools进程中。

2401_87196188的博客 2202

Android安卓自带的 WebView 浏览器内核更新

Android 安卓自带 WebView 浏览器内核更新教程

aken 8万+

多进程android webview,Android上多进程中使用webview的问题

在Andrid P以上的系统中,如果使用了多个进程,而且在这些进程中使用到了webview,那么你可能遇到下面的异常提示java.lang.RuntimeException: Using WebView from more than one process at once with the same data directory is not supported. https://crbug.co...

weixin_42297714的博客 1612
上一篇: Android .mk文件语法解析
下一篇: 推荐一些 Windows 平台上的优质高效软件
旧时旅人
博客等级 码龄10年 186粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧时旅人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值