I'm using the method startVoiceRecognition of class BluetoothHeadset. I can see from android vitals reports, a recurring security exception on Android Pie calling this method. I can't test it on emulator and I don't have a Pie phone to test. From documentation it seems only BLUETOOTH permission is needed and my apps has already that permission. Can someone help me to understand?
You need to request the permission RECORD_AUDIO, add it on your AndroidManifest:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
Read official documentation first. After Android 6.0 (API level 23) you should invoked Runtime Permission
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
}
Related
I want to request permissions on runtime.I checked out official android developer website and it says that shouldShowRequestPermissionRationale returns true if permission was previously denied and returns false if permission has been denied AND never ask again checkbox was selected.
Then i saw this code in the site:
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
My 2 questions are:
1)What happens if the user wasn't asked permission previously??We need to ask him right??Where do you put that code??
2)The above code asks for permission even when the user checked the never ask again checkbox(when shouldShowRequestPermissionRationale returns false,I.e,in the else block).How can u ask for permission when the user has checked that option??
To answer both your questions:
You can first use checkSelfPermission() to see if the permission has already been granted. If it has not been granted then you should check if shouldShowRequestPermissionRationale() returns true or false.
shouldShowRequestPermissionRationale() will return true in the following case:
When the user has denied the permission previously but has not
checked the "Never Ask Again" checkbox.
shouldShowRequestPermissionRationale() will return false in the following 2 cases:
When the user has denied the permission previously AND never ask
again checkbox was selected.
When the user is requesting permission for the first time.
So, what you can do is, if shouldShowRequestPermissionRationale() returns false
you can use a boolean preference value (default value as true) to check for
first time request of permission in the else case, if it is the first
request, then trigger requestPermissions
else if it is not the first request and the user has previously denied the request and also has checked the "Never ask again" checkbox, you can show a simple toast with the reason for unavailability of the feature that requires the permission and also mention the steps to manually enable it via settings.
Something like this:
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
if(isFirstTimeRequest){
// No explanation needed; request the permission
// RESET PREFERENCE FLAG
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
} else {
// User denied previously and has checked "Never ask again"
// show a toast with steps to manually enable it via settings
}
}
I'm currently writing some tests for an app. If the app does not have storage permission, a fragment pops up. I know how to grant permission with "grant permission rule" but is there a method to revoke permission?
No, that is not possible. Quote from https://developer.android.com/reference/android/support/test/rule/GrantPermissionRule:
Once a permission is granted it will apply for all tests running in the current Instrumentation. There is no way of revoking a permission after it was granted. Attempting to do so will crash the Instrumentation process.
What I can suggest is to wrap permission methods into some service and mock the value checking if the permission is granted
Yes, during testing its possible...Feuby gave a somewhat correct answer to the same question in this SO 2017 question
Android revoke permission at start of each test
Repeating his code
public static boolean checkCameraPermission(MainActivity thisActivity) {
return ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED;
}
public static void checkAndAskCameraPermission(final MainActivity thisActivity) {
if (!checkCameraPermission(thisActivity)) {
//No right is granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.CAMERA)) {
//Open a dialog explaining why you are asking permission then when when positive button is triggered, call this line
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CAMERA},
CHECK_FOR_CAMERA_PERMISSION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CAMERA},
CHECK_FOR_CAMERA_PERMISSION);
}
}
}
I am new to Android App developing and BLE, and I am learning these using the sample code BluetoothLeGatt [The one I imported from Android Studio]. The code works fine on my tablet (Android 5.0), but the scan activity does not return any BLE devices on Android 6.0. The error message I got is shown below.
07-19 12:41:39.615 7617-7642/? W/Binder: Caught a RuntimeException from the binder stub implementation.
java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:772)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:331)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)
at android.os.Binder.execTransact(Binder.java:458)
I looked at the post Bluetooth Low Energy startScan on Android 6.0 does not find devices and the official page Requesting Permissions at Run Time, but I still don't really know how to modify my code.
I did add the permissions of GPS, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, and I turned on the Location Service on my tablet.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature android:name="android.hardware.location.gps" />
But the App still cannot return any BLE devices. Then, when I try to add the following block of code to my App (from Requesting Permissions at Run Time ), there is always an error on checkSelfPermission [Cannot resolve symbol 'checkSelfPermission']. But I did import import android.support.v4.content.ContextCompat;
Can someone help me with this? Also, is there a simpler answer to the question how to make DeviceScanActivity work? I don't really know where to put the blocks of the code from Requesting Permissions at Run Time to my code :( I know this is a really stupid question, but I am really new to this field. Please help me!
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
EDIT
The following is my dependencies block.
dependencies {
compile "com.android.support:support-v4:25.3.1"
compile "com.android.support:support-v13:25.3.1"
compile "com.android.support:cardview-v7:25.3.1"
compile "com.android.support:appcompat-v7:25.3.1"
}
Thank you everyone for your responses and help! I've just solved my case!
What I did is that besides adding the permissions in AndroidManifest.xml, I added the following code to my onCreate method in DeviceScanActivity, and the reference I used is Requesting Permissions at Run Time. Also, I just randomly assigned a number to MY_PERMISSIONS_REQUEST_LOCATION.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
mHandler = new Handler();
//Check for permissions
int permissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_CALENDAR);
Log.e(TAG, "Permission Status: " +permissionCheck );
//***********************************************************
//
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
{
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_COARSE_LOCATION))
{
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
}
else
{
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
}
......//The rest of code
}
When I first added the above code, there is a pop-up window coming up on my tablet asking me for permissions, and I clicked "allow."
Then, I am able to scan my ble devices.
BTW, it only asks for my permission once. When I clicked "Run Application" later (after slight modifications of my code), it didn't ask for my permission again.
Do you add those all permissions:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
It works fine on android 6.0
In my android application I wish to ask users permission to use the google playservices. Is there any way to do that?
Like for reading contacts, we use:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(getActivity(),
android.Manifest.permission.)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
android.Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
P.S : My gradle.build file has:
compile 'com.google.android.gms:play-services:9.0.2'
compile 'com.google.android.gms:play-services-location:8.1.0'
Google play service are library. You never need to ask for permission to use them. Bt depends on feature you wanna use u need permission.
Like to use map you need to ask location permission
I'm testing denial of permission to an application and I'm seeing that when asking for the state of the permission it returns granted instead of denied.
I'm checking state of permissions according to Google's Guide:
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.CAMERA)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.CAMERA},
PERMISSIONS_REQUEST_TAKE_PHOTO);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Here is what it actually returns in the first if:
State "0" means PackageManager.PERMISSION_GRANTED
This is generating a java.lang.RuntimeException: Fail to connect to camera service error.
DEVICE IS A NEXUS 5X
Best regards.
Quotig #CommonsWare:
You're supposed to get PERMISSION_GRANTED for any targetSdkVersion below 23, even if the user toggled off that permission group in Settings. I suggest that you uninstall the app completely, set your targetSdkVersion to 23, and try it again.
This was the solution.
(This answer will be marked correct temporarily until commenter posts an answer)