Path to screenshots in Android - android

Is there a way to find out the path used by android to save screenshots?
Can I get the path from a code?

Android's API has no fixed path for screenshots but
File pix = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File screenshots = new File(pix, "Screenshots");
might work. That's what ICS uses as path.

The "Screenshots" value is part of the private API.
Here is link to the source code where the value is set. Since the class is loaded in our application context there is no option to access the field. I'd hardcode it as #zapi suggested.

Few might find this usefull..
public static File mDir= new File(String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)));
public static File mDirScreenshots = new File(mDir,"Screenshots");
And to fetch the screenshots
public static ArrayList<File> getAllScreenshots(File dir){
File listFile[] = dir.listFiles();
if (listFile != null && listFile.length > 0) {
for (int i = 0; i < listFile.length; i++) {
Log.e(YOUR_TAG, "getAllScreenshots: " + i + listFile[i].getName());
mScreenshotsFiles.add(listFile[i]);
}
}
return mScreenshotsFiles;
}

Recursion is your friend here.
Tested on Android version 9 and 12. Works good.
final String findThisDirectory = "screenshots";
final String rootPath = Environment.getExternalStorageDirectory().getPath();
//we do not want to include 'Android' directory because looking inside it
//or some directories inside of it can and will cause crash in some Android versions due to permissions related issues
String ignoreThisDirectory = "android";
void getPathRecursively(String rootPath, String matchThisDirectory, String ignoreThisDirectory){
File[] filesArray = new File(rootPath).listFiles();
if(filesArray.length > 0){
for(File file: filesArray){
if(file.isDirectory()){
if(file.getName().toLowerCase().equals(ignoreThisDirectory)){
continue;
}
else if(file.getName().toLowerCase().equals(matchThisDirectory)){
// here you found the path to 'screenshots' in file object
// get it from the file.getAbsolutePath()
break;
}
getPathRecursively(file.getAbsolutePath(), matchThisDirectory, ignoreThisDirectory);
}
}
}
}

Related

Java listFiles return null but I can still find files when I have a full path to a file in the directory

So in my react-native module I Want to find the already created files that my app has created in
/storage/emulated/0/Download/xx/xx
It work great when My app create those files in those directory and File.listFiles("/storage/emulated/0/Download/xx/xx") return all those files without any problem.
Now when I uninstall my app and install it again, listFiles cant find those old files anymore!!
But only find the files that I create a new.
Now for those of you who think this is about permission I already check it and have full access
status{"android.permission.WRITE_EXTERNAL_STORAGE":"granted","android.permission.READ_EXTERNAL_STORAGE":"granted"}
Here is the Java method that I have
#ReactMethod(isBlockingSynchronousMethod = true)
public String getAllAppDownloadedFiles(String folderPath) {
File folder = new File(folderPath);
String result = "";
if (!folder.exists())
return result;
File[] files = folder.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isFile())
result += file.getAbsolutePath() + (files.length - 1 > i ? "," : "");
}
return result;
}
I should point out that the problem only exist when I run the app on my mobile and not in emulator. I suspect it has to do with the version of API.
Any Idea how I could fix this?

Get files list from apk expension file

How I can get files list of certain folder in expension apk file?
For assets I did it with:
String[] filesList = getAssets().list("some/path");
But for APK expension file I have only
getExpansionFile().getAllEntries();
which retreive all files.
But I need to move around folder, for example move to folder1, show files that place inside. And next move to subfolder1 (which place in folder1) and show fileslist there. I can't it hardcode, becouce files might be changed.
And again: how I can retreive files of certain folder in apk expension file?
Finally, I wrote my own implementation.
public class FileStructure {
public final String pathName;
// or TreeMap if order matter
public HashMap<String, FileStructure> files;
public FileStructure(String path){
this.pathName = path;
files = new HashMap<String, FileStructure>();
}
}
Getting apk expension file entries with java.util.zip.ZipFile:
ZipFile zf = new ZipFile(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/Android/obb/" + getPackageName()
+ "/main.1." + getPackageName() + ".obb");
Enumeration zipEntries = zf.entries();
String fname;
while (zipEntries.hasMoreElements()) {
fname = ((ZipEntry) zipEntries.nextElement()).getName();
addToRoot(fname, root);
}
And parse it with in FileStructure class
private void addToRoot(String fname, FileStructure root) {
String[] directories = fname.split(File.separator);
FileStructure current = root;
for (int i = 0; i < directories.length; i++) {
if (!current.files.containsKey(directories[i])) {
current.files.put(directories[i], new FileStructure(directories[i]));
}
current = current.files.get(directories[i]);
}
}
But, I will appreciate, if someone share some better solution or find defect of my implementation!

