I am doing a simple application that loads and saves files in java. I am trying to port it over to Android and am having trouble getting it to see the file.
The file path I am currently using is
private static final String SAVE_FILE_PATH = "data/save";
Here is the function that loads the data from the file:
public void loadData() throws FileNotFoundException {
File file = new File(SAVE_FILE_PATH);
Scanner scanner;
if (file.exists()) {
scanner = new Scanner(new FileInputStream(file));
try {
while (scanner.hasNextLine()) {
allPlayers.add(new Player(scanner.nextLine()));
}
} finally {
scanner.close();
}
}
else {
System.out.println("No file found");
}
} finally {
scanner.close();
}
}
}
While getExternalStorageDirectory() gets you the path to the SD card, consider using Activity.getExternalFilesDir() which will return (and create if necessary) a directory that's nominally private to your application. It also has the advantage that it will be auto-deleted for you if the application is uninstalled. This is new in API 8, so you might not want to use it if you're supporting older devices.
Otherwise, you'll have to follow ρяσѕρєя K's advice. Don't forget to create the storage directory you want to use. My code typically looks like this:
/**
* Utility: Return the storage directory. Create it if necessary.
*/
public static File dataDir()
{
File sdcard = Environment.getExternalStorageDirectory();
if( sdcard == null || !sdcard.isDirectory() ) {
// TODO: warning popup
Log.w(TAG, "Storage card not found " + sdcard);
return null;
}
File datadir = new File(sdcard, "MyApplication");
if( !confirmDir(datadir) ) {
// TODO: warning popup
Log.w(TAG, "Unable to create " + datadir);
return null;
}
return datadir;
}
/**
* Create dir if necessary, return true on success
*/
public static final boolean confirmDir(File dir) {
if( dir.isDirectory() ) return true;
if( dir.exists() ) return false;
return dir.mkdirs();
}
Now use this to specify your save file:
File file = new File(dataDir(), "save");
Scanner scanner;
if (file.exists()) {
// etc.
}
Related
I am not able get root path usb otg in Android Nougat working fine till marshmallow. even able to get root path of sd card .can any body help me out from this i am frustrated from couple days.
Here is my code that return root path upto marshmallow and nougat sdcard. but not usb otg
public static String FileSystem() {
String path = null;
String SD_CARD_DIR = null;
try {
Process mount = Runtime.getRuntime().exec("mount");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mount.getInputStream()));
mount.waitFor();
// String extPath = Environment.getExternalStorageDirectory().getPath();
// String isMedai = Environment.getExternalStorageState();
// if(Environment.MEDIA_MOUNTED.equalsIgnoreCase(isMedai)){
// String root = Environment.getRootDirectory().getPath();
// path = Environment.getExternalStoragePublicDirectory(DIRECTORY_EDUCOMP).getPath();
// }
String line;
String strFileSystem = null;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("\\s+");
for (int i = 0; i < split.length - 1; i++) {
if (SD_CARD_DIR == null) {
File mainroot = new File(split[i]);
File f[] = mainroot.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
}); // Get First level folders /mnt
if (f != null) {
for (File aFile : f) {
File[] filenames = aFile.listFiles(); // Get second level
// folders
// /mnt/sdcard so on
// and math Educomp
// folder
if (filenames != null) {
for (File ff : filenames) {
String eduFileName = ff.getName();
if (eduFileName.equals("Temp")) {
File[] listEducompfile = ff.listFiles();
if (listEducompfile != null) {
for (File fff : listEducompfile) {
String contentFileName = fff.getName();
if (contentFileName.equals("ts")) {
SD_CARD_DIR = aFile
.getAbsolutePath() + "/";
break;
}
}
}
} else {
File[] filenamesList = ff.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
});
if (filenamesList != null) {
for (File fff : filenamesList) {
String eduFileNamess = fff.getName();
if (eduFileNamess.equals("Temp")) {
File[] listEducompfile = fff.listFiles();
if (listEducompfile != null) {
for (File fffds : listEducompfile) {
String contentFileName = fffds.getName();
if (contentFileName.equals("ts")) {
return SD_CARD_DIR = ff + "/";
}
}
}
}
}
}
}
}
}
}
}
}
// SD_CARD_DIR = DEFAULT_SD_CARD_DIR;
}
return SD_CARD_DIR;
}
return path;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
File dir = new File ("/");
File files = dir.listFiles();
You will not get a listing in Nougat for the root directory. You could have told us that.
`files==null` or files.length()==0
Nougat does not allow listing root. There are several other directories too that you cannot list anymore under Nougat.
You can check this approach on Nougat. But there is no way to make difference between removable SD card and USB flash if they are both connected to your device simultaneously.
Your approach - parsing mount file - does not work for some (chineese?) devices because string entry for internal memory may be completely the same as for removable SD card.
P.S. It is a user responsibility to find out where is USB flash or removable SD card in a "well" designed app. You should not do that by himself because Android does not provide public API for this purpose except Intent.ACTION_OPEN_DOCUMENT_TREE to call a built-in file chooser to interact with user in order to choose folder.
P.P.S INTERACTION WITH USER:
Create button with name "Show USB OTG Root" and onClick method containing
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);//http://stackoverflow.com/questions/28605278/android-5-sd-card-label
startActivityForResult(intent, REQUEST_CODE_USB_ACCESS);
In onActivityResult callback you have to catch user answer when he choose USB OTG root in internal Android chooser:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_USB_ACCESS:
if (data.getData() != null) {
int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
DocumentFile documentFile = DocumentFile.fromTreeUri(this, data.getData());
}
}
}
documentFile is an access object representing USB OTG root (if user did not make mistake when choosing). You can make some file operation like documentFile.listFiles() on it. There is no other way to operate with files on removable media in public API starting from Lollipop. I.e. your desired path to USB OTG can not be obtained as a string from some public API method.
I have a xml file that I'm getting its full path, and pass it to a function where I add a String to its name. However I'm not being able to use it (the initial fullpath) after adding the string. How can it be done, that after getting the fullpath in search(String dirName), and adding the string in lk(String fullpath), I can still use the path which is returned by search(String dirName).
public String search( String dirName)throws Exception{
String fullPath = null;
File dir = new File(dirName);
if ( dir.isDirectory() )
{
String[] list = dir.list(new FilenameFilter()
{
#Override
public boolean accept(File f, String s )
{
return s.endsWith(".xml");
}
});
if ( list.length > 0 )
{
fullPath = dirName+list[0];
lockFile(fullPath);
return fullPath;
}
}
return "";
}
public void lk( String fullPath) throws Exception {
File f = new File(fullPath);
String fileNameWithExt = f.getName();
try {
File newfile =new File(fileNameWithExt+".lock");
if(f.renameTo(newfile)){
System.out.println("Rename succesful");
}else{
System.out.println("Rename failed");
}
} catch (Exception e) {
e.printStackTrace();
}
}
try this
File originalFile = new File(<file parent path>, "myxmlfile");
File cloneFile = new File(originalFile.getParent(),
originalFile.getName()+"<anything_i_want_to_add>");
Files.copy(originalFile.toPath(),cloneFile.toPath());
//now your new file exist and you can use it
originalFile.delete();//you delete the original file
...
//after you are done with everything and you want the path back
Files.copy(cloneFile.toPath(),originalFile.toPath());
cloneFile.delete();
In your lock method, you are calling renameTo method. Because of that, the original filename is now gone, and is replaced by the new filename that ends with .lock.
The java.io.File class is not a file pointer but an object to hold a filename. Using a file object that still refers to an old filename will cause an error.
To answer your question: If you want the old filename after locking, you must use a different approach in locking your file. For example, MS Access locks their .accdb files by creating a lockfile with the same filename as the opened .accdb file.
You may use this code as a reference:
public boolean fileIsLocked(File file) {
File lock = new File(file.getAbsolutePath() + ".lock");
return lock.exists();
}
public void lockFile(File file) {
if (!fileIsLocked(file)) {
File lock = new File(file.getAbsolutePath() + ".lock");
lock.createNewFile();
lock.deleteOnExit(); // unlocks file on JVM exit
}
}
public void unlockFile(File file) {
if (fileIsLocked(file)) {
File lock = new File(file.getAbsolutePath() + ".lock");
lock.delete();
}
}
I am developing an Android app. I am still learning android. But I am having a problem with checking file in download folder exists or not. It is always returning false. But the file actually exists.
This is the function to check file exists or not in CommonHelper class
public static boolean fileExists(String path)
{
File file = new File(path);
if(file.exists())
{
return true;
}
else{
return false;
}
}
This is how I am checking files in built in download folder
if(CommonHelper.fileExists(String.valueOf(Environment.DIRECTORY_DOWNLOADS)+"/"+cursor.getString(1)))
{
//do other stuffs here
}
What is wrong with my code?
The problem is, that you are not getting the full path.
Try getting the path with Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
public static boolean fileExists(File path, String filename){
return new File(path, filename).exists();
}
And then call:
CommonHelper.fileExists(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), cursor.getString(1));
EDIT: Please note, getExternalStoragePublicDirectory can also be something else, like getExternalStorageDirectory() depending, on where you actually stored your file.
Try this:
File file = getContext().getFileStreamPath(file_name);
if(file.exists()){
FileInputStream fileIn= new FileInputStream(file);
...
}
you have to add the file name to the path when creating the file... Please try as below..
File file = new File(storagePath + "/" + fileName);
if (file.exists()) {
return true;
}
else
{
return false;
}
try this
if(CommonHelper.fileExists(new File(Environment.DIRECTORY_DOWNLOADS),cursor.getString(1)))
{
//do other stuffs here
}
and
public static boolean fileExists(File directory, String fileName)
{
File file = new File(directory,fileName);
if(file.exists())
{
return true;
}
else{
return false;
}
}
File file = new File(Environment.getExternalStorageDirectory() + "/filename");
if(file.exists){
return true;
}else{
return false;
}
I hava a java swing application and would like to use auto update using AppLoader.java class that i found online at
**https://reportmill.wordpress.com/2014/12/04/automatically-update-your-javapackager-applications/
**
has anybody had any experience with this class. i can not seem to implement this class with my application and am getting errors:
java.io.FileNotFoundException: C:\Users\home\Documents\NetBeansProjects\test_update\build\classes (Access is denied)
and
java.lang.RuntimeException: Main Jar not found!
yep, the code seems not working. I did some modification for the code to make it work. please do as follows:
download the file through http://reportmill.com/snap1/SnapCode1.jar.pack.gz
copy this file to C:\Users\home\Documents\NetBeansProjects\test_update\build\classes
copy and paste the code below and give it a run
import java.io.;
import java.lang.reflect.Method;
import java.net.;
import java.text.;
import java.util.jar.;
import javax.swing.*;
import java.util.zip .GZIPInputStream;
/**
* This app
*/
public class AppLoader {
// Constants
static final String AppDirName = "SnapCode";
static final String JarName = "SnapCode1.jar";
static final String JarURL = "http://reportmill.com/snap1/SnapCode1.jar.pack.gz";
static final String MainClass = "snap.app.App";
/**
* Main method - reinvokes main1() on Swing thread in exception handler.
*/
public static void main(final String args[]) {
// Invoke real main with exception handler
try {
main1(args);
} catch (Throwable e) {
JOptionPane.showMessageDialog(null, e.toString());
e.printStackTrace();
}
}
/**
* Main method: - Gets main Jar file from default, if missing - Updates main
* Jar file from local update file, if previously loaded - Load main Jar
* into URLClassLoader, load main class and invoke main method - Check for
* update from remove site in background
*/
public static void main1(final String args[]) throws Exception {
// Make sure default jar is in place
try {
copyDefaultMainJar();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.toString());
e.printStackTrace();
}
// If Update Jar exists, copy it into place
File jar = getAppFile(JarName);
File updateJar = getAppFile(JarName + ".update");
if (updateJar.exists()) {
copyFile(updateJar, jar);
jar.setLastModified(updateJar.lastModified());
updateJar.delete();
}
// If jar doesn't exist complain bitterly
if (!jar.exists() || !jar.canRead())
throw new RuntimeException("Main Jar not found!");
// Check for updates in background thread
if (args.length == 0 || !args[0].equals("-snap"))
new Thread(new Runnable() {
public void run() {
checkForUpdatesSilent();
}
}).start();
// Create URLClassLoader for main jar file, get App class and invoke
// main
// URLClassLoader ucl = new URLClassLoader(
// new URL[] { jar.toURI().toURL() });
// Class cls = ucl.loadClass(MainClass); // ucl.close();
// Method meth = cls.getMethod("main", new Class[] { String[].class });
// meth.invoke(null, new Object[] { args });
// if (cls == Object.class)
// ((Closeable) ucl).close(); // Getting rid of warning message for ucl
}
/**
* Copies the default main jar into place for initial run.
*/
private static void copyDefaultMainJar() throws IOException, ParseException {
// Get main jar from app package and get location of working jar file
URL url = AppLoader.class.getProtectionDomain().getCodeSource()
.getLocation();
String path0 = url.getPath();
path0 = URLDecoder.decode(path0, "UTF-8");
path0 = path0 + "SnapCode1.jar.pack.gz" ;
File jar0 = getAppFile(JarName);
File jar1 = new File(path0);
// If app package main jar is newer, copy it into place and set time
if (jar0.exists() && jar0.lastModified() >= jar1.lastModified())
return;
copyFile(jar1, jar0);
}
/**
* Check for updates.
*/
private static void checkForUpdatesSilent() {
try {
checkForUpdates();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Check for updates.
*/
private static void checkForUpdates() throws IOException,
MalformedURLException {
// Get URL connection and lastModified time
File jarFile = getAppFile(JarName);
URL url = new URL(JarURL);
URLConnection connection = url.openConnection();
long mod0 = jarFile.lastModified(), mod1 = connection.getLastModified();
if (mod0 >= mod1) {
System.out.println("No update available at " + JarURL + '(' + mod0
+ '>' + mod1 + ')');
return;
}
// Get update file and write to JarName.update
System.out.println("Loading update from " + JarURL);
byte bytes[] = getBytes(connection);
System.out.println("Update loaded");
File updatePacked = getAppFile(JarName + ".pack.gz"), updateFile = getAppFile(JarName
+ ".update");
writeBytes(updatePacked, bytes);
System.out.println("Update saved: " + updatePacked);
unpack(updatePacked, updateFile);
System.out.println("Update unpacked: " + updateFile);
updateFile.setLastModified(mod1);
updatePacked.delete();
// Let the user know
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane
.showMessageDialog(null,
"A new update is available. Restart application to apply");
}
});
}
/**
* Returns the Main jar file.
*/
private static File getAppFile(String aName) {
return new File(getAppDir(), aName);
}
/**
* Returns the Main jar file.
*/
private static File getAppDir() {
return getAppDataDir(AppDirName, true);
}
/**
*
* Utility Methods for AppLoader.
*
*/
/**
* Copies a file from one location to another.
*/
public static File copyFile(File aSource, File aDest) throws IOException {
// Get input stream, output file and output stream
FileInputStream fis = new FileInputStream(aSource);
File out = aDest.isDirectory() ? new File(aDest, aSource.getName())
: aDest;
FileOutputStream fos = new FileOutputStream(out);
// Iterate over read/write until all bytes written
byte[] buf = new byte[8192];
for (int i = fis.read(buf); i != -1; i = fis.read(buf))
fos.write(buf, 0, i);
// Close in/out streams and return out file
fis.close();
fos.close();
return out;
}
/**
* Writes the given bytes (within the specified range) to the given file.
*/
public static void writeBytes(File aFile, byte theBytes[])
throws IOException {
if (theBytes == null) {
aFile.delete();
return;
}
FileOutputStream fileStream = new FileOutputStream(aFile);
fileStream.write(theBytes);
fileStream.close();
}
/**
* Unpacks the given file into the destination file.
*/
public static File unpack(File aFile, File aDestFile) throws IOException {
// Get dest file - if already unpacked, return
File destFile = getUnpackDestination(aFile, aDestFile);
if (destFile.exists() && destFile.lastModified() > aFile.lastModified())
return destFile;
// Create streams: FileInputStream -> GZIPInputStream -> JarOutputStream
// -> FileOutputStream
FileInputStream fileInput = new FileInputStream(aFile);
GZIPInputStream gzipInput = new GZIPInputStream(fileInput);
FileOutputStream fileOut = new FileOutputStream(destFile);
JarOutputStream jarOut = new JarOutputStream(fileOut);
// Unpack file
Pack200.newUnpacker().unpack(gzipInput, jarOut);
// Close streams
fileInput.close();
gzipInput.close();
jarOut.close();
fileOut.close();
// Return destination file
return destFile;
}
/**
* Returns the file that given packed file would be saved to using the
* unpack method.
*/
public static File getUnpackDestination(File aFile, File aDestFile) {
// Get dest file - if null, create from packed file minus .pack.gz
File destFile = aDestFile;
if (destFile == null)
destFile = new File(aFile.getPath().replace(".pack.gz", ""));
// If dest file is directory, change to file inside with packed file
// minus .pack.gz
else if (destFile.isDirectory())
destFile = new File(destFile, aFile.getName().replace(".pack.gz",
""));
// Return destination file
return destFile;
}
/**
* Returns the AppData or Application Support directory file.
*/
public static File getAppDataDir(String aName, boolean doCreate) {
// Get user home + AppDataDir (platform specific) + name (if provided)
String dir = System.getProperty("user.home");
if (isWindows)
dir += File.separator + "AppData" + File.separator + "Local";
else if (isMac)
dir += File.separator + "Library" + File.separator
+ "Application Support";
if (aName != null)
dir += File.separator + aName;
// Create file, actual directory (if requested) and return
File dfile = new File(dir);
if (doCreate && aName != null)
dfile.mkdirs();
return dfile;
}
/**
* Returns bytes for connection.
*/
public static byte[] getBytes(URLConnection aConnection) throws IOException {
InputStream stream = aConnection.getInputStream(); // Get stream for
// connection
byte bytes[] = getBytes(stream); // Get bytes for stream
stream.close(); // Close stream
return bytes; // Return bytes
}
/**
* Returns bytes for an input stream.
*/
public static byte[] getBytes(InputStream aStream) throws IOException {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
byte chunk[] = new byte[8192];
for (int len = aStream.read(chunk, 0, 8192); len > 0; len = aStream
.read(chunk, 0, 8192))
bs.write(chunk, 0, len);
return bs.toByteArray();
}
// Whether Windows/Mac
static boolean isWindows = (System.getProperty("os.name")
.indexOf("Windows") >= 0);
static boolean isMac = (System.getProperty("os.name").indexOf("Mac OS X") >= 0);
}
Your problem is that in your copyFile method FileInputStream takes a wrong File object
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;
}