Cannot request Bluetooth permission on Wear OS Samsung Galaxy Watch 4 - android

I've created a sample Wear OS app, which should discover BLE devices, but my code requires Bluetooth permission. When I put these lines in manifest:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
corresponding permission is not displayed in settings/apps/permissions and every permission request does nothing. By the way, my BLE-devices (a speaker and a esp-32) is not shown in settings/Bluetooth also.
How can I grant Bluetooth permissions for my app or how can I connect BLE device to my watch?
upd:
I tried these:
if (checkSelfPermission(Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH), 1001)
}
if (checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH_CONNECT), 1001)
}
if (checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH_SCAN), 1001)
}
if (checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH_ADMIN), 1001)
}
But dialogs windows still are not displayed

According documentation, you need particular permissions in based of the target Android API version.
If your app targets Android 11 (API level 30) or lower, declare the following permissions in your app's manifest file:
BLUETOOTH is necessary to perform any Bluetooth classic or BLE communication, such as requesting a connection, accepting a connection, and transferring data.
ACCESS_FINE_LOCATION is necessary because, on Android 11 and lower, a Bluetooth scan could potentially be used to gather information about the location of the user.
If your app targets Android 9 (API level 28) or lower, you can declare the ACCESS_COARSE_LOCATION permission instead of the ACCESS_FINE_LOCATION permission.
In order to perform a scan to discover BLE devices the app must require explicitaly to the user the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission also to be declared in the AndroidManifest.xml.
In my project (WearOS API version 28) I used this code in the onCreate function of MainActivity class
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
1);
}
And I overrided the onRequestPermissionsResult function
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case 1:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Logger.d("MainActivity","Permission approved");
} else {
Logger.d("MainActivity","Error getting permission");
}
return;
}
}
This works for me, I hope would help you

there are some permissions like camera, bluetooth which need to be asked first and then manually provided. use this in the activity that loads first in your app.
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.CAMERA), 1001);
} //ask camera permissions
make sure to do required changes.

Related

Oreo (WRITE EXTERNAL STORAGE) Permission

According to "developer.android.com"
If the app targets Android 8.0 (API level 26), the system grants only
READ_EXTERNAL_STORAGE at that time; however, if the app later requests
WRITE_EXTERNAL_STORAGE, the system immediately grants that privilege
without prompting the user.
Now, I have the READ_EXTERNAL_STORAGE and I'm requesting the DownloadManager to download a file in the Public Download folder
downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mAttachmentItem.getFilename());
Unfortunately, I got
E/UncaughtException: java.lang.IllegalStateException: Unable to create directory: /storage/emulated/0/data/user/0/com.abc.cba/files
at android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.java:699)
I have declared both of permissions in the Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Read permission is already Granted and in Runtime I'm requesting Write permission, the system doesn't prompt any message or dialog, it's always Denied(Not Granted) in "onRequestPermissionsResult"
public static boolean isPermissionsToAccessStorageAreGranted(Context context, Activity activity) {
ArrayList<String> permissions = new ArrayList<>();
if (!PermissionUtil.checkPermissions(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!permissions.isEmpty()) {
String[] permissionsList = permissions.toArray(new String[permissions.size()]);
PermissionUtil.requestPermissions(activity, permissionsList,
PermissionUtil.REQUESTCODE_ACCESS_STORAGE);
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==REQUESTCODE_ACCESS_STORAGE && grantResults[0]== PackageManager.PERMISSION_GRANTED){
/* downloadFile(); */
}
}
I'm trying to grant those two permissions via ADB, it shows me an error:
adb shell pm grant com.abc.cba
android.permission.WRITE_EXTERNAL_STORAGE
Operation not allowed: java.lang.SecurityException: Package com.abc.cbs
has not requested permission android.permission.WRITE_EXTERNAL_STORAGE
adb shell pm grant com.abc.cba
android.permission.READ_EXTERNAL_STORAGE
Operation not allowed: java.lang.SecurityException: Can't change
android.permission.READ_EXTERNAL_STORAGE. It is required by the
application
Actually, It was an external problem. One of App Libs I'm using request the WRITE_EXTERNAL_PERMISSION with android:maxSdkVersion. So when merging with my Manifest it will remove the permission for the whole application.
The Solution is to add:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/>
You are correct in adding the permissions to the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
For versions of Lollipop and higher, you need to also request the permissions at runtime. To solve this problem, I created a new method requestAppPermission that I call when the main activity is created. This method runs only for Lollipop and higher, and returns early otherwise:
private void requestAppPermissions() {
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
if (hasReadPermissions() && hasWritePermissions()) {
return;
}
ActivityCompat.requestPermissions(this,
new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, REQUEST_WRITE_STORAGE_REQUEST_CODE); // your request code
}
private boolean hasReadPermissions() {
return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}
private boolean hasWritePermissions() {
return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}
I call this method in the activity's onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other things
requestAppPermissions();
}
On first load, this will prompt the user to accept permissions.
Then, before you run any code that needs to read and write to storage, you can check these permissions, either by storing the values or running those checks again using methods hasReadPermissions() and hasWritePermissions() defined above.
UPDATE: See this answer for a better solution
EDIT: This is not a solution, just a quick workaround.
If you get permission denied error even when the permissions are granted and you already implemented permission checks,
make sure you're not targetting api level 29:
Change targetSdkVersion and compilesdkversion from 29 to 28 or any other lower level.
For Oreo,
you need to explicitly do a READ_EXTERNAL_STORAGE request (by code) even if you have already requested and is granted the WRITE_EXTERNAL_STORAGE permission, and vis versa.
prior to this, READ_EXTERNAL_STORAGE is automatically granted when WRITE_EXTERNAL_STORAGE is granted.
so what you need to do, is to
1) ask for WRITE permission in your codes.
2) when user grants the WRITE permission, ask again for READ permission - this will be automatically granted (you will get an exception if you do not ask for a READ explicitly)
The changes for Oreo doesn't make much sense to me (no idea why do we need to ask for a permission that is automatically granted), but that is what it is.
https://developer.android.com/about/versions/oreo/android-8.0-changes.html#rmp
You have to grant permissions at runtime on Marshmallow or higher.
Sample snippet :
private static final int REQUEST_WRITE_STORAGE = 112;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean hasPermission = (ContextCompat.checkSelfPermission(getBaseContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
ActivityCompat.requestPermissions(SplashScreen.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.INTERNET
},
REQUEST_WRITE_STORAGE);
}else{ startMainActivity(); }
}
Hope it helps.
Use this
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
instead of
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE/>"
Some of your third party libraries are override maxSdkVersion like com.vungle:publisher-sdk-android, to finding them just check the Merged Manifest below of your manifest screen. see this
For SDK 29 and Later
If you are still having issue to accessing external storage, consider using android:requestLegacyExternalStorage="true" in your <application> tag of your manifest.
Just a notice: on Android P I had to show a terminate dialog box to user asking to restart the app because even after all written above app couldn't read external storage, only after restart. Seriously, those guys in google makes Android better each time. 6, 8, and now so much troubles with 9, one more such stupid update and I will go to iOS :)

