skip to Main Content

WAfter browsing the internet, watching a few YouTube videos, I’ve to admit, that I’m at the end of the road. Amongs plain wrong, and/or outdated instructions, there’s not much left to do than to turn to the community in hopes someone actually has an up-to-date solution.

I’ll update this main thread accordingly to display the "correct" code once we’re done.

I’ve used the following video, relatively recent, which results in a working app on the emulator, but does not allow for generating a signed app bundle. I’d assume it’s the closest solution to making this work and being able to build a basic-webview app. Even the Android Studio Documentation offers a solution which results in an unresolved reference.

Source (a):
https://www.youtube.com/watch?v=mLsLwqpDoE4

Source(b):
https://developer.android.com/develop/ui/views/layout/webapps/webview

Code:

MainActivity

package com.sloth.hub

import android.R
import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.sloth.hub.ui.theme.SlothHubTheme


class MainActivity : ComponentActivity() {

    private var myWebView: WebView? = findViewById<View>(R.id.webView) as WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SlothHubTheme {
                // A surface container using the 'background' color from the theme
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    Greeting("Android")
                }
            }
        }
        myWebView.setWebViewClient(WebViewClient())
        myWebView.loadUrl("https://app.sloths.one")
        val webSettings = myWebView.getSettings()
        webSettings.javaScriptEnabled = true
    }

    class myWebClient : WebViewClient() {
        override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
            super.onPageStarted(view, url, favicon)
        }

        override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
            view.loadUrl(url)
            return true
        }
    }

    override fun onBackPressed() {
        if (myWebView!!.canGoBack()) {
            myWebView!!.goBack()
        } else {
            super.onBackPressed()
        }
    }


}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
            text = "Hello $name!",
            modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    SlothHubTheme {
        Greeting("Android")
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Errors:

e: /home/dgriffin/AndroidStudioProjects/SlothHub/app/src/main/java/com/sloth/hub/MainActivity.kt: (23, 63): Unresolved reference: webview
e: /home/dgriffin/AndroidStudioProjects/SlothHub/app/src/main/java/com/sloth/hub/MainActivity.kt: (28, 18): Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type WebView?
e: /home/dgriffin/AndroidStudioProjects/SlothHub/app/src/main/java/com/sloth/hub/MainActivity.kt: (29, 18): Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type WebView?
e: /home/dgriffin/AndroidStudioProjects/SlothHub/app/src/main/java/com/sloth/hub/MainActivity.kt: (30, 36): Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type WebView?
---
org.gradle.api.GradleException: Compilation error. See log for more details
Caused by: org.gradle.api.GradleException: Compilation error. See log for more details

2

Answers


  1. I don’t use WebViews, so I can’t go beyond explaining how to get it into your Activity.

    You already have an XML layout created that has a WebView in it, so you just need to set that layout as your content view, and afterwards use findViewById to get the reference to put in your property. Your property needs to be lateinit so it won’t have to be nullable. We use lateinit for properties that we cannot initialize until onCreate() but are definitely not null once they have been initialized.

    Since you have an XML layout, you can delete all the Compose stuff.

    class MainActivity : ComponentActivity() {
    
        private lateinit var myWebView: WebView
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            myWebView = findViewById(R.id.webView)
            myWebView.webViewClient = myWebViewClient() // I assume you meant to instantiate your own class, not the superclass WebViewClient
            myWebView.loadUrl("https://app.sloths.one")
            val webSettings = myWebView.settings
            webSettings.javaScriptEnabled = true
        }
    
        // Keep the other code you had below the onCreate function
    
    }
    
    // You can delete the Composable functions.
    

    You can also use the apply scope function to clean it up a bit:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myWebView = findViewById(R.id.webView).apply {
            webViewClient = myWebViewClient()
            loadUrl("https://app.sloths.one")
            settings.javaScriptEnabled = true
        }
    }
    
    Login or Signup to reply.
  2. Here is a super simple example that you could test out…

    package com.sloth.hub
    
    import android.os.Bundle
    import android.webkit.WebChromeClient
    import android.webkit.WebView
    import android.webkit.WebViewClient
    import androidx.appcompat.app.AppCompatActivity
    
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            supportActionBar?.hide()
    
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val myWebView: WebView = findViewById(R.id.webView)
    
            myWebView.loadUrl("https://app.sloths.one")
    
            myWebView.webViewClient = WebViewClient()
    
            myWebView.settings.javaScriptEnabled = true
        }
    
        override fun onBackPressed() {
            val myWebView: WebView = findViewById(R.id.webView)
            myWebView.webViewClient = WebViewClient()
            if (myWebView.canGoBack()) myWebView.goBack() else super.onBackPressed()
        }
    }
    

    I definitely agree how much of a pain it can be. I had tried various examples with no avail when I first started. And now I’m stuck again and looking for some answers on Stack Overflow 🙂 This code above has worked for me for some basic use.
    Also, be sure to put the following in your AndroidManifest.xml: <uses-permission android:name="android.permission.INTERNET"/>

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search