The android application crash - android

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
)
)

Related

Bluetooth pemissions in Android Studio

I want to request BLUETOOTH_SCAN and BLUETOOTH_CONNECT permission. Could anyone tell me how should I do that in Kotlin? I have this piece of code but it always tells permission denied.
class MainActivity : AppCompatActivity() {
var requestBluetooth = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
Toast.makeText(this, "granted", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(this, "denied", Toast.LENGTH_SHORT).show()
}
}
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
Log.d("test", "${it.key} = ${it.value}")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button) // just a simple button from XML file
button.setOnClickListener {
// for android 12
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
requestMultiplePermissions.launch(arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT))
}
else{
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
requestBluetooth.launch(enableBtIntent)
}
}
}
}
Because I am not yet well-versed in Kotlin (and I expect you to be able to easily convert the Java codes into Kotlin), I'll just show you how to request the dangerous Manifest.permission.BLUETOOTH_CONNECT permission every time we want to access the list of paired Bluetooth devices:
public static final int PERMISSIONS_REQUEST_BLUETOOTH_CONNECT = 101; //the int value must be unique
public boolean checkBluetoothConnectPermission(Activity activity) {
boolean permitted = false;
Boolean bluetoothAlreadyGranted = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ?
ActivityCompat.checkSelfPermission(activity,
Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED: true;
Log.i(IMapView.LOGTAG,
String.format("PERMISSION: checkBluetoothPermission(%s) bluetoothAlreadyGranted=%s",
activity.getClass().getSimpleName(),
bluetoothAlreadyGranted));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Check for permission
if (!bluetoothAlreadyGranted.booleanValue()) {
bluetoothAlreadyGranted = ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.BLUETOOTH_CONNECT);
// Check for permission
if (bluetoothAlreadyGranted.booleanValue()) {
new AlertDialog.Builder(MainApp.getCurrentActivity(), R.style.AppCompatAlertDialogStyle)
.setTitle(activity.getString(R.string.bluetooth_connect_rational_title,
activity.getString(R.string.app_name_flavor)))
.setMessage(activity.getString(R.string.bluetooth_connect_rational_message,
activity.getString(R.string.app_name_flavor)))
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.BLUETOOTH_CONNECT},
PERMISSIONS_REQUEST_BLUETOOTH_CONNECT);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.BLUETOOTH_CONNECT},
PERMISSIONS_REQUEST_BLUETOOTH_CONNECT);
}
} else {
permitted = true;
}
} else {
permitted = true;
}
return permitted;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
// Check if permission was granted
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; //#TODO you need to check which permission from the array to get the granted status for the matched request code...
switch (requestCode) {
case PERMISSIONS_REQUEST_BLUETOOTH_CONNECT: {
//do whatever you want here
}
break;
}
}
In the Android manifest, the following entry shall be provided:
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
The same shall apply for the dangerous Manifest.permission.BLUETOOTH_SCAN permission with a different intent request code.

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

Android continue after checking and requesting permission

I know there are many questions answered regarding checking and requesting permission and handling their response and I am clear on that. But what I bit confuse about is if we are checking for same permission for two different things, how do we continue task after permission is granted?
For example,I have recycleView and in my adapter I have code for two buttons, one would save file and another one would save and open activity to share that file with other app.
MyRecycleAdapter {
Context context:
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(checkPermission()) {
have permission
save file to disk
} else {
requestPermission
save file to disk
}
}
});
share.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(checkPermission()) {
have permission
save file to disk
open share activity using (context)
} else {
requestPermission
save file to disk
open share activity using (context)
}
}
});
}
Use different request codes to control what happens after permission is granted:
final int SAVE = 1;
final int SAVE_AND_SHARE = 2;
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
new String[]{
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
},
[either SAVE or SAVE_AND_SHARE]);
} else {
//permission is already granted, continue
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
grantResults) {
if (requestCode == SAVE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
//save
} else {
//permission was denied
}
} else if (requestCode == SAVE_AND_SHARE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
//save and share
} else {
//permission was denied
}
}
}
Just for the sake of completion. Requesting permissions has been simplified lately in the API. Here's how I check for a permission before doing some action:
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Permission callback
val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
// Yay, permission was granted
doSomething()
}
else {
// Boo, permission was refused
Snackbar.make(root,"Wut ?! We need your permission!", Snackbar.LENGTH_LONG).show()
}
}
}
private fun checkLocationPermissionAndDoSomething() {
// Do we have the permission ?
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Permission is not granted. Should we show an explanation?
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
// Explanation is needed. Show dialog
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Please")
builder.setMessage("We need to use your location because bla blah bla.")
builder.setPositiveButton(android.R.string.ok) { _, _ ->
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
builder.show()
}
else {
// No explanation needed, we can request the permission.
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
} else {
// Permission has already been granted
doSomething()
}
}
When multiple permissions are needed just use ActivityResultContracts.RequestMultiplePermissions and use an array of permissions

