Skip to content

feat: Implement Kiosk Mode and Runtime Permissions #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<activity android:name=".MainActivity"
android:lockTaskMode="if_whitelisted">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
89 changes: 81 additions & 8 deletions app/src/main/java/imrankst1221/website/in/webview/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package imrankst1221.website.`in`.webview

import android.annotation.SuppressLint
import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.ConnectivityManager
import android.net.NetworkInfo
Expand All @@ -24,6 +26,8 @@ import android.widget.RelativeLayout
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.io.File
import java.io.IOException
import java.io.UnsupportedEncodingException
Expand All @@ -37,6 +41,7 @@ import java.text.SimpleDateFormat
import java.util.*
import javax.crypto.*
import javax.crypto.spec.SecretKeySpec
import kotlin.collections.HashMap

class MainActivity : Activity() {
private lateinit var mContext: Context
Expand Down Expand Up @@ -64,11 +69,22 @@ class MainActivity : Activity() {
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
// Set content to appear behind the system bars so that the
// content doesn't resize when the system bars hide and show.
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// Hide the nav bar and status bar
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN)
setContentView(R.layout.activity_main)

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)

mContext = this

checkAndRequestPermissions()
mWebView = findViewById<View>(R.id.webview) as WebView
prgs = findViewById<View>(R.id.progressBar) as ProgressBar
btnTryAgain = findViewById<View>(R.id.btn_try_again) as Button
Expand Down Expand Up @@ -376,25 +392,82 @@ class MainActivity : Activity() {
}

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack()
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mWebView.canGoBack()) {
mWebView.goBack()
}
// Consume the event to prevent closing the app
return true
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
// Attempt to consume the app switch key event
return true
}
return super.onKeyDown(keyCode, event)
}

if (doubleBackToExitPressedOnce) {
return super.onKeyDown(keyCode, event)
override fun onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack()
}
// If WebView cannot go back, do nothing (consume the event)
}

private fun checkAndRequestPermissions() {
val writePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
val readPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)

this.doubleBackToExitPressedOnce = true
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show()
val listPermissionsNeeded = ArrayList<String>()
if (writePermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (readPermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE)
}

Handler().postDelayed({ doubleBackToExitPressedOnce = false }, 2000)
return true
if (listPermissionsNeeded.isNotEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toTypedArray(), STORAGE_PERMISSION_CODE)
} else {
// Permissions are already granted. You can proceed with operations that need these permissions.
// For example, initialize WebView loading here if it depends on storage, though unlikely for just viewing.
}
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == STORAGE_PERMISSION_CODE) {
val perms: MutableMap<String, Int> = HashMap()
// Initialize the map with permissions
perms[Manifest.permission.WRITE_EXTERNAL_STORAGE] = PackageManager.PERMISSION_GRANTED
perms[Manifest.permission.READ_EXTERNAL_STORAGE] = PackageManager.PERMISSION_GRANTED

// Fill with actual results from user
if (grantResults.isNotEmpty()) {
for (i in permissions.indices) {
perms[permissions[i]] = grantResults[i]
}
// Check for both permissions
if (perms[Manifest.permission.WRITE_EXTERNAL_STORAGE] == PackageManager.PERMISSION_GRANTED &&
perms[Manifest.permission.READ_EXTERNAL_STORAGE] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Storage permissions granted")
// Permissions granted, proceed with app functionality or re-initialize parts that depend on it
// If webview loading was deferred, you might trigger it here or a part of it.
// For now, just logging is fine.
} else {
Log.d(TAG, "Some permissions were denied")
// Permissions were denied. Explain to the user the importance of these permissions
// and potentially offer to request them again or disable functionality.
Toast.makeText(this, "Storage Permissions are required for file uploads and downloads. Please enable them in app settings.", Toast.LENGTH_LONG).show()
// Optionally, you could finish the activity or disable parts of the app
// finish()
}
}
}
}

companion object {
internal var TAG = "---MainActivity"
val INPUT_FILE_REQUEST_CODE = 1
private const val STORAGE_PERMISSION_CODE = 101
val EXTRA_FROM_NOTIFICATION = "EXTRA_FROM_NOTIFICATION"


Expand Down