I tried to make some folder in my storage and store image from camera into it, but mkdirs always return false, already tried using mkdir and canWrite, but still the same
2020-02-12 09:32:44.043 22914-23146/example.com.absensiapp D/TET: Folder Not Exist
2020-02-12 09:32:44.047 22914-23146/example.com.absensiapp D/TET: Failed To Create Directory
Here is the code for making the folder and save the image from camera
String wholeFolderPath = fh.TRAINING_PATH + name;
File dir = new File(wholeFolderPath);
if(!dir.exists()) {
Log.d("TET", "Folder Not Exist");
//create new directory
if(dir.mkdirs())
fh.saveMatToImage(m, wholeFolderPath + "/");
else
Log.d("TET", "Failed To Create Directory");
}
else {
Log.d("TET", "Folder Exist");
//save the image to directory
fh.saveMatToImage(m, wholeFolderPath + "/");
}
Already put the permission in my manifest and main activity
Manifest :
<uses-permission android:name="android.permission.INTERNET" />
<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" />
Main Activity :
private static boolean hasPermissions(Context context, String... permissions) {
if (context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
private void checkPermission() {
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
}
Solve the problem. Downgrade my targetSdkVersion in build.gradle from 29 to 21
Related
I am working on a simple camera app whose pictures should only be visible in the app that created the pictures. I am testing with Samsung galaxy phone running on android 12. My snippets are in kotlin
I want to save to a directory that does not get scanned for media. However, I think I might have a permission problem trying to access the data directory such as "/data/user/0/com.example.demo.camerax/files/CameraXDemo/".
Whenever I attempt to save pictures, I get the error "Failed to write destination file"
// Mirror image when using the front camera
isReversedHorizontal = lensFacing == CameraSelector.DEFAULT_FRONT_CAMERA
}
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
// Options fot the output image file
val outputOptions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val extn = "beg"
val filename = System.currentTimeMillis()
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "$filename")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, oDir)
}
val contentResolver = requireContext().contentResolver
// Create the output uri
val contentUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
OutputFileOptions.Builder(contentResolver, contentUri, contentValues)
} else {
File(oDir).mkdirs()
val file = File(oDir, "${System.currentTimeMillis()}.jpg")
OutputFileOptions.Builder(file)
}.setMetadata(metadata).build()
This is the snippet that should create the directory above and save the pictures.
I have set my permissions in the Manifest file as follows
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
Android Marshmallow requires that the user will grant permission in order to make modifications. Here's how I implemented this
private val permissions = mutableListOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
add(Manifest.permission.ACCESS_MEDIA_LOCATION)
}
}
private val permissionRequest = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions.all { it.value }) {
onPermissionGranted()
} else {
view?.let { v ->
Snackbar.make(v, R.string.message_no_permissions, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.label_ok) { ActivityCompat.finishAffinity(requireActivity()) }
.show()
}
}
}```
Is there a better approach to hiding pictures taken
I want to delete a picture from gallery or photo apps from device according to its URI. I tried several approach around internet but no way found.
I called below method
deleteMethod(getPath(selectedImageUri));
These two method defination is here.
private void deleteMethod(String file_dj_path) {
File fdelete = new File(file_dj_path);
if (fdelete.exists()) {
if (fdelete.delete()) {
System.out.println("file Deleted :" + file_dj_path);
Toast.makeText(getApplicationContext(),
"file Deleted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
"file not Deleted", Toast.LENGTH_SHORT).show();
System.out.println("file not Deleted :" + file_dj_path);
}
}
}
public String getPath(Uri uri) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(uri, projection, null, null, null);
if (cursor != null) {
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} else return null;
}
I add permission in manifest. Like,
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
My provider looks like:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path path="Android/data/com.***.calculator/"
name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>
i got uri like this:
:/storage/emulated/0/DCIM/Camera/IMG_20180804_181447.jpg
Am i missing anything?
Update:
I added runtime permission before run the code. After i run the code it always goes "file not Deleted" consists else block.
You also need to check if you have the permission and if not acquire it on RUNTIME. Asking for the permissions in your manifest file is not enough. You could use these two methods to see if you have permission to write and if not acquire it:
protected boolean checkPermission() {
int result1 = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result1 == PackageManager.PERMISSION_GRANTED ) {
return true;
} else {
return false;
}
}
protected void requestPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(this, "Write External Storage permission allows us to do store images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
}
}
}
Change like this
String path = selectedImageUri.getPath()
deleteMethod(path);
then deleteMethod inside
File file = new File(new URI(path));
if (fdelete.exists()) {
if (fdelete.delete()) {
System.out.println("file Deleted :" + uri.getPath());
} else {
System.out.println("file not Deleted :" + uri.getPath());
}
}
Well, since you say you also take the permission to write on runtime, perhaps you should use the setWritable() method after you have established the file exists and before trying to delete it.
After Android 6.0, some permissions are granted at runtime. You can use this code.
also, check https://developer.android.com/about/versions/marshmallow/android-6.0-changes
public boolean hasStoragePermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
return true;
} else {
Log.v(TAG,"Permission error");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v(TAG,"Permission is granted");
return true;
}
}
Following is a code I currently use to delete a downloaded apk programmatically.
final File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + giftapk);
if (file.exists()) {
if (file.delete()) {
System.out.println("file Deleted :" + file);
} else {
System.out.println("file not Deleted :" + file);
}
}
I want create new file and write/read app settings. isExternalStorageAvailable() return false and should true. Android emulator external memory = 200mb.
boolean isExternalStorageAvailable() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
return true;
}
return false;
}
Added permissions to manifest file:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
saveButton.setEnabled(false);
System.out.println("Available: "+isExternalStorageAvailable()+", ReadOnly: "+isExternalStorageReadOnly());
}
else {
myExternalFile = new File(getExternalFilesDir(filepath), filename);
}
}
To get all external storage paths this can be used:
File[] extSDCardPaths = null;
try {
extSDCardPaths = ContextCompat.getExternalFilesDirs(ctx, null);
} catch (Exception e) {
// handle
}
for (File f : extSDCardPaths) {
if (Environment.isExternalStorageRemovable(f)) {
// check if anything found
}
}
If extSDCardPaths returns something then ext storage is available.
The above works for > 4.4(KitKat) only
The below hack can be used as fallback for lower OS versions:
String[] fallback = {"/storage/sdcard1/", "/mnt/ext_card/", "/mnt/extSdCard/", "/storage/extsdcard/",
"/mnt/extsdcard/", "/storage/extSdCard/", "/mnt/external_sd", "/storage/MicroSD/",
"/storage/external_SD/", "/storage/ext_sd/", "/storage/removable/sdcard1/", "/mnt/sdcard/external_sd/",
"/storage/ext_sd/", "/mnt/emmc/", "/data/sdext/", "/sdcard/sd/"};
for (String path : fallback) {
if (new File(path).exists()) {
// found an ext. dir
break;
}
}
If your application is targeting and running on marshmallow or above, you must gain permission to read/write to external storage, you must request permission from user explicitly after declaring permission in manifest.
Make sure you have this in your manifest: <uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Check for permission explicitly. If not provided, request it:
public void checkPermissionReadStorage(Activity activity){
if (ContextCompat.checkSelfPermission(activity,
Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
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(activity,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_STORAGE);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
}
Receive permission response:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PermissionManager.MY_PERMISSIONS_REQUEST_READ_STORAGE:
//premission to read storage
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted. Call your storage related code here
} else {
// permission denied.
// Handle permission failed here.
}
return;
// other 'case' lines to check for other
// permissions this app might request
}
}
Code was taken from here
I am using this code in async to create directory if not exists in android with permissions. My code sucessfully works in android 5.1 but when i deployed app in android 7.0 the directory not created automatically
File sdcard = Environment.getExternalStorageDirectory() ;
File folder = new File(sdcard.getAbsoluteFile(), "Quoteimages");
if(!folder.exists()){
folder.mkdir();
}
Manifest file is
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
Link to detail of application apk App apk detail link
Now what should i do i want to create folder write images from url to it and then read them. This work for me in android 5.1 but not in Android version 7 .
You need to implement runtime permissions for android versions above lollipop
Maybe this piece of code will help you:
private static final int PERMS_REQUEST_CODE = 123;
//...........................................................................................................
private boolean hasPermissions(){
int res = 0;
//string array of permissions,
String[] permissions = new String[]
{android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
for (String perms : permissions){
res = checkCallingOrSelfPermission(perms);
if (!(res == PackageManager.PERMISSION_GRANTED)){
return false;
}
}
return true;
}
private void requestPerms(){
String[] permissions = new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(permissions,PERMS_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
boolean allowed = true;
switch (requestCode){
case PERMS_REQUEST_CODE:
for (int res : grantResults){
// if user granted all permissions.
allowed = allowed && (res == PackageManager.PERMISSION_GRANTED);
}
break;
default:
// if user not granted permissions.
allowed = false;
break;
}
if (allowed){
//user granted all permissions we can perform our task.
ListItem listItem = new ListItem();
Glide.with(getApplicationContext()).asBitmap().load(listItem.getImgurl()).into(new SimpleTarget<Bitmap>(){
#Override
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
FileOutputStream fileOutputStream = null;
File file = getDisc();
if(!file.exists()&& !file.mkdirs()){
Toast.makeText(getApplicationContext(),"Can't create directory to save image", Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat simpleDataFormat = new SimpleDateFormat("yyyymmsshhmmss");
String date = simpleDataFormat.format(new Date());
String name = "img"+date+".jpg";
String file_name = file.getAbsolutePath()+"/"+name;
File new_file= new File(file_name);
try {
fileOutputStream=new FileOutputStream(new_file);
resource.getHeight();
resource.getWidth();
resource.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
Toast.makeText(getApplicationContext(),"SAVED", Toast.LENGTH_LONG).show();
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
refreshGallery(new_file);
}
public void refreshGallery(File file){
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
}
private File getDisc(){
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(file, "FolderNamerYourChoice");
}
});
}
else {
// we will give warning to user that they haven't granted permissions.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(this, "Storage Permissions denied.", Toast.LENGTH_SHORT).show();
}
}
}
I am developing an SDK(.aar) which third parties can consume. In my sample application when I use the aar, I can see that the application doesnt prompt for the camera permission. When I open the aar and see its manifest.xm, it contains the below:
<!-- WRITE_EXTERNAL_STORAGE is needed because we are storing there the config files of KM -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.read_external_storage" />
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.sensor.accelerometer" />
Since the camera is present as a required permission can anyone tell me why it is not coming up when installing the sample app.
Since Android 6.0 you have to request the permssions at runtime and the user is not prompted at the time of installation.
https://developer.android.com/training/permissions/requesting.html
Here is how i check for permissions:
public boolean permissionsGranted() {
boolean allPermissionsGranted = true;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
boolean hasWriteExternalPermission = (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
boolean hasReadExternalPermission = (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
boolean hasCameraPermission = (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED);
if (!hasWriteExternalPermission || !hasReadExternalPermission || !hasCameraPermission) {
allPermissionsGranted = false;
}
}
return allPermissionsGranted;
}
This is how i make the request if permissionsGranted() method returns false
String[] permissions = {android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA, android.Manifest.permission.READ_EXTERNAL_STORAGE};
ActivityCompat.requestPermissions(this, permissions, 1);
And you have to override onRequestPermissionsResult method, below is what i have in mine.
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1: {
boolean startActivity = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults.length > 0 && grantResults[i] != PackageManager.PERMISSION_GRANTED) {
String permission = permissions[i];
boolean showRationale = shouldShowRequestPermissionRationale(permission);
if (!showRationale) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
intent.setData(uri);
startActivityWithIntent(intent);
Toast.makeText(this, "Enable required permissions", Toast.LENGTH_LONG).show();
startActivity = false;
break;
} else {
Toast.makeText(this, "Enable required permissions", Toast.LENGTH_LONG).show();
break;
}
}
}
if(startActivity) {
getActivity().finish();
startActivityWithIntent(getIntent());
}
}
}
}
public void startActivityWithIntent(Intent intent){
startActivity(intent);
}
showRationale is to check if user ticked never ask again, if so then i start the settings activity so that user can enable permissions.
Let me know if you need more clarity