How to handle permission issue in below Marshmallow Android

How can be handle permission issue in Sdk 22 .If user manually deny the permission.Their is way of handling permission in Marshmallow,but how can be it done in below M?.
Before Android Marshmallow users accept permissions just by installing your app (They can see the request permission list before installing).
So you don't need to handle denied permission for users running a version below Android Marshmallow.
for below Marshmallow version just give permission in manifest file.
Actually Android minimum sdk version 21-22 i.e. 5.0 doesn't need to check permission but when we have to Test the our app on different phones for eg. on minimum sdk version 23 i.e. on Marshmallow. You need to check permission externally in your App.
For Handling the permissions in App
Write below code in Your Starting_Activity
private void requestingPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_NETWORK_STATE)){
//Exaplian here why you need this permission
}
//Ask for the permission
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.ACCESS_NETWORK_STATE, },STORAGE_PERMISSION_CODE);}
Now Add another
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//checking the request code of Permission request
if (requestCode == STORAGE_PERMISSION_CODE){
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){//Toast.makeText(getApplicationContext(),"Permission Granted",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"Permission Denied",Toast.LENGTH_SHORT).show();
}
}
}
Dont forget call below method in your activity onCreate() Method
requestingPermission();

Request permission for microphone on Android M

I need to utilize the microphone with Android M. I've tried setting up a permission group in the manifest, and can't get it working properly. Here's what I've got in the manifest:
<permission-group android:name="android.permission-group.MICROPHONE"
android:label="label"
android:icon="#mipmap/day_icon"
android:priority="360"/>
<permission android:name="android.permission.MICROPHONE"
android:permissionGroup="android.permission-group.MICROPHONE"
android:protectionLevel="dangerous"
android:label="label" />
I've also tried getting the access through code:
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission_group.MICROPHONE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission_group.MICROPHONE},
REQUEST_MICROPHONE);
}
The alert doesn't show to grant access.
I still don't have access to microphone. Anyone know how get permission for the microphone?
Note: This is only not working for Android M
To request microphone, you should be requesting Manifest.permission.RECORD_AUDIO instead of the permission group Manifest.permission_group.MICROPHONE.
So, remove the tags <permission/> and <permission-group/> in the Manifest because they are to indicate that your want to create new permissions rather than use them.
Then to request the permission just do this:
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.RECORD_AUDIO},
REQUEST_MICROPHONE);
}

Android 6.0 bug ? Have permission but getScanResults() still return empty list in Android 6.0

