android application exist after location switch on - android

I need to use Location in my application and I check location at every onResume. When location is switched off I try to switch it on with:
val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (!LocationManagerCompat.isLocationEnabled(lm)) {
val intent = Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
return
}
When this activity finished my application exited. I tried startActivityForResult, but it didn't help. How can I return to my application after settings?
thx
Zamek

override fun onResume() {
super.onResume()
checkLocation()
}
private fun checkLocation() {
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(LocationRequest().apply {
interval = 10000
fastestInterval=5000
priority=LocationRequest.PRIORITY_LOW_POWER
})
val settingsClient = LocationServices.getSettingsClient(this)
val task : Task<LocationSettingsResponse> = settingsClient.checkLocationSettings(builder.build())
task.addOnSuccessListener {
model.start()
}
task.addOnFailureListener{
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), REQUEST_LOCATION)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray) {
when(requestCode) {
REQUEST_LOCATION -> locationResult(grantResults)
}
}
private fun locationResult(grantResults: IntArray) {
if (grantResults[0]==PackageManager.PERMISSION_GRANTED) {
val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (!LocationManagerCompat.isLocationEnabled(lm)) {
val intent = Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
return
}
model.start()
return
}
exitApplication()
}
I checked it on a Xiaomi device. Maybe that should be the problem...
thx,
Zamek

Related

Creating custom ActivityResultContract to ask for location permission

