31

I am new to both Android and Kotlin.

Anyone can help me to load an URL in a webView?

I just want to load the URL and view the webpage when the app is open.

JorgeAmVF
  • 1,660
  • 3
  • 21
  • 32
Ayan Chakraborty
  • 613
  • 1
  • 8
  • 13

5 Answers5

73

1.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.kotlinwebview.MainActivity">


<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="MissingConstraints"
    tools:layout_editor_absoluteX="8dp"
    tools:layout_editor_absoluteY="8dp" />
    
</android.support.constraint.ConstraintLayout>

2.MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        webView = findViewById(R.id.webview)
        webView.settings.setJavaScriptEnabled(true)

        webView.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                view?.loadUrl(url)
                return true
            }
        }
        webView.loadUrl("https://www.google.co.in/")
    }
}
Ramesh sambu
  • 3,577
  • 2
  • 24
  • 39
10

Here is the complete working code to load a website in android webView. Just create a new project from the android studio and use the following code to load the web view. Just change the URL you want to load it in the web view.

  • It will load a website in the webview
  • It will check internet connection availability
  • If there is no internet ask the user to enable WiFi from the snack bar message
  • Loads the progress until website loads
  • Handles the error if something went wrong while loading website
  • Handles the back button press cases
  • Handles exit from the app confirmation with toast

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/infoTV"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt:

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.util.Log
import android.view.KeyEvent
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

    private var progress: Progress? = null
    private var isLoaded: Boolean = false
    private var doubleBackToExitPressedOnce = false
    private var webURL = "https://www.geeklabs.co.in/" // Change it with your URL

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        webView.settings.javaScriptEnabled = true
        if (!isOnline()) {
            showToast(getString(R.string.no_internet))
            infoTV.text = getString(R.string.no_internet)
            showNoNetSnackBar()
            return
        }
    }

    override fun onResume() {
        if (isOnline() && !isLoaded) loadWebView()
        super.onResume()
    }

    private fun loadWebView() {
        infoTV.text = ""
        webView.loadUrl(webURL)
        webView.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                val url = request?.url.toString()
                view?.loadUrl(url)
                return super.shouldOverrideUrlLoading(view, request)
            }

            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                setProgressDialogVisibility(true)
                super.onPageStarted(view, url, favicon)
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                isLoaded = true
                setProgressDialogVisibility(false)
                super.onPageFinished(view, url)
            }

            override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
                isLoaded = false
                val errorMessage = "Got Error! $error"
                showToast(errorMessage)
                infoTV.text = errorMessage
                setProgressDialogVisibility(false)
                super.onReceivedError(view, request, error)
            }
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (event.action == KeyEvent.ACTION_DOWN) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (webView.canGoBack()) {
                    webView.goBack()
                } else {
                    showToastToExit()
                }
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    private fun showToastToExit() {
        when {
            doubleBackToExitPressedOnce -> {
                onBackPressed()
            }
            else -> {
                doubleBackToExitPressedOnce = true
                showToast(getString(R.string.back_again_to_exit))
                Handler(Looper.myLooper()!!).postDelayed({ doubleBackToExitPressedOnce = false }, 2000)
            }
        }
    }

    private fun setProgressDialogVisibility(visible: Boolean) {
        if (visible) progress = Progress(this, R.string.please_wait, cancelable = true)
        progress?.apply { if (visible) show() else dismiss() }
    }

    private fun isOnline(): Boolean {
        val connectivityManager =
                getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val capabilities =
                connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (capabilities != null) {
            when {
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR")
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI")
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET")
                    return true
                }
            }
        }
        return false
    }

    private fun showToast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }

    private fun showNoNetSnackBar() {
        val snack = Snackbar.make(rootView, getString(R.string.no_internet), Snackbar.LENGTH_INDEFINITE)
        snack.setAction(getString(R.string.settings)) {
            startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
        }
        snack.show()
    }
}

Progress.kt:

import android.app.AlertDialog
import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.annotation.StringRes

class Progress constructor(
    context: Context?,
    @StringRes private val titleRes: Int,
    cancelable: Boolean = false
) {

    private var view: View? = null
    private var builder: AlertDialog.Builder
    private var dialog: Dialog

    init {
        view = LayoutInflater.from(context).inflate(R.layout.progress, null)
        view?.findViewById<TextView>(R.id.text)?.setText(titleRes)
        builder = AlertDialog.Builder(context)
        builder.setView(view)
        dialog = builder.create()
        dialog.setCancelable(cancelable)
    }

    fun setProgressMessage(@StringRes titleRes: Int) {
        view?.findViewById<TextView>(R.id.text)?.setText(titleRes)
    }

    fun show() {
        dialog.show()
    }

    fun dismiss() {
        if (dialog.isShowing) {
            dialog.dismiss()
        }
    }

    fun setProgressDialogVisibility(isVisible: Boolean) {

    }
}

pregress.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical">

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Subtitle"
        tools:text="Loading" />

</LinearLayout>

Manifest.xml:

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

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

    <application
        android:allowBackup="true"
        android:fullBackupContent="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

strings.xml:

<resources>
    <string name="app_name">WebViewKotlin</string>
    <string name="please_wait">Please wait&#8230;</string>
    <string name="no_internet">No internet connection!</string>
    <string name="settings">Settings</string>
    <string name="back_again_to_exit">Please click BACK again to exit</string>
