I'm trying to create a simple app that can get an image from the Gallery app and display it on an imageButton. I'm testing with API 21 on a phone running Android 5.0.1. Unfortunately, no matter what I try I keep getting a security error - even when I specify the permissions.
My code for getting retrieving the image is:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent){
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch(requestCode){
case PICK_IMAGE_REQUEST:
if(resultCode == RESULT_OK && imageReturnedIntent != null && imageReturnedIntent.getData() != null) {
Uri uri = imageReturnedIntent.getData();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
// Log.d(TAG, String.valueOf(bitmap));
ImageButton ib = (ImageButton) findViewById(R.id.inputImg);
ib.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
break;
}
}
The code works when I try to select an image from Dropbox, but when I select an image from gallery, I get
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/35634 from pid=25240, uid=10070 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
I made the use-permission tag for READ_EXTERNAL_STORAGE a child of manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="[REDACTED]">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<uses-permission tools:node="replace" android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="18" />
<application>
[REDACTED]
</application>
</manifest>
I've searched high and low on other posts, but still can't seem to figure out why I'm still getting this pesky error.
PROBLEM
Your have the error
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/35634 from pid=25240, uid=10070 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission().
CAUSE
You are not giving correctly permissions because of android:maxSdkVersion="18", which according to documentation.
The highest API level at which this permission should be granted to your app. Setting this attribute is useful if the permission your app requires is no longer needed beginning at a certain API level.
As long as you didn't give permissions to API 21 your app is behaving ok.
Check this topic for further info.
SOLUTION
If you wanna give read permissions under API 21, you must declare them as:
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="21" />
IMPORTANT:
This only make sense when you need to give extra permissions because some old api's require permissions that new versions doesn't, so user experience get's improved because you only ask for certain permissions when needed.
So (in this case) the correct way will be:
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
ADD ON
If you want to save data you must add WRITE_EXTERNAL_STORAGE permissions.
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Simply replace with the below one and try,
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
While debugging on some devices you need to grant permission explicitly by going to your settings --> apps --> MY_APPLICATION --> Permissions and then grant required permissions.
In addition to adding the below in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
we also need to request permission in the activity for the app to actually have access to external storage. https://developer.android.com/training/permissions/requesting.html
Related
I am working on a bluetooth application. When I run the app on my phone and press the button that is supposed to run the startDiscovery() method, it works fine for me. But when I try the same thing on another phone, it doesn't work. It does not start searching for devices. Both phones run Android 11.
This is the code I have:
btnSearch.setOnClickListener(new View.OnClickListener() {
#SuppressLint("MissingPermission")
#Override
public void onClick(View v) {
enableBt();
txtStatus.setText("Searching...");
btnSearch.setEnabled(false);
btnCancel.setVisibility(View.VISIBLE);
pbLoading.setVisibility(View.VISIBLE);
deviceList.clear();
addresses.clear();
setAdapter();
bluetoothAdapter.startDiscovery();
}
});
I have all the necessary permissions written in the AndroidManifest file:
<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" />
I request from user for ACCESS_FINE_LOCATION permission in MainActivity.java. Which should also automatically allow ACCESS_COARSE_LOCATION.(right?). Both phones get location permission request, and both phones get bluetooth enable request, but only one scans for other bluetooth devices when the btnSearch is pressed.
I tried to ask for BLUETOOTH_SCAN which isn't required for android 11 if I'm right. And I am pretty much out of ideas.
I want to load an image but I got this error:
/storage/emulated/0/productss/Montearci_products/Bracelets/airplane/Brac - 020.jpg: open failed: EACCES (Permission denied)
The file is exist.
My codes:
Picasso.get().setLoggingEnabled(true);
Picasso.get().load(muri).into(mimg);
my android version is 10.
my permissions:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
I just added this line to application:
android:requestLegacyExternalStorage="true"
I don't know but for android 10 it should be added !
First Option that you should take care of is Permision -
For API 23+ you need to request the read/write permissions even if they are already in your manifest file cause these are considered dangerous permissions
// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
/**
* Checks if the app has permission to write to device storage
*
* If the app does not has permission then the user will be prompted to grant permissions
*
*
*/
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
Second Option that you can try is :-
According to Picasso docs you have to do something like this: file:///android_asset/DvpvklR.png
So I used to have:
/storage/sdcard/Pictures/findyoursport/yoursport_1482358052384.jpeg
Prepending: file:// did the trick
Third - If you're running this on Android 10 or higher then use this->
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
I hope it will work
Maybe you should add request for FileSystem permission
You might be missing the following permissions in your Manifest to be able to read from SD Card:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I'm following the File transfer example on the Nearby Connections Exchange page (the "more complex example" code snippet).
I can send an image and receive it on another device in the Download/Nearby folder. The image is sent successfully since if I were to change the file name to give it an appropriate extension (e.g. .jpg), I can open the image in a photo gallery app.
private void processFilePayload(long payloadId) {
Payload filePayload = completedFilePayloads.get(payloadId);
String filename = filePayloadFilenames.get(payloadId);
if (filePayload != null && filename != null) {
completedFilePayloads.remove(payloadId);
filePayloadFilenames.remove(payloadId);
// Retrieve received file from Downloads folder
Payload.File payloadFile2 = filePayload.asFile();
File payloadJavaFile = payloadFile2.asJavaFile();
if (payloadJavaFile == null) {
Log.d(TAG, "Payload java file is null in processFilePayload()");
} else {
payloadJavaFile.renameTo(new File(payloadJavaFile.getParentFile(), filename));
}
}
}
Why is the payloadJavaFile variable null? From looking at Payload.class, I know that the result of asJavaFile() is a nullable File and that, from the asJavaFile() method description, calling asJavaFile() in processFilePayload() from within onPayloadReceived() (as is done in the example on the API page) may lead to the File not having received all of the payload's contents yet. However, I also call processFilePayload() from within onPayloadTransferUpdate() after verifying the success of the PayloadTransferUpdate, and so shouldn't the payload have received all of its contents by this stage (and not be null when calling asJavaFile() on the payload object)?
My code is almost the same as the documentation for both sending and receiving the image and file name.
Payload.asJavaFile() will be null if the READ_EXTERNAL_STORAGE permission is not properly set up for your application. You need READ_EXTERNAL_STORAGE in the AndroidManifest.xml and you need to also request READ_EXTERNAL_STORAGE permission at runtime since it is a dangerous permission. (https://developer.android.com/training/permissions/requesting)
To share files using Nearby Connections, your application will need all of the following:
AndroidManifest.xml
<!-- Required for Nearby Connections -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Optional: needed to share files -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
MainActivity.java
ActivityCompat.requestPermissions(thisActivity,
new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE
},
PERMISSIONS_REQUEST_CODE);
We will improve the documentation to make this requirement for sharing files more obvious.
I checked the source code. From what I can see, asJavaFile() is always set (and I'm not sure why it's marked as #Nullable).
Unfortunately, for me to look into it any further, I'd need you to provide me with a sample app that reproduces the bug you're seeing.
I've a strange android permission denial, here is it:
java.lang.SecurityException: Permission Denial: isUserRunning() from pid=1078, uid=10284 requires android.permission.INTERACT_ACROSS_USERS
I haven't found anything about android.permission.INTERACT_ACROSS_USERS only android.permission.INTERACT_ACROSS_USERS_FULL
Here is the full logcat:
java.lang.SecurityException: Permission Denial: isUserRunning() from pid=25403, uid=10310 requires android.permission.INTERACT_ACROSS_USERS
at android.os.Parcel.readException(Parcel.java:1693)
at android.os.Parcel.readException(Parcel.java:1646)
at android.app.ActivityManagerProxy.isUserRunning(ActivityManagerNative.java:7000)
at android.os.UserManager.isUserUnlocked(UserManager.java:1069)
at android.os.UserManager.isUserUnlocked(UserManager.java:1063)
at com.android.launcher3.compat.UserManagerCompatVN.isUserUnlocked(UserManagerCompatVN.java:39)
at com.android.launcher3.LauncherModel$LoaderTask.loadWorkspace(LauncherModel.java:1759)
at com.android.launcher3.LauncherModel$LoaderTask.loadAndBindWorkspace(LauncherModel.java:1387)
at com.android.launcher3.LauncherModel$LoaderTask.run(LauncherModel.java:1486)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
I've added this to my manifest:
<permission android:name="android.permission.INTERACT_ACROSS_USERS" android:protectionLevel="signature"/>
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature"/>
TL;DR; Either this stack trace does not belong to your application or you need a permission that you don't have. To know about those permissions read the rest.
Although Michele probably has found the answer, I've decided to answer this question as it might be useful for others. Mentioned permissions are signature|system level permissions. To read more about different types of permissions read this: Permissions overview
Basically these permissions are needed to use multi-user APIs such as:
Context.startActivityAsUser(Intent, UserHandle)
Context.bindServiceAsUser(Intent, …, UserHandle)
Context.sendBroadcastAsUser(Intent, … , UserHandle)
Context.startServiceAsUser(Intent, …, UserHandle)
To know more, read this: Supporting Multiple Users and this: Building Multiuser-Aware Apps
Due to the error, Michele has come to this conclusion that he has to add these permissions to manifest (which we will see how it is possible for an application to have these permissions granted), but instead, he has defined these permissions(to know more about defining a permission read this: Define a Custom App Permission):
<permission android:name="android.permission.INTERACT_ACROSS_USERS" android:protectionLevel="signature"/>
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature"/>
I think you will end up seeing a run time error because you can't define these permissions since they have the same name as two system permission that are already defined. Want to be sure? Take a look at a part of a real system manifest:
<!-- #SystemApi #hide Allows an application to call APIs that allow it to do interactions
across the users on the device, using singleton services and
user-targeted broadcasts. This permission is not available to
third party applications. -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS"
android:protectionLevel="signature|system|privileged" />
<!-- #hide Fuller form of {#link android.Manifest.permission#INTERACT_ACROSS_USERS}
that removes restrictions on where broadcasts can be sent and allows other
types of interactions. -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
android:protectionLevel="signature" />
You see in this manifest file of an android system, these permissions are defined already and to use them we should use the tag.
So now lets talk how theses permissions might be granted to your application. In my experience OEMs define system manifest in a way that these permissions could be granted to
Apps which have the same signature as the system(practically only apps which are developed by the OEM)
Privileged apps being under the /system/priv-app.
In the system manifest I mentioned above the second permission is only defined as signature so only apps with the same signature as system can have those permissions granted.
If you have write access on a device (probably it should be rooted, I don't know much about that), you can copy your apk in the priv-app folder by this command:
adb push path-to-your-app/your-app.apk /system/priv-app
Is that all? Not yet!
Since android 8.0 there are some complications about permissions being granted to applications under priv-app that you can read about it here: Privileged Permission Whitelisting
You should implement permission request at run-time in Android, specifically for Marshmallow or higher version.
If you don’t implement run-time permission, then your application will crash or will not work properly on the device having Marshmallow.
I hope you are now pretty much aware with Runtime Permission concept in Marshmallow. Let’s understand this code:
int currentAPIVersion = Build.VERSION.SDK_INT;
if(currentAPIVersion>=android.os.Build.VERSION_CODES.M)
{
if (ContextCompat.checkSelfPermission(context, Manifest.permission.INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.INTERACT_ACROSS_USERS)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setTitle("Permission necessary");
alertBuilder.setMessage("Interact across users permission is necessary to this app");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.INTERACT_ACROSS_USERS}, MY_PERMISSIONS_REQUEST_INTERACT_ACROSS_USERS);
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
} else {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.INTERACT_ACROSS_USERS}, MY_PERMISSIONS_REQUEST_INTERACT_ACROSS_USERS);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_INTERACT_ACROSS_USERS:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do something here...
Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_SHORT).show();
} else {
//code for deny
Toast.makeText(getApplicationContext(), "Permission denied", Toast.LENGTH_SHORT).show();
}
break;
}
}
I am developing an android app that is implementing the Wifi P2P framework ...the user-permissions are set on the Manifest.xml as follow:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
.. and, I believe, the P2P service is enabled once I start my app (and on resume) ...
and I do not want that anymore ...i.e.: enabling the P2P service automatically ..
I want to be able to set a ToggleButton that enables or disables these permissions from within my MainActivity.java file. here is my ToggleButton code:
public void onToggleClicked(View view) {
Button btnDiscover = (Button) findViewById(R.id.btnDiscover);
boolean on = ((ToggleButton) view).isChecked();
if (on) {
// Enable the P2P service
} else {
}
}
How can I do this ?
P.S: I am new to android and Java programming
No. The user needs to be informed about the permissions while installing the application. Askling them at runtime would be a security risk. And google doesn't like possible security-leaks.
Instead of changing the permissions dynamically...Use a boolean variable. If it true proceed other wise don't proceed further...the variable default value is false