How to rename folder of SD-Card from list-view in android

I am trying get all the list of particular folder name from SD-Card to list-view in android. I am giving two option to user they can create folder as well as they can rename folder from application it self.
With the list-view i have given check-box so user can check any single list value at a time and then can perform operation as they want of editing or creating folder in SD-Card.
Everything is working fine till creating folder, but my problem start's here, when user tries to rename folder name, then first time user can successfully changes the folder name but while doing same task second time, user is not able to rename same folder again.
What mistake i am doing, following is my code please help, Thanks in advance.
private static List<String> myList = new ArrayList<String>();
public static void folder_create() {
if (Code.pm == 1) {
String updateFolder = Environment.getExternalStorageDirectory()
.getPath() + "/AudioRecorder/";
File filecall = null;
filecall = new File(updateFolder);
File list[] = filecall.listFiles();
for (int i = 0; i < list.length; i++) {
myList.add(list[i].getName());
}
int len = mListView.getCount();
SparseBooleanArray checked = mListView.getCheckedItemPositions();
for (int i = 0; i < len; i++)
if (checked.get(i)) {
String mUpdateName = myList.get(i);
File file = new File(updateFolder + "/" + mUpdateName);
System.out.println("=======File======" + file);
File file2 = new File(updateFolder + "/" + Code.className);
System.out.println("=======File2======" + file2);
file.renameTo(file2);
}
} else {
String filepath = Environment.getExternalStorageDirectory()
.getPath();
File file = new File(filepath, "/AudioRecorder/" + Code.className);
if (!file.exists()) {
file.mkdirs();
}
}
}
Here Code is static class and pm is integer variable. So when user click button based on pm variable value it will perform task weather to rename folder or create folder.
If I understand your issue, you're trying to rename a directory after having made 'some tasks'. Are those tasks made into this folder? If yes, be sure that you have closed your streams (creating / modifying content) like so:
stream.close();
Please also check the LogCat to see if some warnings are shown.

Delete files from a known folder

I'm trying to delete all files that are exists in a known path.
I've used the next function to do so -
public void deleteAllImages(){
Log.d(TAG, "ENTERD DELETED ALL IMAGES ");
String path = "/data/data/yourapp/app_data/imageDir/";
File directory = new File(path);
if (directory.isDirectory()){
Log.d(TAG, "ENTERED IF ");
for (File child : directory.listFiles()){
Log.d(TAG, "ENTERED FOR "+ child);
child.delete();
}
}
}
But it seem that it never getting into the if statement - guess it mean that it doesn't treat directory as one. So what am I doing wrong here?
Most likely the path is not correct. The isDirectory() will return false in the following cases:
The path points to file (obviously), and not to directory.
The path
is invalid (i.e. there is no such file/directory exists).
There is
not enough permissions granted to your application to determine
whether path points to directory.
Try this :
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
new File(dir, children[i]).delete();
}
}
Check this : Delete files from folder
Hope this helps.
try this...
String path = "/data/data/yourapp/app_data/imageDir/";
File file = new File(path);
if(file.isDirectory()) {
File[] files = file.listFiles();
if(files != null && files.length > 0) {
for (File file2 : files) {
file2.delete();
}
}
}

How can I get the external SD card path for Android 4.0+?