I would like to create a custom ActivityResultContract to request both coarse and fine location that has a custom response.
class LocationPermission : ActivityResultContract<Void?, LocationPermissionResult>() {
override fun createIntent(context: Context, input: Array<String>): Intent {
val requestPermissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
return Intent(ActivityResultContracts.RequestMultiplePermissions.ACTION_REQUEST_PERMISSIONS)
.putExtra(ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSIONS, requestPermissions)
}
...
}
Calling that from an activity:
private val reportLocationIntent = registerForActivityResult(LocationPermission()) { result ->
}
...
reportLocationIntent.launch()
However when doing so createIntent is never called. What am I doing wrong?
Your code in question has compilation errors, however this approach seems to work. I don't really know what the "custom response" should be from the question directly, so I've created a class called class LocationPermissionResult(val granted: Boolean) based on your question. It is mostly compiled from RequestMultiplePermissions from ActivityResultContracts.
Tested on API 30 and API 33 emulator, the permission dialog opens and the returned result is correct as well. (Make sure the permissions are added to AndroidManifest.xml)
Here is the source code:
class LocationPermission : ActivityResultContract<Void?, LocationPermissionResult>() {
private val permissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
override fun createIntent(context: Context, input: Void?): Intent {
return Intent(ActivityResultContracts.RequestMultiplePermissions.ACTION_REQUEST_PERMISSIONS).putExtra(
ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSIONS, permissions)
}
override fun getSynchronousResult(context: Context,
input: Void?): SynchronousResult<LocationPermissionResult>? {
val allGranted = permissions.all { permission ->
ContextCompat.checkSelfPermission(
context,
permission
) == PackageManager.PERMISSION_GRANTED
}
return if (allGranted) {
SynchronousResult(LocationPermissionResult(true))
} else null
}
override fun parseResult(resultCode: Int, intent: Intent?): LocationPermissionResult {
if (resultCode != Activity.RESULT_OK) return LocationPermissionResult(false)
if (intent == null) return LocationPermissionResult(false)
val grantResults = intent.getIntArrayExtra(
ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSION_GRANT_RESULTS)
return LocationPermissionResult(grantResults?.all { it == PackageManager.PERMISSION_GRANTED } == true)
}
}
class LocationPermissionResult(val granted: Boolean)
this is my solution to request both coarse and fine location, i hope this will do the job
object Permission {
private const val REQUEST_CODE_PERMISSION: Int = 1
#SuppressLint("ObsoleteSdkInt")
fun isGrantedLocationPermission(context: Context): Boolean {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
true
} else {
context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
}
fun grantLocationPermission(context: Context) {
val permissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
(context as MainActivity).requestPermissions(permissions, REQUEST_CODE_PERMISSION)
}
}
Use it from MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
...
val button = findViewById<Button>(R.id.btnGetLocation)
button.setOnClickListener {
getLocation()
}
}
private fun getLocation() {
//check if permission isnt granted:
if (!Permission.isGrantedLocationPermission(this))
Permission.grantLocationPermission(this)
else {
...
}
}
//Check if user give permission or not:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission granted
} else {
//permission denied
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

Unable to resume activity, java.lang.RuntimeException: Failure delivering result ResultInfo

As you can see this is my code, I built an applications in which I used several permission methods without any problem. In this case, I only have just one activity in order to get the user location, but it gives me an error while it wants to return the request permission result.
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var map: GoogleMap
private lateinit var binding: ActivityMapsBinding
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var geofencingClient: GeofencingClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMapsBinding.inflate(layoutInflater)
setContentView(binding.root)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#SuppressLint("MissingPermission")
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
map.uiSettings.isZoomControlsEnabled = true
if (!isLocationPermissionGranted()) {
val permissions = mutableListOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
permissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
ActivityCompat.requestPermissions(
this,
permissions.toTypedArray(),
LOCATION_REQUEST_CODE
)
} else {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION_REQUEST_CODE
)
}
map.isMyLocationEnabled = true
// Zoom to last known location
fusedLocationClient.lastLocation.addOnSuccessListener {
if (it != null) {
with(map) {
val latLng = LatLng(it.latitude, it.longitude)
moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, CAMERA_ZOOM_LEVEL))
}
} else {
with(map) {
moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(65.01355297927051, 25.464019811372978),
CAMERA_ZOOM_LEVEL
)
)
}
}
}
}
setLongClick(map)
setPoiClick(map)
}
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)?.showInfoWindow()
scheduleJob()
}
}
private fun setLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latlng ->
map.addMarker(
MarkerOptions().position(latlng)
.title("Current location")
)?.showInfoWindow()
map.addCircle(
CircleOptions()
.center(latlng)
.strokeColor(Color.argb(50, 70, 70, 70))
.fillColor(Color.argb(70, 150, 150, 150))
.radius(GEOFENCE_RADIUS.toDouble())
)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, CAMERA_ZOOM_LEVEL))
val database = Firebase.database
val reference = database.getReference("reminders")
val key = reference.push().key
if (key != null) {
val reminder = Reminder(key, latlng.latitude, latlng.longitude)
reference.child(key).setValue(reminder)
}
createGeoFence(latlng, key!!, geofencingClient)
}
}
#SuppressLint("UnspecifiedImmutableFlag", "MissingPermission")
private fun createGeoFence(location: LatLng, key: String, geofencingClient: GeofencingClient) {
val geofence = Geofence.Builder()
.setRequestId(GEOFENCE_ID)
.setCircularRegion(location.latitude, location.longitude, GEOFENCE_RADIUS.toFloat())
.setExpirationDuration(GEOFENCE_EXPIRATION.toLong())
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_DWELL)
.setLoiteringDelay(GEOFENCE_DWELL_DELAY)
.build()
val geofenceRequest = GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence)
.build()
val intent = Intent(this, GeofenceReceiver::class.java)
.putExtra("key", key)
.putExtra("message", "Geofence alert - ${location.latitude}, ${location.longitude}")
val pendingIntent = PendingIntent.getBroadcast(
applicationContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ContextCompat.checkSelfPermission(
applicationContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION
) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.ACCESS_BACKGROUND_LOCATION
),
GEOFENCE_LOCATION_REQUEST_CODE
)
} else {
geofencingClient.addGeofences(geofenceRequest, pendingIntent)
}
} else {
geofencingClient.addGeofences(geofenceRequest, pendingIntent)
}
}
private fun isLocationPermissionGranted() : Boolean {
return ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(
applicationContext, Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED
}
#SuppressLint("MissingPermission")
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == GEOFENCE_LOCATION_REQUEST_CODE) {
if (permissions.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(
this,
"This application needs background location to work on Android 10 and higher",
Toast.LENGTH_SHORT
).show()
}
}
if (requestCode == LOCATION_REQUEST_CODE) {
if (
grantResults.isNotEmpty() && (
grantResults[0] == PackageManager.PERMISSION_GRANTED &&
grantResults[1] == PackageManager.PERMISSION_GRANTED)
) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
map.isMyLocationEnabled = true
onMapReady(map)
} else {
Toast.makeText(
this,
"The app needs location permission to function",
Toast.LENGTH_LONG
).show()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (grantResults.isNotEmpty() && grantResults[2] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(
this,
"This application needs background location to work on Android 10 and higher",
Toast.LENGTH_LONG
).show()
}
}
}
}
companion object {
fun removeGeofences(context: Context, triggeringGeofenceList: MutableList<Geofence>) {
val geofenceIdList = mutableListOf<String>()
for (entry in triggeringGeofenceList) {
geofenceIdList.add(entry.requestId)
}
LocationServices.getGeofencingClient(context).removeGeofences(geofenceIdList)
}
fun showNotification(context: Context?, message: String) {
val CHANNEL_ID = "REMINDER_NOTIFICATION_CHANNEL"
var notificationId = 1589
notificationId += Random(notificationId).nextInt(1, 30)
val notificationBuilder = NotificationCompat.Builder(context!!.applicationContext, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_alarm)
.setContentTitle(context.getString(R.string.app_name))
.setContentText(message)
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(message)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
context.getString(R.string.app_name),
NotificationManager.IMPORTANCE_DEFAULT
).apply {
description = context.getString(R.string.app_name)
}
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(notificationId, notificationBuilder.build())
}
}
#SuppressLint("MissingPermission")
private fun scheduleJob() {
val componentName = ComponentName(this, ReminderJobService::class.java)
val info = JobInfo.Builder(321, componentName)
.setRequiresCharging(false)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(15 * 60 * 1000)
.build()
val scheduler = getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler
val resultCode = scheduler.schedule(info)
if (resultCode == JobScheduler.RESULT_SUCCESS) {
Log.d(TAG, "Job scheduled")
} else {
Log.d(TAG, "Job scheduling failed")
scheduleJob()
}
}
private fun cancelJob() {
val scheduler = getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler
scheduler.cancel(321)
Log.d(TAG, "Job cancelled")
}
private fun permissionGrant(){
val permissions = mutableListOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
permissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
ActivityCompat.requestPermissions(
this,
permissions.toTypedArray(),
LOCATION_REQUEST_CODE
)
}
}
here is the error message:
java.lang.RuntimeException: Unable to resume activity {com.adit.bangkit.plagroid/com.adit.bangkit.plagroid.ui.activities.MapsActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=#android:requestPermissions:, request=123, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.adit.bangkit.plagroid/com.adit.bangkit.plagroid.ui.activities.MapsActivity}: kotlin.UninitializedPropertyAccessException: lateinit property map has not been initialized
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3828)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3860)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6810)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=#android:requestPermissions:, request=123, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.adit.bangkit.plagroid/com.adit.bangkit.plagroid.ui.activities.MapsActivity}: kotlin.UninitializedPropertyAccessException: lateinit property map has not been initialized
at android.app.ActivityThread.deliverResults(ActivityThread.java:4423)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3817)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3860) 
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:51) 
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:201) 
at android.app.ActivityThread.main(ActivityThread.java:6810) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873) 
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property map has not been initialized
at com.adit.bangkit.plagroid.ui.activities.MapsActivity.onRequestPermissionsResult(MapsActivity.kt:257)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:7749)
at android.app.Activity.dispatchActivityResult(Activity.java:7594)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4416)
I tried to find a good solution but unfortunately I couldn't fine a right one. why it's happening and how should I solve it? Thanks in advance.

