File.mkdirs() returns false even with permissions - java

I've got the following code:
private int REQUEST_CODE_PERMISSIONS = 1001;
private final String[] REQUIRED_PERMISSIONS = new String[]{"android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE"};
public String getBatchDirectoryName() {
String app_folder_path = "";
if(allPermissionsGranted()){
Log.e("i enter this code","!");
app_folder_path = Environment.getExternalStorageDirectory().toString() + "/images";
File dir = new File(app_folder_path);
if (!dir.exists() && !dir.mkdirs()) { //both are false but why?
Log.e("failed to create:",app_folder_path); ///returns: storage/emulated/0/images
}
}else{
app_folder_path = "fail"; // i DONT enter this code t
}
return app_folder_path;
}
private boolean allPermissionsGranted(){
for(String permission : REQUIRED_PERMISSIONS){
if(ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
I am trying to save a image so I use the function getBatchDirectoryName() to create a directory if it does not exsist,or else returning the exsisting directory.
The issue is that, the directory does not exsist I cant create it for some reason. Both functions exists and mkdirs return false.
What can the cause be? I check before If I have the permission for writing files.

Related

Android root detection not working with mentioned code

I'm using following code for root detection in Android device. But still my security expert saying it can be installed and run in rooted device. Could someone detect what the issue with my code
public static boolean isDeviceRooted() {
// get from build info
String buildTags = android.os.Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys")) {
return true;
}
return checkFiles() || checkLocations();
}
private static boolean checkFiles(){
String[] files = {
"/system/app/Superuser.apk",
"/system/etc/init.d/99SuperSUDaemon",
"/dev/com.koushikdutta.superuser.daemon/",
"/system/xbin/daemonsu"
};
for (String fileData : files) {
try {
File file = new File(fileData);
if (file.exists()) {
return true;
}
} catch (Exception e1) {
// ignore
}
}
return false;
}
private static boolean checkLocations(){
String su = "su";
String[] locations = {
"/system/bin/",
"/system/xbin/",
"/sbin/",
"/system/sd/xbin/",
"/system/bin/failsafe/",
"/data/local/xbin/",
"/data/local/bin/",
"/data/local/",
"/system/sbin/",
"/usr/bin/",
"/vendor/bin/"
};
for (String location : locations) {
if (new File(location + su).exists()) {
return true;
}
}
return false;
}

Android Delete File Using URI not working

So what i want is to delete file using URI
Do not flag is duplicate
I tried many answer but nothing worked here is the question i tried
How to delete file that is created using Uri?
Delete file using Uri
How to delete file that is created using Uri?
I write code to get images from gallery and then copy it to directory called ".blackhat" and delete original one (Kind of Move File Function)..But it's not working. even it is not generation Log so i can check the error.
this code working proper for copying file but not deleting after copying....
if(requestCode == 2 && data.getData() !=null){
if(cd == null){
path.add(data.getData());
Random rn = new Random();
if(copyFileFromUri(this,data.getData(),String.valueOf(rn.nextInt(500)))){
File fdelete = new File(data.getData().getPath());
if (fdelete.exists()) {
if (fdelete.delete()) {
Log.d("delete","deleted");
} else {
Log.d("delete","not deleted");
}
}
Toast.makeText(this, "Done", Toast.LENGTH_SHORT).show();
}
}else{
for(int i=0;i<data.getClipData().getItemCount();i++){
path.add(data.getClipData().getItemAt(i).getUri());
Log.d("RjList",path.get(i).toString());
Random rn=new Random();
if(copyFileFromUri(this,data.getClipData().getItemAt(i).getUri(),String.valueOf(rn.nextInt(500)))){
File fdelete = new File(data.getClipData().getItemAt(i).getUri().getPath());
if (fdelete.exists()) {
if (fdelete.delete()) {
Log.d("delete","deleted");
} else {
Log.d("delete","not deleted");
}
}
Toast.makeText(this, "Done", Toast.LENGTH_SHORT).show();
}
}
}
}
Where am i doing wrong ????
Thank in advance...
public static boolean delete(final Context context, final File file) {
final String pathone = MediaStore.MediaColumns.DATA + "=?";
final String[] selectedArgs = new String[] {
file.getAbsolutePath()
};
final ContentResolver contentResolver = context.getContentResolver();
final Uri fileUri = MediaStore.Files.getContentUri("external");
contentResolver.delete(fileUri, pathone, selectedArgs );
if (file.exists()) {
contentResolver.delete(fileUri, pathone, selectedArgs );
}
return !file.exists();
}
File fdelete = new File(data.getData().getPath(),"here you should pass the file name");
if (fdelete.exists()) {
if (fdelete.delete()) {
Log.d("delete","deleted");
} else {
Log.d("delete","not deleted");
}
}

Google API v3 checking exist folder by passing folder name

I'm using google API v3 for check exist folder. If folder does not exist, then create the new folder. This is my code for creating folder
private void createFolderInDrive() throws IOException {
boolean existed = checkExistedFolder("MyFolder");
if (existed = false) {
File fileMetadata = new File();
fileMetadata.setName("MyFolder");
fileMetadata.setMimeType("application/vnd.google-apps.folder");
File file = mService.files().create(fileMetadata)
.setFields("id")
.execute();
System.out.println("Folder ID: " + file.getId());
Log.e(this.toString(), "Folder Created with ID:" + file.getId());
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
"Folder is existed already", Toast.LENGTH_SHORT).show();
}
}
and here is the code for checking exist file
private boolean checkExistedFolder(String folderName) {
//File file = null;
boolean existedFolder = true;
// check if the folder exists already
try {
//String query = "mimeType='application/vnd.google-apps.folder' and trashed=false and title='" + "Evacuation Kit" + "'";
String query = "mimeType='application/vnd.google-apps.folder' and trashed=false and name='Evacuation Kit'";
// add parent param to the query if needed
//if (parentId != null) {
//query = query + " and '" + parentId + "' in parents";
// }
Drive.Files.List request = mService.files().list().setQ(query);
FileList fileList = request.execute();
if (fileList.getFiles().size() == 0 ) {
// file = fileList.getFiles().get(0);
existedFolder = false;
}
} catch (IOException e) {
e.printStackTrace();
}
return existedFolder;
fileList.getFiles().size() keep returning 3, even there is no folder on g drive. Can you guys tell me where am I doing wrong?
In the code you show, checkExistedFolder is always looking for the name "Evacuation Kit" and not using the argument folderName. Maybe this is the main reason you're always getting 3 from fileList.getFiles().size().
Also there's an assignment in if (existed = false), you should use if ( false == existed ) -using the static value in the left side of the comparison helps avoiding such mistakes-, or if (!existed). Note that it's important to check the nextPageToken when calling Files:list to check if there is more pages to look for the file. See more here https://developers.google.com/drive/api/v3/reference/files/list and Create folder if it does not exist in the Google Drive
This code will check if folder exist on drive. if exists, it will return id else create folder and returns id.
private DriveFile file;
GoogleApiClient mGoogleApiClient;
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.e(TAG, "connected");
new Thread(new Runnable() {
#Override
public void run() {
DriveId Id = getFolder(Drive.DriveApi.getRootFolder(mGoogleApiClient).getDriveId(), "FOLDER_NAME");
Log.e(TAG, "run: " + Id);
}
}).start();
}
DriveId getFolder(DriveId parentId, String titl) {
DriveId dId = null;
if (parentId != null && titl != null) try {
ArrayList<Filter> fltrs = new ArrayList<>();
fltrs.add(Filters.in(SearchableField.PARENTS, parentId));
fltrs.add(Filters.eq(SearchableField.TITLE, titl));
fltrs.add(Filters.eq(SearchableField.MIME_TYPE, DriveFolder.MIME_TYPE));
Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();
MetadataBuffer mdb = null;
DriveApi.MetadataBufferResult rslt = Drive.DriveApi.query(mGoogleApiClient, qry).await();
if (rslt.getStatus().isSuccess()) try {
mdb = rslt.getMetadataBuffer();
if (mdb.getCount() > 0)
dId = mdb.get(0).getDriveId();
} catch (Exception ignore) {
} finally {
if (mdb != null) mdb.close();
}
if (dId == null) {
MetadataChangeSet meta = new MetadataChangeSet.Builder().setTitle(titl).setMimeType(DriveFolder.MIME_TYPE).build();
DriveFolder.DriveFolderResult r1 = parentId.asDriveFolder().createFolder(mGoogleApiClient, meta).await();
DriveFolder dFld = (r1 != null) && r1.getStatus().isSuccess() ? r1.getDriveFolder() : null;
if (dFld != null) {
DriveResource.MetadataResult r2 = dFld.getMetadata(mGoogleApiClient).await();
if ((r2 != null) && r2.getStatus().isSuccess()) {
dId = r2.getMetadata().getDriveId();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return dId;
}
The code working for me with updated API on Kotlin:
override fun createFolder(name: String): Task<GoogleDriveFileHolder> {
check(googleDriveService != null) { "You have to init Google Drive Service first!" }
check(search(name, FOLDER_MIME_TYPE).not()){"folder already exist"}
return Tasks.call<GoogleDriveFileHolder>(
mExecutor,
Callable<GoogleDriveFileHolder> {
val metadata = File()
.setMimeType(FOLDER_MIME_TYPE)
.setName(name)
GoogleDriveFileHolder(
googleDriveService!!.files()
.create(metadata)
.setFields("id")
.execute() ?: throw IOException("Null result when requesting file creation.")
)
})
}
private fun search(name: String, mimeType:String): Boolean {
var pageToken: String? = null
do {
val result: FileList =
googleDriveService!!
.files()
.list()
.setQ("mimeType='$FOLDER_MIME_TYPE'")
.setSpaces("drive")
.setFields("nextPageToken, files(id, name)")
.setPageToken(pageToken)
.execute()
for (file in result.files) {
Log.d(TAG_UPLOAD_FILE , "Found file: %s (%s)\n ${file.name}, ${file.id} ")
if (name == file.name) return true
}
pageToken = result.nextPageToken
} while (pageToken != null)
return false
}
private const val FOLDER_MIME_TYPE= "application/vnd.google-apps.folder"

How to change boolean in fucntion ussing mockito

So here is my class:
public class FileDeleter implements Deleter {
public void deleteDirectories(List<GroupOfCountries> organizedCountries, String path) {
List<String> listOfThreeLettersGroups = new ArrayList<String>();
for (GroupOfCountries groupedCountries : organizedCountries) {
listOfThreeLettersGroups.add(groupedCountries.getName()); //Here it's adding "ABC" and "PQR" to ArrayList because my countries are Albania, Belgium and Portugal.
}
for (String directoryToDelete : listOfThreeLettersGroups) {
String pathOfGorupDirectory = (path + File.separator + directoryToDelete); //Here it's creating paths to ABC and PQR directories, for example /home/test/ABC
File tempfile = createFile(pathOfGorupDirectory);
deleteDirectory(tempfile);
}
}
protected File createFile(String pathOfGorupDirectory) {
return new File(pathOfGorupDirectory);
}
private boolean deleteDirectory(File dir) {
if (dir.isDirectory()) {
File[] children = dir.listFiles();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDirectory(children[i]);
if (!success) {
return false;
}
}
}
return dir.delete();
}
}
I want to have 100% missed branches. If I comment these lines:
if (!success) {
return false;
}
I have 100% missed branches. But somebody have idea what can I do using mockito/junits to change success into false? Because success always returns true so this if will never happend.
Maybe this will help.
FileDeleter deleter = Mockito.mock(FileDeleter.class);
Mockito.when(deleter.deleteDirectory(Mockito.any())).thenReturn(false);

Get correct path to External SDCard in android

i am trying to get the correct path to the sd card that is inside my samsung s4 android device through my app but when i try the above paths:
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
String pathTwo = Environment.getExternalStorageDirectory().getAbsolutePath();
String path3 = getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
It gets the private none-writable path of /storage/emulated/0 instead of the correct path of storage/sdcard1
I found the correct path via File explorer using the Android Device monitor but i do not want to hard code the path as the path can be different depending on the device.
kind regards
For all devices
String sSDpath = null;
File fileCur = null;
for( String sPathCur : Arrays.asList( "MicroSD","external_SD","sdcard1","ext_card", "external_sd", "ext_sd", "external", "extSdCard", "externalSdCard")) // external sdcard
{
fileCur = new File( "/mnt/", sPathCur);
if( fileCur.isDirectory() && fileCur.canWrite())
{
sSDpath = fileCur.getAbsolutePath();
break;
}
if( sSDpath == null) {
fileCur = new File( "/storage/", sPathCur);
if( fileCur.isDirectory() && fileCur.canWrite())
{
sSDpath = fileCur.getAbsolutePath();
break;
}
}
if( sSDpath == null) {
fileCur = new File( "/storage/emulated", sPathCur);
if( fileCur.isDirectory() && fileCur.canWrite())
{
sSDpath = fileCur.getAbsolutePath();
Log.e("path",sSpath);
break;
}
}
}
100% working, tested on multiple device.
Based on a previous answer, the path to external SD card actually varies with different device manufactures.
"Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considered to be "external storage". On some devices, this is removable media, like an SD card. On some devices, this is a portion of on-device flash. Here, "external storage" means "the stuff accessible via USB Mass Storage mode when mounted on a host machine", at least for Android 1.x and 2.x.
But the question is about external SD. How to get a path like "/mnt/sdcard/external_sd" (it may differ from device to device)?
Android has no concept of "external SD", aside from external storage, as described above.
If a device manufacturer has elected to have external storage be on-board flash and also has an SD card, you will need to contact that manufacturer to determine whether or not you can use the SD card (not guaranteed) and what the rules are for using it, such as what path to use for it."
Based on this answer.
So, There is no absolute way to get this path via code.
As gilonm mentioned, external (removable) Sd path varies from device to device, but I wrote a method, which iterates through all the different ext paths that the different manufacturers use, and then it finds the exact match.
It returns empty String if path isn't found. If a path is found, you still need to verify whether the card is inserted or not. (By checking if sub-folders exist on that path)
Note: I used StreamSupport library inside the method, so you'll need to download the jar file and add it to libs folder of your project and that's it, it'll work!
public static String getExternalSdPath(Context context) {
List<String> listOfFoldersToSearch = Arrays.asList("/storage/", "/mnt/", "/removable/", "/data/");
final List<String> listOf2DepthFolders = Arrays.asList("sdcard0", "media_rw", "removable");
final List<String> listOfExtFolders = Arrays.asList("sdcard1", "extsdcard", "external_sd", "microsd", "emmc", "ext_sd", "sdext",
"sdext1", "sdext2", "sdext3", "sdext4");
final String[] thePath = {""};
Optional<File> optional = StreamSupport.stream(listOfFoldersToSearch)
.filter(new Predicate<String>() {
#Override
public boolean test(final String s) {
File folder = new File(s);
return folder.exists() && folder.isDirectory();
}
}) //I got the ones that exist and are directories
.flatMap(new Function<String, Stream<File>>() {
#Override
public Stream<File> apply(final String s) {
try {
List<File> files = Arrays.asList(new File(s).listFiles());
return StreamSupport.stream(files);
} catch (NullPointerException e) {
return StreamSupport.stream(new ArrayList<File>());
}
}
}) //I got all sub-dirs of the main folders
.flatMap(new Function<File, Stream<File>>() {
#Override
public Stream<File> apply(final File file1) {
if (listOf2DepthFolders.contains(file1.getName()
.toLowerCase())) {
try {
List<File> files = Arrays.asList(file1.listFiles());
return StreamSupport.stream(files);
} catch (NullPointerException e) {
return StreamSupport.stream(Collections.singletonList(file1));
}
} else
return StreamSupport.stream(Collections.singletonList(file1));
}
}) //Here I got all the 2 depth and 3 depth folders
.filter(new Predicate<File>() {
#Override
public boolean test(final File o) {
return listOfExtFolders.contains(o.getName()
.toLowerCase());
}
})
.findFirst();
optional.ifPresent(new Consumer<File>() {
#Override
public void accept(final File file) {
thePath[0] = file.getAbsolutePath();
}
});
Log.e("Path", thePath[0]);
try {
ContextCompat.getExternalFilesDirs(context, null);
} catch (Exception e) {
Log.e("PathException", thePath[0]);
}
return thePath[0];
}
P.S. I tested and verified it on a few HTC and Samsung devices.
This function will return the path of SD Card path.
private String getExternalSdCard(){
String finalPath = null;
File sdCardFile = ContextCompat.getExternalFilesDirs(this, null)[1];
String base = String.format("/Android/data/%s/files", getPackageName());
String path = sdCardFile.getAbsolutePath();
if(path.contains(base)){
finalPath = path.replace(base, "");
}
return finalPath;
}
To get all the list of storage. Use Loop
private String[] storages() {
List<String> storages = new ArrayList<>();
try {
File[] externalStorageFiles = ContextCompat.getExternalFilesDirs(this, null);
String base = String.format("/Android/data/%s/files", getPackageName());
for (File file : externalStorageFiles) {
try {
if (file != null) {
String path = file.getAbsolutePath();
if (path.contains(base)) {
String finalPath = path.replace(base, "");
if (validPath(finalPath)) {
storages.add(finalPath);
}
}
}
} catch (Exception e) {
CrashUtils.report(e);
}
}
} catch (Exception e) {
CrashUtils.report(e);
}
String[] result = new String[storages.size()];
storages.toArray(result);
return result;
}

Categories