【问题标题】:Android Pie: WebView showing error for plain HTTP on some sites, even with usesClearTextTraffic="true"Android Pie:WebView 在某些网站上显示纯 HTTP 错误,即使使用 usesClearTextTraffic="true"
【发布时间】:2018-11-13 21:22:04
【问题描述】:

我们的 android 应用程序中有一个 WebView,最终用户可以浏览到他们想要的任何站点。 Android Pie 默认禁用纯 HTTP,因此我们将 usesClearTextTraffic="true" 添加到清单中。

这适用于某些网站,但不适用于其他网站,例如 google.com!在不工作的网站上,我们仍然会得到 net::ERR_CLEARTEXT_NOT_PERMITTED,就好像我们没有设置清单设置一样。

我认为它可能与 HSTS 有关,但在这种情况下,我只希望 WebView 立即重定向到 HTTPS。

那么问题来了,为什么即使在 manifest 中开启了 usesClearTextTraffic,Android WebView 仍然无法通过纯 HTTP 浏览某些网站?

(PS 我们没有网络安全配置)

我们正在 Google Pixel 1XL 上进行测试。

普通的 http 不起作用:

普通的http工作:

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.umajin.umajinviewer">

    <permission android:name="com.umajin.umajinviewer.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.umajin.umajinviewer.permission.C2D_MESSAGE" />

    <application android:label="Umajin Preview"
                 android:icon="@mipmap/ic_launcher"
                 android:theme="@android:style/Theme.NoTitleBar">
        <activity android:name="Umajin"
                  android:label="Umajin Preview"
                  android:configChanges="orientation|screenSize|keyboardHidden"
                  android:screenOrientation="fullSensor"
                  android:icon="@mipmap/ic_launcher"
                  android:largeHeap="true"
                  android:windowSoftInputMode="stateHidden|adjustPan"
                  android:launchMode="singleTask"
                  android:usesCleartextTraffic="true"
                  >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
            </intent-filter>
        </activity>

        <receiver
            android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter
                android:priority="1">
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="com.umajin.umajinviewer" />
            </intent-filter>
        </receiver>
        <service android:name=".MyIntentService" />

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="<redacted>"/>

        <!-- Specify which class to instantiate for the alarm messages -->
        <receiver android:name="com.umajin.app.AlarmReceiver" >
        </receiver>

        <!-- Use this receiver if you to excute something at boot -->
        <!-- Required if you want alarms to survive a device restart -->
        <receiver
           android:name="com.umajin.umajinviewer.BootReceiver"
           android:enabled="true"
           android:exported="true"
           android:label="BootReceiver">
           <intent-filter>
              <action android:name="android.intent.action.BOOT_COMPLETED" />
           </intent-filter>
        </receiver>
        <!-- end boot receiver -->

        <!-- Add this to play private video files in fullscreen externally through intents. -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.umajin.umajinviewer.files"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
        <!-- Android Pie specific fix for crash on Google Maps. Throws a ClassNotFoundException when it fails to
             find "org.apache.http.ProtocolVersion".
             See https://stackoverflow.com/questions/50782806/android-google-maps-java-lang-noclassdeffounderror-failed-resolution-of-lorg-a -->
        <uses-library android:name="org.apache.http.legacy" android:required="false"/>
    </application>

    <uses-feature android:glEsVersion="0x00020000" /> 
    <uses-feature android:name="android.hardware.camera" android:required="false" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
    <uses-feature android:name="android.hardware.location" android:required="false" />
    <uses-feature android:name="android.hardware.location.gps" android:required="false" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <!-- WRITE no longer implies READ. By agreement, we always ask 
         for both at a time as the user prompts are identical and it can appear to 
         a user that they have been asked for the same thing twice even though the
         underlying permission asked for may be different. -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <!-- FINE and COARSE permissions result in the same prompt being displayed to the
         user. It can appear to the user that they have been asked for the same thing
         twice. By agreement, we always ask for both in one request
         to the user to avoid confusing the user. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.NFC" />
    <!-- Used for Samsung fingerprint scanner. -->
    <uses-permission android:name= "com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY"/>

    <!-- Required for Bluetooth LE -->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

    <!-- Use this permission if you want your applications to launch on startup -->
    <!-- Required if you want alarms to survive a device restart -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <!-- Required for WIFI scanning -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest> 

【问题讨论】:

  • 能否请您发布您的清单?
  • 当然,我已经添加了 Manifest。谢谢
  • 请查看解决方案

标签: android http webview


【解决方案1】:

解决方案:

我观察到你的Manifest.xml,你在&lt;activity&gt;标签中使用了android:usesCleartextTraffic="true"

正如您在Documentation of the activity tag 中看到的那样,它不提供文档中提供的语法中的任何功能。

正如您在下面的屏幕截图中看到的,明文流量的描述非常简单。

另外,如果您查看Documentation of the application tag,您会注意到android:usesCleartextTrafficApplication Tag 的属性之一。

所以这里需要的唯一修复是从 activity 标记中删除属性并在 application 标记中使用它,@987654331 不支持活动标记@。

从 Android 9 (Pie) 开始默认禁用明文流量。

因此,解决方案是:

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        ...
        android:usesCleartextTraffic="true"
        ...>
        ...
    </application>
</manifest>

试试吧,如果您有任何与此相关的问题,请发表评论。

【讨论】:

  • 唯一的谜团是为什么有些网站显然没有它也能正常工作。也许它们在 HSTS 列表中,因此在 web 视图中重定向到 HTTPS。
  • @O'Rooney 是的,无论如何我很高兴答案有所帮助。 :)
  • 我遵循了所有这些步骤,但我的 webview 在这些设备中仍然是黑色的。任何其他想法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 2012-12-03
  • 2016-05-11
  • 2022-10-07
  • 2020-10-11
  • 2017-01-12
相关资源
最近更新 更多