How to call OnRequestPermissionResult method from Adapter

I want to make a phone call using the number displayed on the view in the recycler view.
override fun onBindViewHolder(holder: MyViewholder, position: Int) {
val currentItem = userlist[position]
holder.txtFirstName.text = currentItem.firstName
holder.txtLastName.text = currentItem.lastName
holder.txtAge.text = currentItem.phonenumber.toString()
num = currentItem.phonenumber.toString()
holder.call.setOnClickListener {
val number: String = currentItem.phonenumber.toString()
if (ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.CALL_PHONE
) != PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
context as Activity,
arrayOf(android.Manifest.permission.CALL_PHONE),
REQUEST_CALL
)
} else {
val dial = "tel:$number"
val intent = Intent(Intent.ACTION_CALL, Uri.parse(dial))
context.startActivity(intent)
}
}
}
I am not able to override OnResquestPermissionResult() inside the adapter.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_CALL) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val number: String = num
if (ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.CALL_PHONE
) != PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
context as Activity, arrayOf(android.Manifest.permission.CALL_PHONE),
REQUEST_CALL
)
} else {
onRequestPermissionsResult(requestCode,permissions,grantResults)
val dial = "tel:$number"
val intent = Intent(Intent.ACTION_CALL, Uri.parse(dial))
context.startActivity(intent)
}
} else {
Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
}
if I try to override OnResquestPermissionResult() inside the activity I am not able to pass the current phone number from the view.
I removed this whole code:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_CALL) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val number: String = num
if (ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.CALL_PHONE
) != PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
context as Activity, arrayOf(android.Manifest.permission.CALL_PHONE),
REQUEST_CALL
)
} else {
onRequestPermissionsResult(requestCode,permissions,grantResults)
val dial = "tel:$number"
val intent = Intent(Intent.ACTION_CALL, Uri.parse(dial))
context.startActivity(intent)
}
} else {
Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
}
and everything is working fine.
Dont do that, return your click call back into your activity or fragment, then do your request permission like this
Request permission in android
or this, new way of get permission
Request permission in android with activity result api

