I am trying to access the device photo gallery, I can successfully access the camera and take a photo, however the access to gallery appears to be denied, even though Camera, Photos And Videos permission have been granted.
Here is the method used for the click on accessing gallery;
I am testing using Android 13 device (Oppo X3)
Targeting SDK 32 = Works fine
Targeting SDK 33 = Error
case R.id.relativeLayoutEditor:
String[] arrPermissionsEdit = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.CAMERA",
"android.permission.READ_MEDIA_IMAGES"
};
if (Build.VERSION.SDK_INT >= 29) arrPermissionsEdit = new String[] {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.READ_MEDIA_IMAGES"
};
Dexter.withContext(HomeActivity.this).withPermissions(arrPermissionsEdit).withListener(new MultiplePermissionsListener() {
public void onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
if (multiplePermissionsReport.areAllPermissionsGranted()) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
String[] mimetypes = {
"image/*"
};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, IMAGE_GALLERY_REQUEST);
}
if (multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
DetailsDialog.showDetailsDialog(HomeActivity.this);
}
}
public void onPermissionRationaleShouldBeShown(List < PermissionRequest > list, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).withErrorListener(dexterError -> Toast.makeText(HomeActivity.this, "Error occurred! ", Toast.LENGTH_SHORT).show()).onSameThread().check();
return;
Related
I am new to android dev and little knowledge of java.I want to know how to inflate a layout from service using SYSTEM_ALERT_WINDOW
public void checkDrawOverlayPermission() {
/* check if we already have
permission to draw over
other apps */
if(android.os.Build.VERSION.SDK_INT > 23) {
if (!Settings.canDrawOverlays(this))
{
/* if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
/* request permission via start activity for result */
startActivityForResult(intent, REQUEST_CODE);
}
else {
createOnTopView();
}}}}
I used that to get permission↑↑↑
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
/* check if received result code
is equal our requested code for draw permission */
if (requestCode == REQUEST_CODE && android.os.Build.VERSION.SDK_INT > 22) {
/* if so check once again if we have permission */
if (Settings.canDrawOverlays(this)) {
createOnTopView();
}
}
}
after I run this on my phone Teckno k7 ,android 6.0
It runs well buh can't run on my friend's phone Techno F2.it crashes on his phone.
Please help me.
I need to get the MANAGE_ALL_FILES_ACCESS_PERMISSION to be able to download and install APK's from my application.
When I was targeting SDK 27 and lower, everything worked fine, when I declared
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
in the manifest and asked for permission with ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
But now I need to target SDK 30, meaning that WRITE_EXTERNAL_STORAGE is deprecated and not working for API versions 29 and 30.
I have been trying to find a workaround and one that I could think of was starting the Intent to allow users to switch the permission on by themselves but I cannot get it to work.
The code I am using:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri);
startActivity(intent);
} catch (Exception ex){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
100);
}
And the error that I get when trying to open intent:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION }
The error comes from the catch block but the Exception ex gives the same error.
What am I doing wrong or is this just not allowed on the current phone I am using (XCover 4s Android 10).
The answer to getting the storage permission that worked for me.
I had to change the Manifest.permission. strings so instead of what was written in the question I used.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(
activity,
new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
},
1
);
} else {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
100);
}
Or similarly this could be used :
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
Then to get the prompt to allow user to install Apps from unkown sources :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!activity.getPackageManager().canRequestPackageInstalls()) {
activity.startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(Uri.parse(String.format("package:%s", activity.getPackageName()))), 1234);
} else {
}
}
I had this problem when I was trying to navigate the user to enable all files access permission on the app screen directly.
Solution for this one is to add the package name like this:
val storageIntent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
Uri.parse("package:$packageName"))
I going to change some system setting in android and i use this code :
ContentResolver cr = getContentResolver();
Settings.System.putInt(cr, Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
this code used for change screen Brightness use Brightness sensor,
but in android 6 I get this exception
java.lang.SecurityException: com.vpn.sabalan was not granted this permission: android.permission.WRITE_SETTINGS.
i can use this method to get permission from user , but i need get permission programmetically can any one help me ?
private void showBrightnessPermissionDialog( )
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !android.provider.Settings.System.canWrite(this))
{
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:"+getPackageName()));
startActivity(intent);
}
}
Update Android Marshmallow and Higher
You can start System settings to grant Write System Settings. Once this permission is grant by user you can set brightness without any issues
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
}
Follow the step by step provided in documentation. It is very thorough.
https://developer.android.com/training/permissions/requesting.html
All you have to do is request permission, and override the callback for onRequestPermissionsResult to check if you got it or not. If you did, then you are good to go. You still need it in your manifest though or it won't work.
UPDATE to show details based on your comments.
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback{
private static final int REQUEST_WRITE_PERMISSION = 1001;
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doFileWork();
}else{
//handle user denied permission, maybe dialog box to user
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermission();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
} else {
doFileWork();
}
}
}
There are also many good libraries out there that wrap this callback context if you really want to go that route, but it isn't that complex. Make sure you also have write permission in your Manifest.
Below code is working fine on pre-Marshmallow devices but not in Marshmallow.
These are the permissions in Manifest
<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" />
Here is the code
public void saveImageToSDCard(Bitmap bitmap) {
File myDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
pref.getGalleryName());
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Wallpaper-" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
Uri uri = getImageContentUri(_context,file);
Log.d(TAG, "Wallpaper saved to: " + file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
And the same code works when I manually allow the storage permission
Here is the solution given by Nitesh Pareek.
private boolean hasPermissions(Context context, String[] permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 11);
return;
}
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
This is why it works in pre-lolipop versions, and doesn't on API 23. Permissions in Android Manifest alone are not enough, you need to add them at runtime as well. Refer here for more details.
give read write permissions on run time for marshmallow or newer version.
Do like below:-
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 11);
return;
}
private boolean hasPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
You need to take application permissions at runtime instead of taking when install/update as convention
Beginning in Android 6.0 (API level 23), users grant permissions to
apps while the app is running, not when they install the app. This
approach streamlines the app install process, since the user does not
need to grant permissions when they install or update the app
For more help: Requesting Permissions at Run Time
By focusing on the documentation and after doing some google searches, finally I have compiled the code below to handle runtime permissions efficiently
To make it work, you need to follow the instructions below:
Call this method to check if storage permission is granted by user?
If not, then you need to request for it
public static boolean isStoragePermissionGranted(Activity activity) {
boolean flag = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
flag = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
return flag;
}
Call this method to request storage permission
public static void requestStoragePermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isStoragePermissionGranted(activity)) {
return;
}
// Fire off an async request to actually get the permission
// This will show the standard permission request dialog UI
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_STORAGE_PERMISSION);
}
}
Implement this method in your activity to handle response of permission callback
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE_STORAGE_PERMISSION:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
boolean shouldShowRationale = shouldShowRequestPermissionRationale(permissions[0]);
if (!shouldShowRationale) {
// user denied flagging NEVER ASK AGAIN, you can either enable some fall back,
// disable features of your app or open another dialog explaining again the permission and directing to
// the app setting
dialogReasonStoragePermissionToSettings(this);
} else if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0])) {
// user denied WITHOUT never ask again, this is a good place to explain the user
// why you need the permission and ask if he want to accept it (the rationale)
dialogReasonStoragePermission(this);
}
} /*else {
// Do on permission granted work here
}*/
}
}
break;
}
}
public static void dialogReasonStoragePermission(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(R.string.reason_storage_permission));
builder.setCancelable(false);
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
requestStoragePermission(activity);
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
public static void dialogReasonStoragePermissionToSettings(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(R.string.reason_storage_permission));
builder.setCancelable(false);
builder.setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
goToAppDetailsForPermissionSettings(activity);
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private static final int REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING = 3995;
private static void goToAppDetailsForPermissionSettings(Activity activity) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING);
}
I am not providing you direct code for this but here is a reason API level 23 introduce a new Permission structure for more security below is a short but wast description of thing, in documentation here
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
Code is good just you have to put something additional and that is Runtime Permissions for storage.
Read this blog to know everything from deep inside about Runtime Permissions gave me a clear picture about it, hope it helps you too.
Thanks
In my activity, I have the following code:
public void myMethod() {
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "MyDir" + File.separator);
root.mkdirs();
final String fname = "img_" + System.currentTimeMillis() + ".jpg";
outputFileUri = Uri.fromFile(new File(root, fname));
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePhotoIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, outputFileUri);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 232);
startActivityForResult(takePhotoIntent, 1);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 232) {
myMethod();
} else {
System.out.println("returned...");
ImageView imageView = (ImageView) findViewById(R.id.test_image_view);
imageView.setImageURI(outputFileUri);
}
}
My test device is a rooted nexus 6 on Android 6.0.1. When "myMethod" is called, it lets me take the photo, but upon returning to the activity I get the following error:
java.io.FileNotFoundException: /storage/emulated/0/MyDir/img_1466772411267.jpg: open failed: EACCES (Permission denied)
I have the valid permissions declared in my manifest:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera"/>
This error happens on the end of the method (I guess because the prior takes some time to throw the error?) Anyway, from what I see, I appear to be doing things the way I should be. Does anything seem off?
Your code will work till Android 5.0 but not in marshmallow os.
As Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app even though you had given permission in manifest file.
So app need to ask permission from user at runtime and if user does not give that permission you will get permission denial error. So you have to manage code for that.
Refer following link for more details:
https://developer.android.com/training/permissions/requesting.html
Runtime Permissions for Android 6.0
private static final int REQUEST_RUNTIME_PERMISSION = 1;
void checkPremission() {
//select which permission you want
final String permission = Manifest.permission.CAMERA;
//final String permission = Manifest.permission.Storage;
// if in fragment use getActivity()
if (ContextCompat.checkSelfPermission(ActivityName.this, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(ActivityName.this, permission)) {
} else {
ActivityCompat.requestPermissions(ActivityName.this, new String[]{android.permission.CAMERA,android.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_RUNTIME_PERMISSION);
}
} else {
// you have permission go ahead
myMethod();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_RUNTIME_PERMISSION:
final int numOfRequest = grantResults.length;
final boolean isGranted = numOfRequest == 1
&& PackageManager.PERMISSION_GRANTED == grantResults[numOfRequest - 1];
if (isGranted) {
// you have permission go ahead
myMethod();
}else{
// you dont have permission show toast
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}