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)
}
Related
The below code is Working for Android 12 but same not working Android 10 the problem its it showing the run time permission pop up for BLUETOOTH_CONNECT
Here is the below code i have written inside the fragment
class FirstFragment : Fragment() {
private var _binding: FragmentFirstBinding? = null
private var ctx: Context? = null
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
companion object {
private const val BLUETOOTH_PERMISSION_CODE = 100
private const val BLUETOOTH_CONNECT_PERMISSION_CODE = 101
}
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentFirstBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
this.ctx = view.context
//get the devie manifrature name
System.out.println(android.os.Build.MANUFACTURER)
//get the type of the bluetooth device
getBluetoothDeviceType()
checkPermission(
Manifest.permission.BLUETOOTH_CONNECT,
BLUETOOTH_CONNECT_PERMISSION_CODE
)
binding.buttonFirst.setOnClickListener {
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
}
}
private fun requestBluetoothPermission() {
}
private fun getBluetoothDeviceType() {
if (ActivityCompat.checkSelfPermission(
ctx!!,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
if (BluetoothClass.Device.PHONE_CELLULAR == 0x0204) {
System.out.println("permission is granted")
}
} else {
if (BluetoothClass.Device.PHONE_CELLULAR != 0x0204) {
System.out.println("permission is not granted")
}
}
}
private fun checkPermission(permission: String, requestCode: Int) {
if (ContextCompat.checkSelfPermission(
ctx!! as Activity,
permission
) != PackageManager.PERMISSION_GRANTED
) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
println("permission is not required")
} else {
requestPermissions(arrayOf(permission), requestCode)
}
// Requesting the permission
//Fragment.requestPermission.launch(Manifest.permission.CAMERA)
} else {
Toast.makeText(ctx!! as Activity, "Permission already granted", Toast.LENGTH_SHORT)
.show()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == BLUETOOTH_CONNECT_PERMISSION_CODE) {
//permission granted
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (bluetoothAdapter == null) {
// Handle the situation where Bluetooth is not available
} else {
// Get a set of currently paired devices
if (ContextCompat.checkSelfPermission(
ctx!! as Activity,
permissions[0]
) == PackageManager.PERMISSION_GRANTED
) {
val pairedDevices: Set<BluetoothDevice> = bluetoothAdapter.bondedDevices
// If there are paired devices
if (pairedDevices.isNotEmpty()) {
// Loop through paired devices
for (device in pairedDevices) {
// Check if the device is a scanner
if (device.bluetoothClass.majorDeviceClass == BluetoothClass.Device.Major.IMAGING) {
// Device is a scanner
val scannerDevice = device
println("Scanner found: ${scannerDevice.name}")
}
}
} else {
// Handle the situation where there are no paired devices
}
}
Toast.makeText(
ctx!! as Activity,
"Bluetooth Connect Permission Granted",
Toast.LENGTH_SHORT
).show()
}
} else {
Toast.makeText(
ctx!! as Activity,
"Bluetooth Connect Permission Denied",
Toast.LENGTH_SHORT
).show()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
here how below my build.gradle looks like
android {
compileSdk 33
defaultConfig {
applicationId "com.demo"
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
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
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
)
)
**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
When I overriding function onRequestPermissionsResult is not working.
When I remove the override command Android Studio don't complain anymore but the function remains useless...
I'm requesting permissions for ACCES_FINE_LOCATION
The error message is
Modifier 'override' is not applicable to 'local function'
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
val texto = TextView(this)
val ID_REQUISICAO_ACCESS_FINE = 1
setContentView(texto)
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
ID_REQUISICAO_ACCESS_FINE -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the location-related task you need to do.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "permission granted", Toast.LENGTH_LONG).show()
}
} else {
// permission denied, boo! Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show()
}
return
}
}
}
}
}
You have onRequestPermissionsResult as overriden method of class, not local function of onCreate method. So, just close onCreate method before starting onRequestPermissionsResult one:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
val texto = TextView(this)
val ID_REQUISICAO_ACCESS_FINE = 1
setContentView(texto)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
ID_REQUISICAO_ACCESS_FINE -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the location-related task you need to do.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "permission granted", Toast.LENGTH_LONG).show()
} else {
// permission denied, boo! Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show()
}
return
}
}
}
}
}