From 5d431f30fb45f0db8c829669bfe701fb4fe50f62 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Mon, 11 Nov 2024 19:59:23 +0300 Subject: [PATCH 1/3] show rationale for permissions --- .../dialogfragments/WifiDialogFragment.kt | 42 +++++++------- .../bottomsheetdialogs/WifiBottomSheet.kt | 58 ++++++++++++++++++- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/app/src/main/kotlin/io/treehouses/remote/fragments/dialogfragments/WifiDialogFragment.kt b/app/src/main/kotlin/io/treehouses/remote/fragments/dialogfragments/WifiDialogFragment.kt index 9819d6c97..7ab991ca1 100644 --- a/app/src/main/kotlin/io/treehouses/remote/fragments/dialogfragments/WifiDialogFragment.kt +++ b/app/src/main/kotlin/io/treehouses/remote/fragments/dialogfragments/WifiDialogFragment.kt @@ -19,19 +19,19 @@ import java.util.* class WifiDialogFragment : DialogFragment() { - private var mDialog: AlertDialog? = null + private lateinit var mDialog: AlertDialog private var wifiManager: WifiManager? = null private val wifiList = ArrayList() private var mContext: Context? = null private var SSID: String? = null - private var mView: View? = null + private lateinit var mView: View private var firstScan = true private var progressBar: ProgressBar? = null override fun onAttach(context: Context) { super.onAttach(context) val inflater = requireActivity().layoutInflater mView = inflater.inflate(R.layout.dialog_listview, null) - progressBar = mView!!.findViewById(R.id.progressBar) + progressBar = mView.findViewById(R.id.progressBar) } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { @@ -40,20 +40,20 @@ class WifiDialogFragment : DialogFragment() { mDialog = DialogUtils.createAlertDialog(context, mView, R.drawable.dialog_icon) .setTitle("Choose a network: ") .setNegativeButton("Cancel") { dialog: DialogInterface, _: Int -> dialog.dismiss() }.create() - mDialog!!.window!!.setBackgroundDrawableResource(android.R.color.transparent) - return mDialog!! + mDialog.window?.setBackgroundDrawableResource(android.R.color.transparent) + return mDialog } private fun setAdapter() { - val listView = mView!!.findViewById(R.id.listView) - val arrayAdapter = ArrayAdapter(mContext!!, R.layout.simple_list_item, wifiList) + val listView = mView.findViewById(R.id.listView) + val arrayAdapter = ArrayAdapter(requireContext(), R.layout.simple_list_item, wifiList) listView.adapter = arrayAdapter listView.onItemClickListener = OnItemClickListener { _: AdapterView<*>?, _: View?, position: Int, _: Long -> SSID = wifiList[position] if (targetFragment != null) { val intent = Intent() - intent.putExtra(WIFI_SSID_KEY, SSID!!.trim { it <= ' ' }) - targetFragment!!.onActivityResult(targetRequestCode, Activity.RESULT_OK, intent) + intent.putExtra(WIFI_SSID_KEY, SSID?.trim { it <= ' ' }) + targetFragment?.onActivityResult(targetRequestCode, Activity.RESULT_OK, intent) wifiList.clear() dismiss() } @@ -61,15 +61,15 @@ class WifiDialogFragment : DialogFragment() { } private fun setupWifi() { - wifiManager = mContext!!.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + wifiManager = mContext?.applicationContext?.getSystemService(Context.WIFI_SERVICE) as WifiManager if (wifiManager == null) return - wifiManager!!.isWifiEnabled = true + wifiManager?.isWifiEnabled = true val wifiScanReceiver = wifiBroadcastReceiver() val intentFilter = IntentFilter() intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) - mContext!!.registerReceiver(wifiScanReceiver, intentFilter) - val success = wifiManager!!.startScan() - if (!success) { + mContext?.registerReceiver(wifiScanReceiver, intentFilter) + val success = wifiManager?.startScan() + if (success == false) { scanFailure() } } @@ -88,10 +88,10 @@ class WifiDialogFragment : DialogFragment() { } } - private fun getSSIDs(results: List) { + private fun getSSIDs(results: List?) { wifiList.clear() // converts Object list to array - val `object`: Array = results.toTypedArray() + val `object`: Array? = results?.toTypedArray() val temp = `object`.contentToString() val resultArray = temp.split(",".toRegex()).toTypedArray() @@ -109,24 +109,24 @@ class WifiDialogFragment : DialogFragment() { private fun addToList(ssid: String) { if (ssid.trim { it <= ' ' }.isNotEmpty()) { wifiList.add(ssid) - progressBar!!.visibility = View.INVISIBLE + progressBar?.visibility = View.INVISIBLE } } private fun scanSuccess() { - val results = wifiManager!!.scanResults + val results = wifiManager?.scanResults getSSIDs(results) setAdapter() } private fun scanFailure() { // handle failure: new scan did not succeed - val results = wifiManager!!.scanResults + val results = wifiManager?.scanResults getSSIDs(results) - if (results.size >= 1 && firstScan) { + if (results?.isNotEmpty() == true && firstScan) { Toast.makeText(context, "Scan unsuccessful. These are old results", Toast.LENGTH_LONG).show() setAdapter() - } else if (results.size < 1 && firstScan) { + } else if (results?.isEmpty() == true && firstScan) { ifResultListEmpty() } firstScan = false diff --git a/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt b/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt index 9b8657c51..1b3eab5bb 100644 --- a/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt +++ b/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt @@ -1,11 +1,19 @@ package io.treehouses.remote.ui.network.bottomsheetdialogs +import android.Manifest import android.app.Activity +import android.content.Context.LOCATION_SERVICE import android.content.Intent +import android.content.pm.PackageManager +import android.location.LocationManager import android.os.Bundle +import android.provider.Settings import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast +import androidx.appcompat.app.AlertDialog +import androidx.core.app.ActivityCompat import androidx.fragment.app.viewModels import io.treehouses.remote.Constants import io.treehouses.remote.bases.BaseBottomSheetDialog @@ -56,6 +64,54 @@ open class WifiBottomSheet : BaseBottomSheetDialog() { bind.checkBoxEnterprise.setOnCheckedChangeListener { _, isChecked -> viewModel.hiddenOrEnterprise(isChecked) } - bind.btnWifiSearch.setOnClickListener { openWifiDialog(this@WifiBottomSheet, context) } + bind.btnWifiSearch.setOnClickListener { + val locationManager = context?.getSystemService(LOCATION_SERVICE) as LocationManager + + if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + + if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) { + showLocationPermissionRationale() + } else { + requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE) + } + } else { + if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) + context?.startActivity(intent) + } else { + openWifiDialog(this@WifiBottomSheet, context) + } + } + } + } + + private fun showLocationPermissionRationale() { + AlertDialog.Builder(requireContext()) + .setTitle("Location Permission Needed") + .setMessage("This app requires location access to enable WiFi search functionality. Please grant location permission to continue.") + .setPositiveButton("OK") { _, _ -> + requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE) + } + .setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + Toast.makeText(context, "Location permission is required to enable WiFi search", Toast.LENGTH_SHORT).show() + } + .show() + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { + if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) { + bind.btnWifiSearch.performClick() + } else { + Toast.makeText(context, "Location permission is required to enable WiFi search", Toast.LENGTH_SHORT).show() + } + } + } + + companion object { + private const val LOCATION_PERMISSION_REQUEST_CODE = 1001 } } From ac5f73f70b069b6958202272188793874d10d1f2 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Mon, 25 Nov 2024 21:32:01 +0300 Subject: [PATCH 2/3] darkmode theme for dialog --- .../ui/network/bottomsheetdialogs/WifiBottomSheet.kt | 7 ++++--- app/src/main/res/values-night/styles.xml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt b/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt index 1b3eab5bb..5927d736f 100644 --- a/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt +++ b/app/src/main/kotlin/io/treehouses/remote/ui/network/bottomsheetdialogs/WifiBottomSheet.kt @@ -2,17 +2,19 @@ package io.treehouses.remote.ui.network.bottomsheetdialogs import android.Manifest import android.app.Activity +import android.app.AlertDialog import android.content.Context.LOCATION_SERVICE import android.content.Intent import android.content.pm.PackageManager import android.location.LocationManager import android.os.Bundle import android.provider.Settings +import android.view.ContextThemeWrapper import android.view.LayoutInflater import android.view.View +import io.treehouses.remote.R import android.view.ViewGroup import android.widget.Toast -import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityCompat import androidx.fragment.app.viewModels import io.treehouses.remote.Constants @@ -87,7 +89,7 @@ open class WifiBottomSheet : BaseBottomSheetDialog() { } private fun showLocationPermissionRationale() { - AlertDialog.Builder(requireContext()) + AlertDialog.Builder(ContextThemeWrapper(context, R.style.CustomAlertDialogStyle)) .setTitle("Location Permission Needed") .setMessage("This app requires location access to enable WiFi search functionality. Please grant location permission to continue.") .setPositiveButton("OK") { _, _ -> @@ -95,7 +97,6 @@ open class WifiBottomSheet : BaseBottomSheetDialog() { } .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() - Toast.makeText(context, "Location permission is required to enable WiFi search", Toast.LENGTH_SHORT).show() } .show() } diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index 05a9c3768..e5af1ebfe 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -56,7 +56,7 @@ @color/daynight_textColor -