I have request the permission in android version 6.0 - Marshmallow,But it still return empty list when using getScanResults().
private boolean checkPermission() {
List<String> permissionsList = new ArrayList<String>();
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (permissionsList.size() > 0) {
ActivityCompat.requestPermissions((Activity) mContext, permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
After request permission, then in the onRequestPermissionsResult method,I have get the permission of ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, But I still can not the scan result
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
if (permissions.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED ||
(permissions.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
grantResults[1] == PackageManager.PERMISSION_GRANTED)){
List<ScanResult> scanResults = mWifi.getScanResults();
//list is still empty
}
else {
// Permission Denied
Toast.makeText(mContext, getString(R.string.permission_deny), Toast.LENGTH_LONG).show();
}
break;
}
}
Is this a bug of android M?
You still need to enable WIFI after you request the permission. So in short, you have to do this in sequence for scanning the perimeter:
Request the necessary permissions (ACCESS_WIFI_STATE, CHANGE_WIFI_STATE, ACCESS_COARSE_LOCATION). Additionally, on MM you need to request this at run-time, as you stated.
Enable WIFI with WifiManager#setWifiEnabled(true);
You don't have to enable location access programatically that I know off. But read the note below.
You have to register a BrodcastReceiver for SCAN_RESULTS_AVAILABLE_ACTION. This is where you get the signal that the scans are ready. Doesn't matter if you register through AndroidManifest or dynamically at run-time, as long as it's done before the next step.
You have to WifiManager#startScan() in order to request exactly ONE update for network scans. If you want more, set up a timer/timertask (recommended) or reschedule when you receive the previous one (which might never come)
Only on the BroadcastReceiver onReceive will you be able to call WifiManager#getScanResults() with plausible results.
Note: On some phones (Moto X 2014), I noticed you need basic location enabled to get any results, which only the user (system UI) seems to be able to do trigger on/off. If the user has location completely off, I can't seem to get a non-empty result list, even though the system UI can. This is likely due to Marshmallow needs to have location for Bluetooth and WiFi scans in user apps, and a bad implementation by Motorola, or a defect already fixed in latest Marshmallow bug tracker but not in Motorola's latest OTA, because this doesn't happen in a Nexus 5 or a Galaxy S6.
on nexus 5, with M update, it appears to me I also need to have GPS location turned on to get this working.
Maybe it cause by android M's runtime permission management,you can set targetSdkVersion 19(less than 21 or 23) to try again. It works for me
In Android Marshmallow 6.0.1 go to Settings > Connections and hold down Location. There click on Location method and you will see three options:
High accuracy: uses GPS, Wi-Fi and mobile networks.
Battery saving: uses Wi-Fi and mobile networks.
Device only: uses GPS.
Select Battery saving in order to get Wi-Fi scan results without enabling GPS.
The permission is requested when needed at run-time. Note that it is NOT:
Settings -> Location
It is checking:
Settings -> Applications -> (YOUR APP) -> Permissions
That is where the more granular run-time permission must be set. It must be set for each application as of version 6.

Android M User Permission Error - READ and WRITE

I just started off with android M and I am unable to access the external storage. I get the following error
Caused by: java.lang.SecurityException: Permission Denial: reading
com.android.providers.media.MediaProvider uri
content://media/external/images/media from pid=15355, uid=10053 requires
android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
I am adding user-permission in manifest like
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and my build file is with following settings :
compileSdkVersion 23
buildToolsVersion "22.0.1"
minSdkVersion 16
targetSdkVersion 23
How to read and write from external storage in android M?
Reading from the documentation. I have to ask user for permission at runtime. Code example :
Add permission to android manifest like we used to do earlier :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Check if the user has already granted the permission. If yes, skip asking for permission and continue with your work flow else ask user for permission :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.System.canWrite(this)) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 2909);
} else {
// continue with your code
}
} else {
// continue with your code
}
Now to check if the user granted the permission or denied it #Override OnRequestPermissionResult to get a callback :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 2909: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e("Permission", "Granted");
} else {
Log.e("Permission", "Denied");
}
return;
}
}
}
I was not able to READ external storage only by asking WRITE
permission, so i had to request for
Manifest.permission.READ_EXTERNAL_STORAGE as well.
Also if you want to target versions below api 23, check the Build
VERSION at runtime with IF statement and ask for permissions only if
VERSION is equal or above Android M.
In case you are looking for a way to handle in any android version (you are compiling for M, but some devices can be using other versions) there is a compatibility version.
if (ContextCompat.checkSelfPermission(CreatePlayerActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(CreatePlayerActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
// 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(CreatePlayerActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
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.
}
}
In regards to the selected answer:
Settings.System.canWrite(this) and WRITE_EXTERNAL_STORAGE are two very different things! Should be:
boolean needsRead = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED;
boolean needsWrite = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED;
if (needsRead || needsWrite)
requestStoragePermission()
I was struggling with WRITE_EXTERNAL_STORAGE permission: after I requested it, the dialog didn't show up and immediately returned DENIED.
The problem was in one of the included libraries. It contained the same permission declaration in its AndroidManifest.xml, but with maxSdkVersion="22". The declaration in application's manifest file was overridden by the library.
To override permission from the library I used the following:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:node="remove"
tools:selector="com.example.lib" />
I hope this might be helpful.
I used this utility on github. It works with with both API 22 and 23. Adding runtime permissions is not hard but having to seperate your code and move the methods around to capture callbacks is a little pain. This library provides a chained api to do all you need to do for supporting runtime permissions.
https://github.com/kayvannj/PermissionUtil

Categories

Resources