How to create a website as android app using web view in Kotlin language.
Hi All, Now a days Koltin becomes a more popular language in the world as it makes developers happier and open source forever. Here I am going to explain how to create an android app using a web view. By this, you can see the website in your app and behaves like a native app. The only thing to remember is your website should be built-in mobile responsive.
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…</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
Comments
Post a Comment
Thank you will get back to you soon.