Kotlin Request location permission at runtime problem - android

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?

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.

The android application crash

WhoDoctor was helped me on the Previous code
Now, the android application crashed when during running on my phone
and This is the error log
First problem is after I scanned the QRcode with camera it cannot show at the QRcode's result into the tvResult
Second problem is after I selected a QRcode image from the storage, then tap confirmed, it crash
Here below I think are the issue
Type mismatch: inferred type is Uri? but Uri was expected
galleryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), object :ActivityResultCallback<ActivityResult>{
override fun onActivityResult(result: ActivityResult?) {
val data=result?.data
inputImage = InputImage.fromFilePath(requireContext(), data?.data)
processQr()
}
})
Redundant SAM-constructor
binding.btnScanBarcode.setOnClickListener{
val options=arrayOf("camera","gallery")
val builder=AlertDialog.Builder(requireContext())
builder.setTitle("Pick a option")
builder.setItems(options, DialogInterface.OnClickListener { dialog, which ->
if(which==0){
val cameraIntent=Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraLauncher.launch(cameraIntent)
}else{
val storageIntent=Intent()
storageIntent.setType("image/*")
storageIntent.setAction(Intent.ACTION_GET_CONTENT)
galleryLauncher.launch(storageIntent)
}
})
builder.show()
}
'onRequestPermissionsResult(Int, Array<(out) String!>, IntArray): Unit' is deprecated. Deprecated in Java
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode==CAMERA_PERMISSION_CODE){
if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
checkPermission(
Manifest.permission.READ_EXTERNAL_STORAGE,
READ_STORAGE_PERMISSION_CODE)
}else{
Toast.makeText(requireContext(), "Camera Permission Denied", Toast.LENGTH_SHORT).show()
}
}else if(requestCode==READ_STORAGE_PERMISSION_CODE){
if((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)){
checkPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
WRITE_STORAGE_PERMISSION_CODE)
}else{
Toast.makeText(requireContext(), "Storage Permission Denied", Toast.LENGTH_SHORT).show()
}
}else if(requestCode==WRITE_STORAGE_PERMISSION_CODE) {
if (!(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Toast.makeText(requireContext(), "Storage Permission Denied", Toast.LENGTH_SHORT).show()
}
}
}
onRequestPermissionsResult() method is deprecated in androidx.fragment.app.Fragment.
So you use registerForActivityResult() method instead onRequestPermissionsResult().
Following is kotlin code. .
val permReqLuncher = registerForActivityResult(ActivityResultContracts.RequestPermission()){
if (it) {
// Good pass
} else {
// Failed pass
}
}
How to get a permission request in new ActivityResult API (1.3.0-alpha05)?
private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
new ActivityResultCallback<Boolean>() {
#Override
public void onActivityResult(Boolean result) {
if(result) {
Log.e(TAG, "onActivityResult: PERMISSION GRANTED");
} else {
Log.e(TAG, "onActivityResult: PERMISSION DENIED");
}
}
});
// Launch the permission window -- this is in onCreateView()
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPermissionResult.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
});
You can request multiple permissions.
val requestMultiplePermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
Log.e("DEBUG", "${it.key} = ${it.value}")
}
}
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.READ_CONTACTS,
Manifest.permission.ACCESS_FINE_LOCATION
)
)

Multiply Function for Activity in Android Studio

**Halo I need a little help, so you can see there are 2 button create but I run the app by emulator it only work for the button create for asking the permission , but its not going to Activity 2,any can suggest for 2nd button to work? Am I need using override fun?
**
package com.example.preludeprototpe
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.core.app.ActivityCompat
import kotlinx.android.synthetic.main.activity1.*
class Activity1 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity1)
// Its a buutton for go to the Activity 2,but its not working
btncreate.setOnClickListener {
Intent(this, Activity2::class.java).also {
startActivity(it)
}
}
// function for asking permission but its the only one worked
btncreate.setOnClickListener {
requestpermisson()
}
//button for go to Activity 3
btnlogin.setOnClickListener {
Intent(this, Activity3::class.java).also {
startActivity(it)
}
}
}
// function for permission
private fun writeExternalStorage() =
ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
private fun permissionInternet() =
ActivityCompat.checkSelfPermission(this, Manifest.permission.INTERNET) ==
PackageManager.PERMISSION_GRANTED
private fun permissionCamera() =
ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED
private fun permissionExternal() =
ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED
private fun requestpermisson() {
val permissionToRequest = mutableListOf<String>()
if (!writeExternalStorage()) {
permissionToRequest.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (!permissionInternet()) {
permissionToRequest.add(Manifest.permission.INTERNET)
}
if (!permissionCamera()) {
permissionToRequest.add(Manifest.permission.CAMERA)
}
if (!permissionExternal()) {
permissionToRequest.add(Manifest.permission.CAMERA)
}
if(permissionToRequest.isNotEmpty()){
ActivityCompat.requestPermissions(this,permissionToRequest.toTypedArray(),0)
}
}
// fun for permission
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode == 0 && grantResults.isNotEmpty()) {
for(i in grantResults.indices) {
if(grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.d("PermissionRequest","${permissions[i]} granted")
}
}
}
}
}
Tried this
// Its a buutton for go to the Activity 2,but its not working
btncreate.setOnClickListener {
requestpermisson()
val intent = Intent(this, Activity2::class.java)
startActivity(intent)
}
//button for go to Activity 3
btnlogin.setOnClickListener {
val intent = Intent(this, Activity3::class.java)
startActivity(intent)
}
}
Instead of create new
btncreate
you could merge
requestpermission()
in first one

Can't pass in variable to requestPermissions()

My activity RequiresLocation is to request permission to location services.
Here's the code:
import android.content.pm.PackageManager
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.widget.Button
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_requires_location.*
import java.util.jar.Manifest
class RequiresLocation : AppCompatActivity() {
val requestCode: Int = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_requires_location)
turnOnLocationButton.setOnClickListener {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission has already been granted", Toast.LENGTH_SHORT).show()
}
else {
requestLocationPermission()
}
}
}
}
private fun requestLocationPermission(): {
ActivityCompat.requestPermissions(
RequiresLocation.class,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
requestCode) // coming up in red
}
however the requestcode is coming up in red on Android Studio as unresolved reference. How come I can't pass it in? - is it because it's a private variable?
I'm following the official android tutorial for requestPermissions()
Use this#RequiresLocation instead of RequiresLocation.class
Try this
ActivityCompat.requestPermissions(
this#RequiresLocation,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
requestCode)
Or
private fun requestLocationPermission() {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
requestCode) // coming up in red
}
UPDATE
class RequiresLocation : AppCompatActivity() {
val requestCode: Int = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_requires_location)
turnOnLocationButton.setOnClickListener {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission has already been granted", Toast.LENGTH_SHORT).show()
}
else {
requestLocationPermission()
}
}
}
private fun requestLocationPermission() {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
requestCode) // coming up in red
}
}

Categories

Resources