`I want to show a permission prompt to get location permission from user.
But my prompt is not showing up in the app.
I have tried many codes from different sites but nothing worked.
Here is my code....
`private fun requestpermission(){
islocationpermissiongranted = ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
backgroundlocationpermission = ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_BACKGROUND_LOCATION
) == PackageManager.PERMISSION_GRANTED
val permissionRequest : MutableList<String> = ArrayList()
if(!islocationpermissiongranted){
permissionRequest.add(Manifest.permission.ACCESS_FINE_LOCATION)
}
if(!backgroundlocationpermission){
permissionRequest.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
if(permissionRequest.isNotEmpty()){
permissionLauncher.launch(permissionRequest.toTypedArray())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
WindowCompat.setDecorFitsSystemWindows(window, true)
super.onCreate(savedInstanceState)
permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){
permissions ->
islocationpermissiongranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: islocationpermissiongranted
backgroundlocationpermission = permissions[Manifest.permission.ACCESS_BACKGROUND_LOCATION] ?: backgroundlocationpermission
}
requestpermission()
}`
First of all you need to register permission of location in the manifest and if you already added that permission then here is another code and it's work perfectly fine
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "Location"
if (ContextCompat.checkSelfPermission(this#MainActivity,
android.Manifest.permission.ACCESS_FINE_LOCATION) !==
PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this#MainActivity,
android.Manifest.permission.ACCESS_FINE_LOCATION)) {
ActivityCompat.requestPermissions(this#MainActivity,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 1)
} else {
ActivityCompat.requestPermissions(this#MainActivity,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 1)
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1 -> {
if (grantResults.isNotEmpty() && grantResults[0] ==
PackageManager.PERMISSION_GRANTED) {
if ((ContextCompat.checkSelfPermission(this#MainActivity,
android.Manifest.permission.ACCESS_FINE_LOCATION) ===
PackageManager.PERMISSION_GRANTED)) {
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show()
}
return
}
}
}
This is a permission of location in manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
Related
I can't seem to figure out how do I display data after run time allow permission button is pressed.The data is in a recycler view
The permission dialog works correctly because this gives me correct result on log cat but I cannot seem to get data on mobile device
Here is the code:
private val requestMultiplePermissions =registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions[READ_EXTERNAL_STORAGE] == true && permissions[WRITE_EXTERNAL_STORAGE] == true) {
getMusicList()
} else {
checkPermissions()
Log.d(TAG, "Permission not granted")
}
}
private fun checkPermissions(){
if (context?.let {
ContextCompat.checkSelfPermission(
it,
READ_EXTERNAL_STORAGE
)
} != PackageManager.PERMISSION_GRANTED) {
requestMultiplePermissions.launch(
arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE))
}
else {
requestMultiplePermissions
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View {
checkPermissions()
}
private fun checkPermissions() {
if (context?.let {
ContextCompat.checkSelfPermission(
it,
READ_EXTERNAL_STORAGE
)
} != PackageManager.PERMISSION_GRANTED) {
requestMultiplePermissions.launch(
arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE))
} else {
//requestMultiplePermissions
getMusicList()
}
}
Do not need to request permission again when it is granted
I am trying to use a camera on my android. the user will be prompt for the permission of the camera. previously I used startActivityForResult and onRequestPermissionRequest for them. recently I found out that they are deprecated, so I'm trying out with registerForActivity. I managed to change to startActivity but I'm stuck at the permission request. I am wondering do I have to create another permissionlauncher or can I do the permission inside my resultlauncher.
companion object{
private const val CAMERA_PERMISSION_CODE = 1
private const val CAMERA_REQUEST_CODE = 2
}
val checkpermission = Manifest.permission.CAMERA
var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
val DP: Bitmap = data!!.extras!!.get("data") as Bitmap
val image = findViewById<ImageView>(R.id.imageButtonVerifyPhoto)
image.setImageBitmap(DP)
}
}
val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()){
isGranted ->
if(isGranted){
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
resultLauncher.launch((intent))
Toast.makeText(this,"Permission is tested", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(this,"Permission is denied",Toast.LENGTH_SHORT).show()
}
}
var cameraButton = findViewById<Button>(R.id.buttonRetakePhoto) // can change later
cameraButton.setOnClickListener {
if(ContextCompat.checkSelfPermission(
this,
checkpermission
) == PackageManager.PERMISSION_GRANTED
){
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
resultLauncher.launch(intent)
}else{
permissionLauncher.launch(checkpermission)
}
}
}
below is my previous code for the onRequestPermission
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode == CAMERA_REQUEST_CODE){
if(grantResults.isNotEmpty()&& grantResults[0] == PackageManager.PERMISSION_GRANTED){
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent, CAMERA_REQUEST_CODE)
}else{
Toast.makeText(this,"Permission is denied",Toast.LENGTH_SHORT).show()
}
}
}
Requesting runtime permissions is just a little more simplified
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
// do something
}
Now we can call this to get any type of permission you want
cameraButton.setOnClickListener {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
) {
// Pass any permission you want while launching
requestPermission.launch(Manifest.permission.CAMERA)
}
}
Make sure to add in build.gradle
implementation 'androidx.fragment:fragment-ktx:1.2.0' // or later
implementation 'androidx.activity:activity-ktx:1.3.0' // or later
If you want to understand how all this works check here
Latest soluton in 2022: (no more request code)
Create Helper Extension Functions (for use in Fragment):
fun Fragment.requestPermissions(request: ActivityResultLauncher<Array<String>>, permissions: Array<String>) = request.launch(permissions)
fun Fragment.isAllPermissionsGranted(permissions: Array<String>) = permissions.all {
ContextCompat.checkSelfPermission(requireContext(), it) == PackageManager.PERMISSION_GRANTED
}
Request Permissions in Fragment:
class FirstFragment : Fragment() {
companion object {
private val PERMISSIONS = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
private lateinit var binding: FragmentFirstBinding
private lateinit var permissionsRequest: ActivityResultLauncher<Array<String>>
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_first, container, false)
permissionsRequest = getPermissionsRequest()
binding.grantButton.setOnClickListener {
requestPermissions(permissionsRequest, PERMISSIONS) //extension function
}
return binding.root
}
private fun getPermissionsRequest() = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
if (isAllPermissionsGranted(PERMISSIONS)) { //extension function
//do your stuff
} else {
//do your stuff
}
}
}
You could try Aaper, it allows to request for permissions using annotations like so:
Fist, add the permission to your manifest:
<uses-permission android:name="android.permission.CAMERA" />
Then, annotate a method that needs to use the camera:
#EnsurePermissions(permissions = [Manifest.permission.CAMERA])
fun takePhoto() {
Toast.makeText(this, "Camera permission granted", Toast.LENGTH_SHORT).show()
}
That's it, when you call the takePhoto method, it'll check for the camera permission, and if it's not available it will launch a permission request dialog. If the user approves it, then it will proceed to run takePhotos body.
Disclaimer, I'm the creator of Aaper
In the physical device, it takes too much time to call. But in avd it's run perfectly. I test this code in redmi note 4 and zuk z2 plus. Both device location set on HIGH_ACCURACY . I want to fetch the location rapidly. But it takes too much time to execute.
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0f,wcLoactionListener)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0f,wcLoactionListener)
But if I removed this line
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0f,wcLoactionListener)
then onLocationChanged() not calling.
Here is my location listener
class MyListener:LocationListener {
override fun onLocationChanged(location: Location?) {
Log.d("Loc","*************************************************** "+ location)
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
}
override fun onProviderEnabled(provider: String?) {
}
override fun onProviderDisabled(provider: String?) {
}
}
Mainactivity:-
class MainActivity : AppCompatActivity() {
val LOCATION_CODE = 212
private lateinit var locationManager: LocationManager
private lateinit var cwcLoactionListener:MyListener
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
cwcLoactionListener = MyListener()
checkLocationPermission()
}
#SuppressLint("MissingPermission")
fun fechLOc(){
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0f,cwcLoactionListener)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,500,0f,cwcLoactionListener)
}
private fun checkLocationPermission() {
if(Build.VERSION.SDK_INT>=23){
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED ){
requestPermissions(arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_CODE)
return
}
}
fechLOc()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
LOCATION_CODE->{
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Accept this permission", Toast.LENGTH_LONG).show()
}else{
fechLOc()
}
}
else ->{
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
}
}
manifest
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Ι am writing an android application that uses both location and internet connection permissions and I am running it on my tablet. As you can see, I have included both in the manifest file. The problem is that when OnConnected() function is called the below if in the MainActivity.kt evaluates to true and I can't proceed further in the function. So can you give me some hint to provide some more code if it is not relevant
AndroidManifest.xml :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
MainActivity.kt
override fun onConnected(p0: Bundle?) {
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
return;
}
//some code
}
You have to understand the logic behind permissions in Android. Just adding the permissions in the manifest, doesn't mean that the user has authorized the application to do what those permissions enable.
If your if condition evaluates to true, since those permissions are not granted, you have to ask the user for those permissions.
Android has a some good documentation on how to this.
I highly suggest you go over that.
From Android 6.0 onwards needs to request permission the best way is to do a permissionManager Class to Handle that and then check in your Activity if the user has accepted the permissions:
class PermissionManager private constructor() {
fun checkPermission(
activity: Activity,
permissionRequests: Array<String>?,
requestCode: Int
): Boolean {
permissionRequests?.let {
it.firstOrNull {
ContextCompat.checkSelfPermission(
activity,
it
) != PackageManager.PERMISSION_GRANTED
}?.apply {
ActivityCompat.requestPermissions(
activity,
permissionRequests,
requestCode
)
return false
}
}
return true
}
companion object {
val instance by lazy { PermissionManager() }
const val CAMERA_PERMISSION = 1
}
}
Then in your activity check the permission Result:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ar)
//If the user has the permission accepted the next times
if (PermissionManager.instance.checkPermission(
this, arrayOf(
Manifest.permission.CAMERA
), PermissionManager.CAMERA_PERMISSION
)
) {
initLogic()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
PermissionManager.CAMERA_PERMISSION -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initLogic()
} else {
return
}
}
}
}
}
Why is this not working? I've modified the Manifest too.
It is not asking for permission as I've coded. It's behaving as if I'm not even requesting for any permission.
I've made a splash screen and I want it to ask for permission before it goes to the MainActivity.
Splash screen should last for 1sec.
class SplashActivity : AppCompatActivity() {
var permissionsString = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MODIFY_AUDIO_SETTINGS,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.PROCESS_OUTGOING_CALLS,
Manifest.permission.RECORD_AUDIO)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
if (hasPermissions(this#SplashActivity,*permissionsString)){
ActivityCompat.requestPermissions(this#SplashActivity,permissionsString,131)
}else{
Handler().postDelayed({
val startAct = Intent(this#SplashActivity,MainActivity::class.java)
startActivity(startAct)
this.finish()},1000)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when(requestCode){
131 ->{
if (grantResults.isNotEmpty()
&& grantResults[0]==PackageManager.PERMISSION_GRANTED
&& grantResults[1]==PackageManager.PERMISSION_GRANTED
&& grantResults[2]==PackageManager.PERMISSION_GRANTED
&& grantResults[3]==PackageManager.PERMISSION_GRANTED
&& grantResults[4]==PackageManager.PERMISSION_GRANTED){
Handler().postDelayed({
val startAct = Intent(this#SplashActivity,MainActivity::class.java)
startActivity(startAct)
this.finish()},1000)
}else{
Toast.makeText(this#SplashActivity,"Grant it Please",Toast.LENGTH_SHORT).show()
this.finish()
}
return
}
else->{
Toast.makeText(this#SplashActivity,"Something wrong",Toast.LENGTH_SHORT).show()
this.finish()
return
}
}
}
fun hasPermissions(context: Context,vararg permissions: String): Boolean{
var hasAllPermissions = true
for (permission in permissions){
val res = context.checkCallingOrSelfPermission(permission)
if (res!=PackageManager.PERMISSION_GRANTED){
hasAllPermissions = false
}
}
return hasAllPermissions
}
}
Thats because your if condition is wrong. It should on include NOT operator to ask for permission as below:
if (!hasPermissions(this#SplashActivity,*permissionsString)) {
//Ask for permission
}
Ask for permission if you don't have the permission. In your case, you are checking if you have permission, then ask for permission which is wrong.
Check your
targetSdkVersion
in project gradle file.
It should be >= 23 to call run-time permission, otherwise will take permission automatically.