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'
}
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
.