Samsung Galaxy S3 has an external SD card slot, which is mounted to /mnt/extSdCard.
How can I get this path by something like Environment.getExternalStorageDirectory()?
This will return mnt/sdcard, and I can't find the API for the external SD card. (Or removable USB storage on some tablets.)
I have a variation on a solution I found here
public static HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
}
The original method was tested and worked with
Huawei X3 (stock)
Galaxy S2 (stock)
Galaxy S3 (stock)
I'm not certain which android version these were on when they were tested.
I've tested my modified version with
Moto Xoom 4.1.2 (stock)
Galaxy Nexus (cyanogenmod 10) using an otg cable
HTC Incredible (cyanogenmod 7.2) this returned both the internal and external. This device is kinda an oddball in that its internal largely goes unused as getExternalStorage() returns a path to the sdcard instead.
and some single storage devices that use an sdcard as their main storage
HTC G1 (cyanogenmod 6.1)
HTC G1 (stock)
HTC Vision/G2 (stock)
Excepting the Incredible all these devices only returned their removable storage. There are probably some extra checks I should be doing, but this is at least a bit better than any solution I've found thus far.
I found more reliable way to get paths to all SD-CARDs in system.
This works on all Android versions and return paths to all storages (include emulated).
Works correctly on all my devices.
P.S.: Based on source code of Environment class.
private static final Pattern DIR_SEPORATOR = Pattern.compile("/");
/**
* Raturns all available SD-Cards in the system (include emulated)
*
* Warning: Hack! Based on Android source code of version 4.3 (API 18)
* Because there is no standart way to get it.
* TODO: Test on future Android versions 4.4+
*
* #return paths to all available SD-Cards in the system (include emulated)
*/
public static String[] getStorageDirectories()
{
// Final set of paths
final Set<String> rv = new HashSet<String>();
// Primary physical SD-CARD (not emulated)
final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
// All Secondary SD-CARDs (all exclude primary) separated by ":"
final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
// Primary emulated SD-CARD
final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
if(TextUtils.isEmpty(rawEmulatedStorageTarget))
{
// Device has physical external storage; use plain paths.
if(TextUtils.isEmpty(rawExternalStorage))
{
// EXTERNAL_STORAGE undefined; falling back to default.
rv.add("/storage/sdcard0");
}
else
{
rv.add(rawExternalStorage);
}
}
else
{
// Device has emulated storage; external storage paths should have
// userId burned into them.
final String rawUserId;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
{
rawUserId = "";
}
else
{
final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
final String[] folders = DIR_SEPORATOR.split(path);
final String lastFolder = folders[folders.length - 1];
boolean isDigit = false;
try
{
Integer.valueOf(lastFolder);
isDigit = true;
}
catch(NumberFormatException ignored)
{
}
rawUserId = isDigit ? lastFolder : "";
}
// /storage/emulated/0[1,2,...]
if(TextUtils.isEmpty(rawUserId))
{
rv.add(rawEmulatedStorageTarget);
}
else
{
rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
}
}
// Add all secondary storages
if(!TextUtils.isEmpty(rawSecondaryStoragesStr))
{
// All Secondary SD-CARDs splited into array
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
return rv.toArray(new String[rv.size()]);
}
I guess to use the external sdcard you need to use this:
new File("/mnt/external_sd/")
OR
new File("/mnt/extSdCard/")
in your case...
in replace of Environment.getExternalStorageDirectory()
Works for me. You should check whats in the directory mnt first and work from there..
You should use some type of selection method to choose which sdcard to use:
File storageDir = new File("/mnt/");
if(storageDir.isDirectory()){
String[] dirList = storageDir.list();
//TODO some type of selecton method?
}
I was using Dmitriy Lozenko's solution until i checked on an Asus Zenfone2, Marshmallow 6.0.1 and the solution is not working. The solution failed when getting EMULATED_STORAGE_TARGET, specifically for microSD path, i.e: /storage/F99C-10F4/. I edited the code to get the emulated root paths directly from emulated application paths with context.getExternalFilesDirs(null); and add more known phone-model-specific physical paths.
To make our life easier, I made a library here. You can use it via gradle, maven, sbt, and leiningen build system.
If you like the old-fashioned way, you can also copy paste the file directly from here, but you will not know if there is an update in the future without checking it manually.
If you have any question or suggestion, please let me know
In order to retrieve all the External Storages (whether they are SD cards or internal non-removable storages), you can use the following code:
final String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) { // we can read the External Storage...
//Retrieve the primary External Storage:
final File primaryExternalStorage = Environment.getExternalStorageDirectory();
//Retrieve the External Storages root directory:
final String externalStorageRootDir;
if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) { // no parent...
Log.d(TAG, "External Storage: " + primaryExternalStorage + "\n");
}
else {
final File externalStorageRoot = new File( externalStorageRootDir );
final File[] files = externalStorageRoot.listFiles();
for ( final File file : files ) {
if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) { // it is a real directory (not a USB drive)...
Log.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n");
}
}
}
}
Alternatively, you might use System.getenv("EXTERNAL_STORAGE") to retrieve the primary External Storage directory (e.g. "/storage/sdcard0") and System.getenv("SECONDARY_STORAGE") to retieve the list of all the secondary directories (e.g. "/storage/extSdCard:/storage/UsbDriveA:/storage/UsbDriveB"). Remember that, also in this case, you might want to filter the list of secondary directories in order to exclude the USB drives.
In any case, please note that using hard-coded paths is always a bad approach (expecially when every manufacturer may change it as pleased).
Good news! In KitKat there's now a public API for interacting with these secondary shared storage devices.
The new Context.getExternalFilesDirs() and Context.getExternalCacheDirs() methods can return multiple paths, including both primary and secondary devices. You can then iterate over them and check Environment.getStorageState() and File.getFreeSpace() to determine the best place to store your files. These methods are also available on ContextCompat in the support-v4 library.
Also note that if you're only interested in using the directories returned by Context, you no longer need the READ_ or WRITE_EXTERNAL_STORAGE permissions. Going forward, you'll always have read/write access to these directories with no additional permissions required.
Apps can also continue working on older devices by end-of-lifing their permission request like this:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
I did the following to get acces to all the external sd cards.
With:
File primaryExtSd=Environment.getExternalStorageDirectory();
you get the path to the primary external SD
Then with:
File parentDir=new File(primaryExtSd.getParent());
you get the parent dir of the primary external storage, and it is also the parent of all the external sd.
Now, you can list all the storage and select the one that you want.
Hope it is usefull.
Found a new way that is more official starting from Android N (if before, you can try what I've written above) and especially from Android R, using StorageManager (based on a solution I wrote here) :
class MainActivity : AppCompatActivity() {
#RequiresApi(Build.VERSION_CODES.N)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getSdCardPaths(this, true)?.forEach { volumePath ->
Log.d("AppLog", "volumePath:$volumePath")
}
}
/**
* returns a list of all available sd cards paths, or null if not found.
*
* #param includePrimaryExternalStorage set to true if you wish to also include the path of the primary external storage
*/
fun getSdCardPaths(context: Context, includePrimaryExternalStorage: Boolean): List<String>? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
if (!storageVolumes.isNullOrEmpty()) {
val primaryVolume = storageManager.primaryStorageVolume
val result = ArrayList<String>(storageVolumes.size)
for (storageVolume in storageVolumes) {
val volumePath = getVolumePath(storageVolume) ?: continue
if (storageVolume.uuid == primaryVolume.uuid || storageVolume.isPrimary) {
if (includePrimaryExternalStorage)
result.add(volumePath)
continue
}
result.add(volumePath)
}
return if (result.isEmpty()) null else result
}
}
val externalCacheDirs = ContextCompat.getExternalCacheDirs(context)
if (externalCacheDirs.isEmpty())
return null
if (externalCacheDirs.size == 1) {
if (externalCacheDirs[0] == null)
return null
val storageState = EnvironmentCompat.getStorageState(externalCacheDirs[0])
if (Environment.MEDIA_MOUNTED != storageState)
return null
if (!includePrimaryExternalStorage && Environment.isExternalStorageEmulated())
return null
}
val result = ArrayList<String>()
if (externalCacheDirs[0] != null && (includePrimaryExternalStorage || externalCacheDirs.size == 1))
result.add(getRootOfInnerSdCardFolder(context, externalCacheDirs[0]))
for (i in 1 until externalCacheDirs.size) {
val file = externalCacheDirs[i] ?: continue
val storageState = EnvironmentCompat.getStorageState(file)
if (Environment.MEDIA_MOUNTED == storageState)
result.add(getRootOfInnerSdCardFolder(context, externalCacheDirs[i]))
}
return if (result.isEmpty()) null else result
}
fun getRootOfInnerSdCardFolder(context: Context, inputFile: File): String {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
storageManager.getStorageVolume(inputFile)?.let {
val result = getVolumePath(it)
if (result != null)
return result
}
}
var file: File = inputFile
val totalSpace = file.totalSpace
while (true) {
val parentFile = file.parentFile
if (parentFile == null || parentFile.totalSpace != totalSpace || !parentFile.canRead())
return file.absolutePath
file = parentFile
}
}
#RequiresApi(Build.VERSION_CODES.N)
fun getVolumePath(storageVolume: StorageVolume): String? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
return storageVolume.directory?.absolutePath
try {
val storageVolumeClazz = StorageVolume::class.java
val getPath = storageVolumeClazz.getMethod("getPath")
return getPath.invoke(storageVolume) as String
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
}
Thanks for the clues provided by you guys, especially #SmartLemon, I got the solution. In case someone else need it, I put my final solution here( to find the first listed external SD card ):
public File getExternalSDCardDirectory()
{
File innerDir = Environment.getExternalStorageDirectory();
File rootDir = innerDir.getParentFile();
File firstExtSdCard = innerDir ;
File[] files = rootDir.listFiles();
for (File file : files) {
if (file.compareTo(innerDir) != 0) {
firstExtSdCard = file;
break;
}
}
//Log.i("2", firstExtSdCard.getAbsolutePath().toString());
return firstExtSdCard;
}
If no external SD card there, then it returns the on board storage. I will use it if the sdcard is not exist, you may need to change it.
refer to my code, hope helpful for you:
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("mount");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
String line;
String mount = new String();
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
if (line.contains("secure")) continue;
if (line.contains("asec")) continue;
if (line.contains("fat")) {//TF card
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
mount = mount.concat("*" + columns[1] + "\n");
}
} else if (line.contains("fuse")) {//internal storage
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
mount = mount.concat(columns[1] + "\n");
}
}
}
txtView.setText(mount);
This solution (assembled from other answers to this question) handles the fact (as mentioned by #ono) that System.getenv("SECONDARY_STORAGE") is of no use with Marshmallow.
Tested and working on:
Samsung Galaxy Tab 2 (Android 4.1.1 - Stock)
Samsung Galaxy Note 8.0 (Android 4.2.2 - Stock)
Samsung Galaxy S4 (Android 4.4 - Stock)
Samsung Galaxy S4 (Android 5.1.1 - Cyanogenmod)
Samsung Galaxy Tab A (Android 6.0.1 - Stock)
/**
* Returns all available external SD-Card roots in the system.
*
* #return paths to all available external SD-Card roots in the system.
*/
public static String[] getStorageDirectories() {
String [] storageDirectories;
String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
List<String> results = new ArrayList<String>();
File[] externalDirs = applicationContext.getExternalFilesDirs(null);
for (File file : externalDirs) {
String path = file.getPath().split("/Android")[0];
if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file))
|| rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)){
results.add(path);
}
}
storageDirectories = results.toArray(new String[0]);
}else{
final Set<String> rv = new HashSet<String>();
if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) {
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
storageDirectories = rv.toArray(new String[rv.size()]);
}
return storageDirectories;
}
Actually in some devices the external sdcard default name is showing as extSdCard and for other it is sdcard1.
This code snippet helps to find out that exact path and helps to retrieve you the path of external device.
String sdpath,sd1path,usbdiskpath,sd0path;
if(new File("/storage/extSdCard/").exists())
{
sdpath="/storage/extSdCard/";
Log.i("Sd Cardext Path",sdpath);
}
if(new File("/storage/sdcard1/").exists())
{
sd1path="/storage/sdcard1/";
Log.i("Sd Card1 Path",sd1path);
}
if(new File("/storage/usbcard1/").exists())
{
usbdiskpath="/storage/usbcard1/";
Log.i("USB Path",usbdiskpath);
}
if(new File("/storage/sdcard0/").exists())
{
sd0path="/storage/sdcard0/";
Log.i("Sd Card0 Path",sd0path);
}
Yes. Different manufacturer use different SDcard name like in Samsung Tab 3 its extsd, and other samsung devices use sdcard like this different manufacturer use different names.
I had the same requirement as you. so i have created a sample example for you from my project goto this link Android Directory chooser example which uses the androi-dirchooser library. This example detect the SDcard and list all the subfolders and it also detects if the device has morethan one SDcard.
Part of the code looks like this For full example goto the link Android Directory Chooser
/**
* Returns the path to internal storage ex:- /storage/emulated/0
*
* #return
*/
private String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
/**
* Returns the SDcard storage path for samsung ex:- /storage/extSdCard
*
* #return
*/
private String getSDcardDirectoryPath() {
return System.getenv("SECONDARY_STORAGE");
}
mSdcardLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
String sdCardPath;
/***
* Null check because user may click on already selected buton before selecting the folder
* And mSelectedDir may contain some wrong path like when user confirm dialog and swith back again
*/
if (mSelectedDir != null && !mSelectedDir.getAbsolutePath().contains(System.getenv("SECONDARY_STORAGE"))) {
mCurrentInternalPath = mSelectedDir.getAbsolutePath();
} else {
mCurrentInternalPath = getInternalDirectoryPath();
}
if (mCurrentSDcardPath != null) {
sdCardPath = mCurrentSDcardPath;
} else {
sdCardPath = getSDcardDirectoryPath();
}
//When there is only one SDcard
if (sdCardPath != null) {
if (!sdCardPath.contains(":")) {
updateButtonColor(STORAGE_EXTERNAL);
File dir = new File(sdCardPath);
changeDirectory(dir);
} else if (sdCardPath.contains(":")) {
//Multiple Sdcards show root folder and remove the Internal storage from that.
updateButtonColor(STORAGE_EXTERNAL);
File dir = new File("/storage");
changeDirectory(dir);
}
} else {
//In some unknown scenario at least we can list the root folder
updateButtonColor(STORAGE_EXTERNAL);
File dir = new File("/storage");
changeDirectory(dir);
}
}
});
On some devices (for example samsung galaxy sII )internal memory card mabe be in vfat. In this case use refer last code, we obtain path internal memory card (/mnt/sdcad) but no external card. Code refer below solve this problem.
static String getExternalStorage(){
String exts = Environment.getExternalStorageDirectory().getPath();
try {
FileReader fr = new FileReader(new File("/proc/mounts"));
BufferedReader br = new BufferedReader(fr);
String sdCard=null;
String line;
while((line = br.readLine())!=null){
if(line.contains("secure") || line.contains("asec")) continue;
if(line.contains("fat")){
String[] pars = line.split("\\s");
if(pars.length<2) continue;
if(pars[1].equals(exts)) continue;
sdCard =pars[1];
break;
}
}
fr.close();
br.close();
return sdCard;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
File[] files = null;
File file = new File("/storage");// /storage/emulated
if (file.exists()) {
files = file.listFiles();
}
if (null != files)
for (int j = 0; j < files.length; j++) {
Log.e(TAG, "" + files[j]);
Log.e(TAG, "//--//--// " + files[j].exists());
if (files[j].toString().replaceAll("_", "")
.toLowerCase().contains("extsdcard")) {
external_path = files[j].toString();
break;
} else if (files[j].toString().replaceAll("_", "")
.toLowerCase()
.contains("sdcard".concat(Integer.toString(j)))) {
// external_path = files[j].toString();
}
Log.e(TAG, "--///--///-- " + external_path);
}
System.getenv("SECONDARY_STORAGE") returns null for Marshmallow. This is another way of finding all the externals dirs. You can check if it's removable which determines if internal/external
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
File[] externalCacheDirs = context.getExternalCacheDirs();
for (File file : externalCacheDirs) {
if (Environment.isExternalStorageRemovable(file)) {
// It's a removable storage
}
}
}
I am sure this code will surely resolve your issues...This is working fine for me...\
try {
File mountFile = new File("/proc/mounts");
usbFoundCount=0;
sdcardFoundCount=0;
if(mountFile.exists())
{
Scanner usbscanner = new Scanner(mountFile);
while (usbscanner.hasNext()) {
String line = usbscanner.nextLine();
if (line.startsWith("/dev/fuse /storage/usbcard1")) {
usbFoundCount=1;
Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/usbcard1" );
}
}
}
if(mountFile.exists()){
Scanner sdcardscanner = new Scanner(mountFile);
while (sdcardscanner.hasNext()) {
String line = sdcardscanner.nextLine();
if (line.startsWith("/dev/fuse /storage/sdcard1")) {
sdcardFoundCount=1;
Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/sdcard1" );
}
}
}
if(usbFoundCount==1)
{
Toast.makeText(context,"USB Connected and properly mounted", 7000).show();
Log.i("-----USB--------","USB Connected and properly mounted" );
}
else
{
Toast.makeText(context,"USB not found!!!!", 7000).show();
Log.i("-----USB--------","USB not found!!!!" );
}
if(sdcardFoundCount==1)
{
Toast.makeText(context,"SDCard Connected and properly mounted", 7000).show();
Log.i("-----SDCard--------","SDCard Connected and properly mounted" );
}
else
{
Toast.makeText(context,"SDCard not found!!!!", 7000).show();
Log.i("-----SDCard--------","SDCard not found!!!!" );
}
}catch (Exception e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory()
+ File.separator + Environment.DIRECTORY_PICTURES;
File dir = new File(path);
You can use something like - Context.getExternalCacheDirs() or Context.getExternalFilesDirs() or Context.getObbDirs(). They give application specific directories in all external storage devices where the application can store its files.
So something like this - Context.getExternalCacheDirs()[i].getParentFile().getParentFile().getParentFile().getParent() can get you the root path of external storage devices.
I know these commands are for a different purpose but other answers didn't work for me.
This link gave me good pointers - https://possiblemobile.com/2014/03/android-external-storage/
I have tried the solutions provided by Dmitriy Lozenko and Gnathonic on my Samsung Galaxy Tab S2 (Model: T819Y) but none helped me retrieve path to an external SD Card directory. mount command execution contained the required path to external SD Card directory (i.e. /Storage/A5F9-15F4) but it did not match the regular expression hence it was not returned. I don't get the directory naming mechanism followed by Samsung. Why they deviate from standards (i.e. extsdcard) and come up with something really fishy like in my case (i.e. /Storage/A5F9-15F4). Is there anything I am missing? Anyways, following changes in regular expression of Gnathonic's solution helped me get valid sdcard directory:
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*(vold|media_rw).*(sdcard|vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
I am not sure if this is a valid solution and if it will give results for other Samsung tablets but it has fixed my problem for now. Following is another method to retrieve removable SD Card path in Android (v6.0). I have tested the method with android marshmallow and it works. Approach used in it is very basic and will surely work for other versions too but testing is mandatory. Some insight into it will be helpful:
public static String getSDCardDirPathForAndroidMarshmallow() {
File rootDir = null;
try {
// Getting external storage directory file
File innerDir = Environment.getExternalStorageDirectory();
// Temporarily saving retrieved external storage directory as root
// directory
rootDir = innerDir;
// Splitting path for external storage directory to get its root
// directory
String externalStorageDirPath = innerDir.getAbsolutePath();
if (externalStorageDirPath != null
&& externalStorageDirPath.length() > 1
&& externalStorageDirPath.startsWith("/")) {
externalStorageDirPath = externalStorageDirPath.substring(1,
externalStorageDirPath.length());
}
if (externalStorageDirPath != null
&& externalStorageDirPath.endsWith("/")) {
externalStorageDirPath = externalStorageDirPath.substring(0,
externalStorageDirPath.length() - 1);
}
String[] pathElements = externalStorageDirPath.split("/");
for (int i = 0; i < pathElements.length - 1; i++) {
rootDir = rootDir.getParentFile();
}
File[] files = rootDir.listFiles();
for (File file : files) {
if (file.exists() && file.compareTo(innerDir) != 0) {
// Try-catch is implemented to prevent from any IO exception
try {
if (Environment.isExternalStorageRemovable(file)) {
return file.getAbsolutePath();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
Kindly share if you have any other approach to handle this issue. Thanks
String secStore = System.getenv("SECONDARY_STORAGE");
File externalsdpath = new File(secStore);
This will get the path of external sd secondary storage.
//manifest file outside the application tag
//please give permission write this
//<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
File file = new File("/mnt");
String[] fileNameList = file.list(); //file names list inside the mnr folder
String all_names = ""; //for the log information
String foundedFullNameOfExtCard = ""; // full name of ext card will come here
boolean isExtCardFounded = false;
for (String name : fileNameList) {
if (!isExtCardFounded) {
isExtCardFounded = name.contains("ext");
foundedFullNameOfExtCard = name;
}
all_names += name + "\n"; // for log
}
Log.d("dialog", all_names + foundedFullNameOfExtCard);
To access files in my SD card, on my HTC One X (Android), I use this path:
file:///storage/sdcard0/folder/filename.jpg
Note the tripple "/" !
On Galaxy S3 Android 4.3 the path I use is ./storage/extSdCard/Card/ and it does the job. Hope it helps,
that's not true. /mnt/sdcard/external_sd can exist even if the SD card is not mounted. your application will crash when you try to write to /mnt/sdcard/external_sd when it's not mounted.
you need to check if the SD card is mounted first using:
boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
The following steps worked for me. You just need to write this lines:
String sdf = new String(Environment.getExternalStorageDirectory().getName());
String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));
The first line will give the name of sd directory, and you just need to use it in the replace method for the second string. The second string will contain the path for the internal and removable sd(/storage/ in my case). I just needed this path for my app but you can go further if you need it.

Categories

Resources