</resources>

build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.0"

    defaultConfig {
        applicationId "com.geeklabs.webviewkotlin"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

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

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.1.0'
    testImplementation 'junit:junit:4.13'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

}

Here is the complete working code in Git hub. Click here to navigate to Git Hub

Shailendra Madda
  • 20,649
  • 15
  • 100
  • 138
8

Add this to your activity:

@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_webview)

    val mWebView = findViewById<WebView>(R.id.webview)

    val webSettings = mWebView.settings
    webSettings.javaScriptEnabled = true
    mWebView.loadUrl(getString(R.string.website_url))
    mWebView.webViewClient = HelloWebViewClient()
    WebView.setWebContentsDebuggingEnabled(false)

}

And add the following to the HelloWebViewClient() class in order to allow back button navigation and to outbound external links:

    override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
        if (Uri.parse(url).host == getString(R.string.website_domain)) {
            return false
        }
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
        startActivity(intent)
        return true
    }

    override fun onPageFinished(view: WebView, url: String) {
        // TODO Auto-generated method stub
        super.onPageFinished(view, url)
    }

}

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
        webview.goBack()
        return true
    }
    return super.onKeyDown(keyCode, event)
}

Add strings defining website_domain (https://stackoverflow.com/) and website_host (stackoverflow.com).

If you're dealing with difficulties in order to achieve what you're trying, try this full sample and just follow the instructions so as you just need to edit the URL and the clean domain name of your website.

JorgeAmVF
  • 1,660
  • 3
  • 21
  • 32
  • How to enable camera access? – Tiago May 14 '19 at 19:39
  • You'd need to request permission in real-time, I guess. Have you tried it, @Tiago? – JorgeAmVF May 15 '19 at 03:16
  • Does it work on the chrome browser and it doesn't work just in the `WebView`? – JorgeAmVF May 15 '19 at 05:14
  • Exactly. It works in the browser, but it does not work in webview. – Tiago May 15 '19 at 12:11
  • 1
    Look, I'm not sure if the following solutions will be enough, but here are at least a couple of possible workarounds: [one](https://stackoverflow.com/a/48271743/6398434) and [another](https://stackoverflow.com/a/49403612/6398434). However, I'm not sure if they work because I've never tested to implement permissions on a `WebView`. Hope it helps you somehow anyway! – JorgeAmVF May 15 '19 at 14:51
  • 2
    Also, @Tiago, I'd suggest you to directly ask the question explaining your issue and showing pieces of your actual code so others could help you more precisely. – JorgeAmVF May 15 '19 at 14:53
4

Use Android Kotlin Extension plugin. If you are using Android Studio 3.0 and above, don't worry about that. That already installed on your Project.

Use the id of WebView in layout and call loadUrl() method.

Android WebView Example - Kotlin & Java

enter image description here

Here id of WebView : webview

webview.loadUrl("https://www.androidride.com")

don't forget to add

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

If your third-party browser open with any URL that loaded in WebView, then provide WebViewClient.

webview.webViewClient = WebViewClient()

If you want to play youtube videos in your WebView, then you must enable JavaScript in WebView.

enter image description here

webview.settings.javaScriptEnabled = true

If you are a beginner in Android app development, then this tutorial will help you to clear almost all your doubts about WebView.

click here

Vijay Ram
  • 385
  • 5
  • 12
Thomas Daniel
  • 257
  • 4
  • 7
0

The question is so simple, but most of the answer is too complicated. Honestly I tried several method here but did not work for me. So here is what I did (and worked)

  1. Use RelativeLayout instead of androidx.constraintlayout.widget.ConstraintLayout in app>res>layout>activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       tools:context=".MainActivity">
    
     <WebView
         android:id="@+id/webview"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
    
     </RelativeLayout>
    
  2. Create a new Java Class named MainActivity (there is no need to type the .java, android studio will do it for you) in app>java>com.whateveryourcompanynameis.whateveryourappnameis>MainActivity.java

     package com.whateveryourcompanynameis.whateveryourappnameis;
    
     import androidx.appcompat.app.AppCompatActivity;
     import android.os.Bundle;
     import android.webkit.WebView;
     import android.webkit.WebViewClient;
    
     public class MainActivity extends AppCompatActivity {
         private WebView webView;
    
         @Override
         protected void onCreate(Bundle savedinstanceState) {
             super.onCreate(savedinstanceState);
             setContentView(R.layout.activity_main);
             webView=(WebView) findViewById(R.id.webview);
             webView.setWebViewClient(new WebViewClient());
             webView.loadUrl("https://google.com"); //you can change your website here,just remember to use http(s)://
         }
         @Override
         public void onBackPressed() {
             if (webView.canGoBack()) {
                 webView.goBack();
             } else {
                 super.onBackPressed();
             }
         }
     }
    
  3. Last but not least, make the internet accessible by using this code in app>manifest>AndroidManifest.xml

     <?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.apex.webtest">
    
         <uses-permission android:name="android.permission.INTERNET"/>
    
    
    
    <application
         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.Webtest"
         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>
    

This code will run the website when you open the app (in this case google) and after clicking on some link, pressing back button on your android will move u back to the page before, until there is no page left then the app will close. This allows running the web-based interface on android without the need to know so much about android studio.

Ian Campbell
  • 23,484
  • 14
  • 36
  • 57
Apex
  • 36
  • 1
  • 5