javaandroidandroid-studioandroid-webview

Android WebView Crashes for all URLs except `google.com`


I wanted to have a website inside android app. So I made a very simple app (from this youtube tutorial) and if I put grafanaWebsite.loadUrl("https://google.com/") into the class file, I get the google page. If a put any other url, even https://www.google.com/" or http://google.com/ my app crashes immediately when trying to lauch it, see Logcat below. (Still didn't find any other working url.) Ultimately, I would like to load http://192.168.xxx.xxx:3000/. What am I doing wrong ? Thank you !

Here is AndroidManifest.xml and MainActivity.java :

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

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

    <application
        android:usesCleartextTraffic="true"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.PVMonitoring"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
package com.example.pvmonitoring;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    WebView grafanaWebsite;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        grafanaWebsite = findViewById(R.id.grafanaWebsite);
        grafanaWebsite.getSettings().setJavaScriptEnabled(true);
        grafanaWebsite.setWebViewClient(new WebViewClient());
        grafanaWebsite.loadUrl("https://www.google.com/");
    }
}

Logcat output of the crash:

2024-04-09 15:13:09.832 5963-5963/com.example.pvmonitoring E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.pvmonitoring, PID: 5963
    java.lang.SecurityException: Writable dex file '/data/data/com.example.pvmonitoring/code_cache/.overlay/base.apk/classes3.dex' is not allowed.
        at dalvik.system.DexFile.openDexFileNative(Native Method)
        at dalvik.system.DexFile.openDexFile(DexFile.java:406)
        at dalvik.system.DexFile.<init>(DexFile.java:128)
        at dalvik.system.DexFile.<init>(DexFile.java:101)
        at dalvik.system.DexPathList.loadDexFile(DexPathList.java:438)
        at dalvik.system.DexPathList.makeDexElements(DexPathList.java:387)
        at dalvik.system.DexPathList.<init>(DexPathList.java:166)
        at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:160)
        at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:130)
        at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:146)
        at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:93)
        at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:134)
        at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:126)
        at android.app.ApplicationLoaders.getClassLoaderWithSharedLibraries(ApplicationLoaders.java:61)
        at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:1051)
        at android.app.LoadedApk.getClassLoader(LoadedApk.java:1143)
        at android.app.LoadedApk.getResources(LoadedApk.java:1428)
        at android.app.ContextImpl.createAppContext(ContextImpl.java:3487)
        at android.app.ContextImpl.createAppContext(ContextImpl.java:3479)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7539)
        at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2478)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:230)
        at android.os.Looper.loop(Looper.java:319)
        at android.app.ActivityThread.main(ActivityThread.java:8893)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

build.gradle (Module) :

plugins {
    id 'com.android.application'
}

android {
    compileSdk 34

    defaultConfig {
        applicationId "com.example.pvmonitoring"
        minSdk 24
        targetSdk 34
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.10.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

Solution

  • This error is most likely be caused by an older Android Studio version in combination with an Android 14+ device:

    Android 14 devices no longer allow "executable code" like dex files to be loaded from places where the app has write access.

    Android Studio contains a feature called "Instant Run" which allows to patch code updates into running apps, so if you press "Run" in Android Studio only the code changes can be uploaded instead of the whole APK file. Especially on large APK files this can save a lot of time.

    It seems that older Android Studio versions write the code changes into a file like /data/data/<packagename>/code_cache/.overlay/base.apk/classes?.dex which is no longer allowed since Android 14.

    To fix this problem you have to update the used Android Studio version to at least Android Studio Hedgehog.

    Alternatively if don't can or want to update Android Studio you can try to disable "Instant Run" functionality via Android Studio settings.

    Or you don't use the run button and instead install your app via command-line: ./gradlew installDebug.