When I overriding function onRequestPermissionsResult is not working

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
}
}
}
}
}

How to ask runtime permissions for Camera in Android , Runtime storage permissions

I am doing an application to scan barcodes on a button click and it was working fine up to Lollipop versions. When I came to Marshmallow it stopped working. This is the error:
camerabase an error occurred while connecting to camera 0
It forces me to turn on permission by:
Settings --> application --> my app --> camera.
My question is how to allow camera permission to my app automatically in Marshmallow or by asking the user to turn on camera at runtime. A screen shot:
Below I have written a code for granting a runtime permissions for Camera, There is an Array of String in which you can give multiple requests granting as which is needed at runtime.
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 200;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkPermission()) {
//main logic or main code
// . write your main code to execute, It will execute if the permission is already given.
} else {
requestPermission();
}
}
private boolean checkPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
return false;
}
return true;
}
private void requestPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
PERMISSION_REQUEST_CODE);
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_SHORT).show();
// main logic
} else {
Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
showMessageOKCancel("You need to allow access permissions",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermission();
}
}
});
}
}
}
break;
}
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(MainActivity.this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
}
This is the complete code to implement multiple or single runtime permissions
Step 1
Add permission in manifest for camera and also other required
permissions
like
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Step 2
declare this variable
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS= 7;
and Call this method checkAndroidVersion() in oncreate()
private void checkAndroidVersion() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkAndRequestPermissions();
} else {
// code for lollipop and pre-lollipop devices
}
}
private boolean checkAndRequestPermissions() {
int camera = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.CAMERA);
int wtite = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
int read = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (wtite != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (camera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CAMERA);
}
if (read != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(getActivity(), listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d("in fragment on request", "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d("in fragment on request", "CAMERA & WRITE_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE permission granted");
// process the normal flow
//else any one or both the permissions are not granted
} else {
Log.d("in fragment on request", "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// // shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
showDialogOK("Camera and Storage Permission required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(getActivity(), "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(getActivity())
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
if (ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity)
getContext(), Manifest.permission.CAMERA)) {
} else {
ActivityCompat.requestPermissions((Activity) getContext(),
new String[]{Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CAMERA);
}
}
This sample Profile project demonstrates how to get Read Storage and Camera Permission in Android and also how to handle when the user selects DENY & DON'T ASK AGAIN.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerStoragePermission()
registerGalleryLauncher()
registerCameraPermission()
registerCameraLauncher()
}
private fun registerCameraPermission() {
requestCameraPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
Log.d(TAG, "registerCameraPermission - Camera Permission Granted")
openCamera()
} else {
Log.d(TAG, "registerCameraPermission - Camera Permission NOT Granted")
requestCameraPermission()
}
}
}
private fun registerStoragePermission() {
requestStoragePermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
Log.d(TAG, "registerStoragePermission - Storage Permission Granted")
viewGallery()
} else {
Log.d(TAG, "registerStoragePermission - Storage Permission NOT Granted")
requestStoragePermission()
}
}
}
private fun registerCameraLauncher() {
cameraLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
if (data == null) {
return#registerForActivityResult
}
val extras = data.extras
imageBitmap = extras!!["data"] as Bitmap
file = FileUtils.createFile(requireContext(),
getString(R.string.app_name),
"my_profile_image.png"
)
//FileUtils.saveBitmap(imageBitmap, file);
val imageLocalPath = FileUtils.saveImageToInternalStorage(file, imageBitmap)
SharedPreferencesUtils.setProfilePath(requireActivity(), imageLocalPath)
profileFragmentBinding.imageViewCircleNoStroke.setImageBitmap(imageBitmap)
profileFragmentBinding.imageViewCircleNoStroke.setScaleType(ImageView.ScaleType.CENTER_CROP)
}
}
}
private fun registerGalleryLauncher() {
galleryLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
if (data == null) {
return#registerForActivityResult
}
val uri = data.data
var imageLocalPath = File(FileUtils.getPathReal(requireActivity(), uri!!))
file = imageLocalPath.absoluteFile
SharedPreferencesUtils.setProfilePath(requireActivity(), imageLocalPath.absolutePath)
Glide.with(requireActivity()).load(uri)
.into(profileFragmentBinding.imageViewCircleNoStroke)
profileFragmentBinding.imageViewCircleNoStroke.setScaleType(ImageView.ScaleType.CENTER_CROP)
}
}
}
private fun showImageUploadOptions() {
val mDialog = activity.let { Dialog(it!!) }
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
mDialog.setContentView(R.layout.dialog_profile_image_option)
mDialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
//val mAlertMessageTv = mDialog.findViewById<View>(R.id.id_alert_tv) as TextView
//mAlertMessageTv.text = message
galleryLl = mDialog.findViewById<View>(R.id.id_gallery_ll) as LinearLayout
cameraLl = mDialog.findViewById<View>(R.id.id_camera_ll) as LinearLayout
removePhotoLl = mDialog.findViewById<View>(R.id.id_remove_photo_ll) as LinearLayout
galleryLl.setOnClickListener {
CallStoragePermission()
mDialog.dismiss()
}
cameraLl.setOnClickListener {
CallCameraPermission()
mDialog.dismiss()
}
removePhotoLl.setOnClickListener {
CallRemovePhoto()
mDialog.dismiss()
}
mDialog.setCancelable(true)
mDialog.show()
val metrics = resources.displayMetrics
val width = metrics.widthPixels
val height = metrics.heightPixels
mDialog.window!!.setLayout(
width,
LinearLayout.LayoutParams.WRAP_CONTENT
)
}
fun CallStoragePermission() {
if (!Status_checkReadExternalStoragePermission()) {
requestStoragePermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
} else {
viewGallery()
}
}
private fun Status_checkReadExternalStoragePermission(): Boolean {
val permissionState = ActivityCompat.checkSelfPermission(
requireActivity(),
Manifest.permission.READ_EXTERNAL_STORAGE
)
return permissionState == PackageManager.PERMISSION_GRANTED
}
private fun requestCameraPermission() {
when {
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
Log.d(TAG, "requestCameraPermission - Camera Permission Granted")
openCamera()
// The permission is granted
// you can go with the flow that requires permission here
}
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// This case means user previously denied the permission
// So here we can display an explanation to the user
// That why exactly we need this permission
Log.d(TAG, "requestCameraPermission - Camera Permission NOT Granted")
showPermissionAlert(
getString(R.string.camera_permission),
getString(R.string.camera_permission_denied),
getString(R.string.ok_caps),
getString(R.string.cancel_caps)
) { requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA) }
}
else -> {
// Everything is fine you can simply request the permission
showPermissionAlert(
getString(R.string.camera_permission),
getString(R.string.camera_permission_denied),
getString(R.string.settings_caps),
getString(R.string.cancel_caps)
) {
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
val uri = Uri.fromParts(
"package",
BuildConfig.APPLICATION_ID, null
)
intent.data = uri
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
}
}
}
private fun requestStoragePermission() {
when {
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED -> {
Log.d(TAG, "requestStoragePermission - Storage Permission Granted")
viewGallery()
// The permission is granted
// you can go with the flow that requires permission here
}
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> {
// This case means user previously denied the permission
// So here we can display an explanation to the user
// That why exactly we need this permission
Log.d(TAG, "requestStoragePermission - Storage Permission NOT Granted")
showPermissionAlert(
getString(R.string.read_storage_permission_required),
getString(R.string.storage_permission_denied),
getString(R.string.ok_caps),
getString(R.string.cancel_caps)
) { requestStoragePermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) }
}
else -> {
// Everything is fine you can simply request the permission
showPermissionAlert(
getString(R.string.read_storage_permission_required),
getString(R.string.storage_permission_denied),
getString(R.string.settings_caps),
getString(R.string.cancel_caps)
) {
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
val uri = Uri.fromParts(
"package",
BuildConfig.APPLICATION_ID, null
)
intent.data = uri
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
}
}
}
private fun showPermissionAlert(
title: String,
message: String,
ok: String,
cancel: String,
function: () -> Unit
) {
val mDialog = requireActivity().let { Dialog(it) }
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
mDialog.setContentView(R.layout.dialog_permission_alert)
mDialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val mTitleTv = mDialog.findViewById<View>(R.id.id_title_tv) as AppCompatTextView
mTitleTv.text = title
val mMessageTv = mDialog.findViewById<View>(R.id.id_message_tv) as AppCompatTextView
mMessageTv.text = message
val mNoBtn = mDialog.findViewById<View>(R.id.no_btn) as AppCompatTextView
mNoBtn.text = cancel
val mYesBtn = mDialog.findViewById<View>(R.id.yes_btn) as AppCompatTextView
mYesBtn.text = ok
mYesBtn.setOnClickListener {
function.invoke()
mDialog.dismiss()
}
mNoBtn.setOnClickListener { mDialog.dismiss() }
mDialog.setCancelable(true)
mDialog.show()
val metrics = resources.displayMetrics
val width = metrics.widthPixels
val height = metrics.heightPixels
mDialog.window!!.setLayout(
width,
LinearLayout.LayoutParams.WRAP_CONTENT
)
}
fun viewGallery() {
val intentDocument = Intent(Intent.ACTION_GET_CONTENT)
intentDocument.type = "image/*"
intentDocument.putExtra(
Constants.REQUEST_CODE,
Constants.REQUEST_PHOTO_FROM_GALLERY
)
galleryLauncher.launch(intentDocument)
}
fun openCamera() {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
takePictureIntent.putExtra(
Constants.REQUEST_CODE,
Constants.REQUEST_PERMISSIONS_REQUEST_CODE_CAMERA
)
cameraLauncher.launch(takePictureIntent)
}
fun CallCameraPermission() {
if (!Status_checkCameraPermission()) {
requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA)
} else {
openCamera()
}
}
private fun Status_checkCameraPermission(): Boolean {
val camera = ActivityCompat.checkSelfPermission(
requireActivity(),
Manifest.permission.CAMERA
)
return camera == PackageManager.PERMISSION_GRANTED
}
RxPermission is best library for asking permissions from user.
For camera permission the workaround is like this.
1) First add these permissions (or one you need) in your manifest.xml.
<uses-permission android:name="android.permission.CAMERA" />
2) Then ask run time permission from user in your activity.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA) // ask single or multiple permission once
.subscribe(granted -> {
if (granted) {
// All requested permissions are granted
} else {
// At least one permission is denied
}
});
add this library in your build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}
Isn't this easy?
Manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
Call it somewhere in your activity:
handlePermissions(new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
});
Also in your activity:
private void handlePermissions(String[] permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> notGrantedPerms = new ArrayList<>();
for (String p : permissions) {
if (this.checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED)
notGrantedPerms.add(p);
}
permissions = notGrantedPerms.toArray(new String[0]);
if (permissions != null && permissions.length > 0)
this.requestPermissions(permissions, 701);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 701) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (String p : permissions) {
String msg = "";
if (this.checkSelfPermission(p) == PackageManager.PERMISSION_GRANTED)
msg = "Permission Granted for " + p;
else
msg = "Permission not Granted for " + p;
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
}
}
void AutoRequestAllPermissions(){
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M){return;}
PackageInfo info = null;
try {
info = getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if(info==null){return;}
String[] permissions = info.requestedPermissions;
boolean remained = false;
for (String permission : permissions) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
remained = true;
}
}
if(remained) {
requestPermissions(permissions, 0);
}
}
this code-
automatically read all permissions from manifest
then check if any permission is not granted
then request that remaining permissions
This might help:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
if(ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.CAMERA))
{
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setTitle("Permission necessary");
alertBuilder.setMessage("CAMERA is necessary");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUESTS);
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
} else {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUESTS);
}
return false;
} else {
return true;
}
Where MY_PERMISSIONS_REQUESTS is your final value of the request code.
It works just fine for me.
After having it defined in your manifest file, a friendlier alternative to the native solution would be using Aaper: https://github.com/LikeTheSalad/aaper like so:
#EnsurePermissions(permissions = [Manifest.permission.CAMERA])
private fun takePhoto() {
// Your code that needs the camera permission granted.
}
Disclaimer, I'm the creator of Aaper.
Android team has provided a new way in requesting permissions using registerForActivityResult,
<uses-permission
android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Define an object to request permissions, and receive the result in the
callback
private val requestPermissionsLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions.all { it.value }) {
Toast.makeText(
this,
"You have obtained the required permissions",
Toast.LENGTH_LONG
).show()
} else Toast.makeText(
this,
"You have not accepted all the permissions",
Toast.LENGTH_LONG
).show()
}
To ask for the permissions, do the following, you can add wherever you think is better:
requestPermissionsLauncher.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
)

Categories

Resources