Kotlin Request location permission at runtime problem

import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.gms.location.*
#RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
class DeviceScanActivity : AppCompatActivity() {
//Getting BluetoothAdapter from BluetoothManager
private fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
private var fusedLocationProvider: FusedLocationProviderClient? = null
private val locationRequest: LocationRequest = LocationRequest.create().apply {
interval = 30
fastestInterval = 10
priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
maxWaitTime= 60
}
private var locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val locationList = locationResult.locations
if (locationList.isNotEmpty()) {
val location = locationList.last()
Toast.makeText(this#DeviceScanActivity, "Got Location: " + location.toString(), Toast.LENGTH_LONG).show()
}
}
}
private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) {
val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
bluetoothManager.adapter
}
companion object {
const val TAG: String = "Log"
private const val MY_PERMISSIONS_REQUEST_LOCATION = 99
}
private val BluetoothAdapter.isDisabled: Boolean get() = !isEnabled
private val REQUEST_ENABLE_BT = 1000
//On memory
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "DeviceScanActivity()")
fusedLocationProvider = LocationServices.getFusedLocationProviderClient(this)
checkLocationPermission()
packageManager.takeIf {
it.missingSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
}?.also {
Toast.makeText(this, "R.string.ble_not_supported", Toast.LENGTH_SHORT).show()
finish()
}
bluetoothAdapter?.takeIf { it.isDisabled }?.apply {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
}
finish()
}
override fun onResume() {
super.onResume()
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
fusedLocationProvider?.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
}
}
override fun onPause() {
super.onPause()
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
fusedLocationProvider?.removeLocationUpdates(locationCallback)
}
}
private fun checkLocationPermission() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
if(ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
) {
AlertDialog.Builder(this)
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton(
"OK"
) { _, _ ->
//Prompt the user once explanation has been shown
requestLocationPermission()
}
.create()
.show()
} else {
requestLocationPermission()
}
}
}
private fun requestLocationPermission() {
Log.d(TAG, "requestLocationPermission()")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
),
MY_PERMISSIONS_REQUEST_LOCATION
)
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
MY_PERMISSIONS_REQUEST_LOCATION
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
Log.d(TAG, "result()")
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
MY_PERMISSIONS_REQUEST_LOCATION -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
fusedLocationProvider?.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
} else {
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show()
}
return
}
}
}
}
To use BLE observing and advertising, I have granted permission at Manifests and also trying to request at runtime manually.
However, my code doesn't look like it is calling onRequestPermissionResult, as it doesn't show "result()" on LogCat, and the advertising/observing is not working properly. What is the problem of my code?

Unable to update the UI using Broadcast Receiver(Kotlin)

I wanted to update the UI of My MainActivity when the bluetooth is On/Off
MainActivity
private val broadcastReceiver = Broadcast()
open var bluetooth : ImageView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
registerReceiver(broadcastReceiver, filter)
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
bluetooth = findViewById(R.id.image_bluetooth)
val bluetoothName = findViewById<TextView>(R.id.text_bluetooth_name)
bluetoothName.text = bluetoothAdapter.name
bluetooth?.setOnClickListener {
if (!bluetoothAdapter.isEnabled) {
val turnOn = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(turnOn, 0)
} else {
bluetoothAdapter.disable()
}
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(broadcastReceiver)
}
fun enableBluetooth()
{
bluetooth?.setImageDrawable(ContextCompat.getDrawable(this,R.drawable.ic_bluetooth_enable_48dp))
}
fun disableBluetooth()
{
bluetooth?.setImageDrawable(ContextCompat.getDrawable(this,R.drawable.ic_bluetooth_disable_48dp))
}
BroadcastReceiver
class Broadcast : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent?.action
val mainActivity = MainActivity()
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
when (intent?.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
BluetoothAdapter.STATE_OFF -> {
Toast.makeText(context, "Bluetooth Turned OFF", Toast.LENGTH_LONG).show()
mainActivity.disableBluetooth()
}
BluetoothAdapter.STATE_ON -> {
Toast.makeText(context, "Bluetooth Turned ON", Toast.LENGTH_LONG).show()
mainActivity.enableBluetooth()
}
}
}
}
}
After the onReceive call in BroadcastReceiver, in enableBluetooth and disableBluetooth method bluetooth value return null.Can any one help to over come the process?Thanks in advance
For this case, use On onActivityResult Method to update the UI
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 0 && bluetoothAdapter!!.isEnabled) {
Toast.makeText(this, "Bluetooth Turned ON", Toast.LENGTH_LONG).show()
image_bluetooth?.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_bluetooth_enable_48dp))
}
}

Categories

Resources