1111import android .net .Uri ;
1212import android .os .Build ;
1313import android .os .Environment ;
14+ import android .os .storage .StorageManager ;
15+ import android .os .storage .StorageVolume ;
1416import android .provider .DocumentsContract ;
1517import android .util .Log ;
1618import android .webkit .MimeTypeMap ;
2022import java .io .FileOutputStream ;
2123import java .io .InputStream ;
2224import java .io .OutputStream ;
25+ import java .lang .reflect .Method ;
2326import java .util .ArrayList ;
2427import java .util .Comparator ;
28+ import java .util .HashSet ;
2529import java .util .List ;
2630import java .util .Locale ;
2731
@@ -48,14 +52,24 @@ public int compare( UriPermission a, UriPermission b )
4852
4953 private static final StringBuilder stringBuilder = new StringBuilder ();
5054
51- public static String GetExternalDrives ()
55+ public static String GetExternalDrives ( Context context )
5256 {
5357 File primary = Environment .getExternalStorageDirectory ();
5458 String primaryPath = primary .getAbsolutePath ();
59+ String primaryCanonicalPath = primaryPath ;
60+ try
61+ {
62+ primaryCanonicalPath = primary .getCanonicalPath ();
63+ }
64+ catch ( Exception e )
65+ {
66+ }
5567
5668 stringBuilder .setLength ( 0 );
5769 stringBuilder .append ( primaryPath ).append ( ":" );
5870
71+ HashSet <String > potentialDrives = new HashSet <String >( 16 );
72+
5973 // Try paths saved at system environments
6074 // Credit: https://stackoverflow.com/a/32088396/2373034
6175 String strSDCardPath = System .getenv ( "SECONDARY_STORAGE" );
@@ -69,25 +83,7 @@ public static String GetExternalDrives()
6983 {
7084 String path = externalPaths [i ];
7185 if ( path != null && path .length () > 0 )
72- {
73- File file = new File ( path );
74- if ( file .exists () && file .isDirectory () && file .canRead () && !file .getAbsolutePath ().equalsIgnoreCase ( primaryPath ) )
75- {
76- String absolutePath = file .getAbsolutePath () + File .separator + "Android" ;
77- if ( new File ( absolutePath ).exists () )
78- {
79- try
80- {
81- // Check if two paths lead to same storage (aliases)
82- if ( !primary .getCanonicalPath ().equals ( file .getCanonicalPath () ) )
83- stringBuilder .append ( file .getAbsolutePath () ).append ( ":" );
84- }
85- catch ( Exception e )
86- {
87- }
88- }
89- }
90- }
86+ potentialDrives .add ( path );
9187 }
9288 }
9389
@@ -102,29 +98,51 @@ public static String GetExternalDrives()
10298 File [] fileList = new File ( root ).listFiles ();
10399 for ( File file : fileList )
104100 {
105- if ( file .exists () && file .isDirectory () && file .canRead () && !file .getAbsolutePath ().equalsIgnoreCase ( primaryPath ) )
106- {
107- String absolutePath = file .getAbsolutePath () + File .separator + "Android" ;
108- if ( new File ( absolutePath ).exists () )
109- {
110- try
111- {
112- // Check if two paths lead to same storage (aliases)
113- if ( !primary .getCanonicalPath ().equals ( file .getCanonicalPath () ) )
114- stringBuilder .append ( file .getAbsolutePath () ).append ( ":" );
115- }
116- catch ( Exception ex )
117- {
118- }
119- }
120- }
101+ if ( file .exists () && file .isDirectory () && file .canRead () )
102+ potentialDrives .add ( file .getAbsolutePath () );
121103 }
122104 }
123105 catch ( Exception e )
124106 {
125107 }
126108 }
127109
110+ // This is the only working method on some Android 11+ devices (when Storage Access Framework isn't used)
111+ if ( android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .N )
112+ {
113+ try
114+ {
115+ Method getPath = StorageVolume .class .getMethod ( "getPath" );
116+ StorageManager storageManager = (StorageManager ) context .getSystemService ( Context .STORAGE_SERVICE );
117+ for ( StorageVolume volume : storageManager .getStorageVolumes () )
118+ potentialDrives .add ( (String ) getPath .invoke ( volume ) );
119+ }
120+ catch ( Exception e )
121+ {
122+ }
123+ }
124+
125+ for ( String potentialDrive : potentialDrives )
126+ {
127+ File file = new File ( potentialDrive );
128+ if ( file .exists () && file .isDirectory () && file .canRead () && !file .getAbsolutePath ().equalsIgnoreCase ( primaryPath ) )
129+ {
130+ String absolutePath = file .getAbsolutePath () + File .separator + "Android" ;
131+ if ( new File ( absolutePath ).exists () )
132+ {
133+ try
134+ {
135+ // Check if two paths lead to same storage (aliases)
136+ if ( !primaryCanonicalPath .equals ( file .getCanonicalPath () ) )
137+ stringBuilder .append ( file .getAbsolutePath () ).append ( ":" );
138+ }
139+ catch ( Exception ex )
140+ {
141+ }
142+ }
143+ }
144+ }
145+
128146 return stringBuilder .toString ();
129147 }
130148
0 commit comments