Samsung Galaxy S3には、外部SDカードスロットが搭載されてい/mnt/extSdCard
ます。
どうすればこのパスを取得できEnvironment.getExternalStorageDirectory()
ますか?
これはを返しmnt/sdcard
、外部SDカードのAPIが見つかりません。(または一部のタブレットではリムーバブルUSBストレージ。)
Samsung Galaxy S3には、外部SDカードスロットが搭載されてい/mnt/extSdCard
ます。
どうすればこのパスを取得できEnvironment.getExternalStorageDirectory()
ますか?
これはを返しmnt/sdcard
、外部SDカードのAPIが見つかりません。(または一部のタブレットではリムーバブルUSBストレージ。)
回答:
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;
}
元のメソッドはテストされ、
彼らがテストされたとき、私はこれらがどのアンドロイドバージョンであったかわかりません。
私は修正したバージョンをテストしました
また、SDカードをメインストレージとして使用する単一のストレージデバイス
Incredibleを除いて、これらすべてのデバイスはリムーバブルストレージのみを返しました。たぶん、追加のチェックがいくつかあるはずですが、これは、これまでに見つけたどのソリューションよりも少なくとも少しは優れています。
システム内のすべてのSD-CARDへのパスを取得するより信頼性の高い方法を見つけました。これは、すべてのAndroidバージョンで機能し、すべてのストレージ(エミュレート済みを含む)へのパスを返します。
すべてのデバイスで正しく動作します。
PS:Environmentクラスのソースコードに基づいています。
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()]);
}
Pattern
のために/
System.getenv("SECONDARY_STORAGE")
返されるMarshmallow(Galaxy Tab A w / 6.0.1)では機能しません/storage/sdcard1
。その場所は存在しませんが、実際の場所はです/storage/42CE-FD0A
。ここで、42CE-FD0Aはフォーマットされたパーティションのボリュームシリアル番号です。
私はあなたがこれを使用する必要がある外部SDカードを使用すると思います:
new File("/mnt/external_sd/")
または
new File("/mnt/extSdCard/")
あなたの場合...
の代わりに Environment.getExternalStorageDirectory()
私のために働く。最初にディレクトリmntの内容を確認し、そこから作業する必要があります。
使用するSDカードを選択するには、いくつかのタイプの選択方法を使用する必要があります。
File storageDir = new File("/mnt/");
if(storageDir.isDirectory()){
String[] dirList = storageDir.list();
//TODO some type of selecton method?
}
すべての外部ストレージを取得するには(SDカードであるか、リムーバブルでない内部ストレージであるかにかかわらず)、次のコードを使用できます。
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");
}
}
}
}
または、System.getenv( "EXTERNAL_STORAGE")を使用してプライマリ外部ストレージディレクトリ("/ storage / sdcard0"など)を取得し、System.getenv( "SECONDARY_STORAGE")を使用してすべてのセカンダリディレクトリ(例:" / storage / extSdCard:/ storage / UsbDriveA:/ storage / UsbDriveB ")。この場合も、USBドライブを除外するために、セカンダリディレクトリのリストをフィルタリングしたい場合があることに注意してください。
いずれにせよ、ハードコードされたパスを使用することは常に悪いアプローチであることに注意してください(特に、すべての製造元が満足できるように変更する場合)
Asus Zenfone2、Marshmallow 6.0.1を確認してソリューションが機能しなくなるまで、Dmitriy Lozenkoのソリューションを使用していました。EMULATED_STORAGE_TARGETを取得するときに、特にmicroSDパス(/ storage / F99C-10F4 /など)でソリューションが失敗しました。コードを編集して、エミュレートされたアプリケーションパスからエミュレートされたルートパスを直接取得し、より既知の電話モデル固有の物理パスを追加しました。context.getExternalFilesDirs(null);
私たちの生活を楽にするために、ここにライブラリを作成しました。gradle、maven、sbt、およびleiningenビルドシステムを介して使用できます。
昔ながらの方法が好きな場合は、ここから直接ファイルをコピーして貼り付けることもできますが、手動でチェックしないと、将来のアップデートがあるかどうかわかりません。
ご質問やご提案がございましたら、お知らせください
context.getExternalFilesDirs(null)
とnull
、いずれかのファイルが返され、次のループで例外が発生します。if (file == null) continue;
ループの最初の行として追加することをお勧めします。
朗報!KitKatには、これらのセカンダリ共有ストレージデバイスとやり取りするためのパブリックAPIがあります。
新しいメソッドContext.getExternalFilesDirs()
とContext.getExternalCacheDirs()
メソッドは、プライマリデバイスとセカンダリデバイスの両方を含む複数のパスを返すことができます。あなたは、それらを反復して確認することができますEnvironment.getStorageState()
し、File.getFreeSpace()
あなたのファイルを保存するのに最適な場所を決定します。これらのメソッドはContextCompat
、support-v4ライブラリでも利用できます。
またContext
、によって返されるディレクトリの使用のみに関心がある場合は、READ_
またはWRITE_EXTERNAL_STORAGE
権限は不要になることにも注意してください。今後は、これらのディレクトリへの読み取り/書き込みアクセス権が常に付与され、追加の権限は必要ありません。
アプリは、次のように許可リクエストを終了することで、古いデバイスでも引き続き動作できます。
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
すべての外部sdカードにアクセスするために、次のことを行いました。
と:
File primaryExtSd=Environment.getExternalStorageDirectory();
プライマリ外部SDへのパスを取得します。
File parentDir=new File(primaryExtSd.getParent());
プライマリ外部ストレージの親ディレクトリを取得し、すべての外部sdの親でもあります。これで、すべてのストレージをリストして、必要なストレージを選択できます。
お役に立てれば幸いです。
SDカードパス(プライマリ外部ストレージを除く)のリストを取得する方法は次のとおりです。
/**
* 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
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static List<String> getSdCardPaths(final Context context,final boolean includePrimaryExternalStorage)
{
final File[] externalCacheDirs=ContextCompat.getExternalCacheDirs(context);
if(externalCacheDirs==null||externalCacheDirs.length==0)
return null;
if(externalCacheDirs.length==1)
{
if(externalCacheDirs[0]==null)
return null;
final String storageState=EnvironmentCompat.getStorageState(externalCacheDirs[0]);
if(!Environment.MEDIA_MOUNTED.equals(storageState))
return null;
if(!includePrimaryExternalStorage&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB&&Environment.isExternalStorageEmulated())
return null;
}
final List<String> result=new ArrayList<>();
if(includePrimaryExternalStorage||externalCacheDirs.length==1)
result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0]));
for(int i=1;i<externalCacheDirs.length;++i)
{
final File file=externalCacheDirs[i];
if(file==null)
continue;
final String storageState=EnvironmentCompat.getStorageState(file);
if(Environment.MEDIA_MOUNTED.equals(storageState))
result.add(getRootOfInnerSdCardFolder(externalCacheDirs[i]));
}
if(result.isEmpty())
return null;
return result;
}
/** Given any file/folder inside an sd card, this will return the path of the sd card */
private static String getRootOfInnerSdCardFolder(File file)
{
if(file==null)
return null;
final long totalSpace=file.getTotalSpace();
while(true)
{
final File parentFile=file.getParentFile();
if(parentFile==null||parentFile.getTotalSpace()!=totalSpace||!parentFile.canRead())
return file.getAbsolutePath();
file=parentFile;
}
}
externalCacheDirs[0].getParentFile().getParentFile().getParentFile().getParentFile().getAbsolutePath()
これは災害のレシピです。これを行っている場合は、必要なパスをハードコードするだけでよいでしょう。4つの親以外のキャッシュディレクトリを取得すると、NullPointerExceptionまたは間違ったパスが返されます。
皆さん、特に@SmartLemonから提供された手がかりをありがとう、私は解決策を得ました。他の誰かがそれを必要とする場合、私はここに私の最終的な解決策を置きます(最初にリストされた外部SDカードを見つけるために):
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;
}
そこに外部SDカードがない場合は、オンボードストレージを返します。SDカードが存在しない場合は使用しますが、変更する必要がある場合があります。
私のコードを参照してください、あなたに役立つことを願っています:
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);
実際、一部のデバイスでは、外部SDカードのデフォルト名がとして表示されextSdCard
、他のデバイスではデフォルト名が表示されますsdcard1
。
このコードスニペットは、その正確なパスを見つけ、外部デバイスのパスを取得するのに役立ちます。
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);
}
はい。製造元によって、Samsung Tab 3のextsdのように異なるSDカード名を使用し、他のサムスンデバイスでは、この異なる製造元が異なる名前を使用するようにsdcardを使用します。
私はあなたと同じ要件を持っていました。だから私は私のプロジェクトからサンプルのサンプルを作成しましたandroi-dirchooserライブラリを使用するこのリンクAndroid Directory Chooserサンプルに移動します この例では、SDカードを検出してすべてのサブフォルダーを一覧表示し、デバイスに複数のSDカードがあるかどうかも検出します。
コードの一部は次のようになります。完全な例については、リンク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);
}
}
});
このソリューション(この質問に対する他の回答から集められたもの)System.getenv("SECONDARY_STORAGE")
は、マシュマロでは役に立たない(@onoによって言及された)事実を処理します。
テスト済みで作業中:
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;
}
rawSecondaryStoragesStr.contains(path)
により、内部ストレージも追加される可能性があります。私はその状態をよりよく取り除くことができます。私のデバイスはで内部ストレージディレクトリをSystem.getenv("SECONDARY_STORAGE")
返しますがSystem.getenv(EXTERNAL_STORAGE)
、KitKatでは外部メモリカードパスを返すため、この問題に直面しました。...異なるベンダーがどのいまいましい標準なしで異なり、これを実装していたようだ
一部のデバイス(samsung galaxy sIIなど)では、内部メモリカードがvfatになっています。この場合、最後の参照コードを使用して、パス内部メモリカード(/ mnt / sdcad)を取得しますが、外部カードは取得しません。以下のコードを参照してこの問題を解決してください。
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);
}
このコードで問題が確実に解決されると思います...これは私にとってはうまく機能しています... \
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();
}
それは真実ではない。/ mnt / sdcard / external_sdは、SDカードがマウントされていなくても存在できます。マウントされていないときに/ mnt / sdcard / external_sdに書き込もうとすると、アプリケーションがクラッシュします。
最初にSDカードがマウントされているかどうかを確認する必要があります。
boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
getExternalStorageState()
外付けのSDカードではなく、内部のストレージを返却しても意味がないと思います。
-Context.getExternalCacheDirs()、Context.getExternalFilesDirs()、Context.getObbDirs()などを使用できます。これらは、アプリケーションがファイルを保存できるすべての外部ストレージデバイスにアプリケーション固有のディレクトリを提供します。
したがって、このようなもの-Context.getExternalCacheDirs()[i] .getParentFile()。getParentFile()。getParentFile()。getParent()は、外部ストレージデバイスのルートパスを取得できます。
これらのコマンドが別の目的で使用されていることはわかっていますが、他の回答ではうまくいきませんでした。
このリンクは私に良い指針を与えました-https ://possiblemobile.com/2014/03/android-external-storage/
System.getenv("SECONDARY_STORAGE")
マシュマロの場合はnullを返します。これは、すべての外部ディレクトリを見つける別の方法です。あなたはそれが内部/外部かどうかを決定する取り外し可能かどうかを確認することができます
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
}
}
}
私はによって提供ソリューション試してみましたドミトリLozenkoとGnathonic上の私のサムスンギャラクシータブS2(モデル:T819Y)が、どれも私は、外部SDカードのディレクトリへのパスを取得助けません。mount
コマンドの実行には、外部SDカードディレクトリへの必要なパス(/ Storage / A5F9-15F4など)が含まれていましたが、正規表現と一致しなかったため、返されませんでした。サムスンが続いているディレクトリ命名メカニズムがわかりません。なぜ標準(extsdcardなど)から逸脱して、私の場合(/ Storage / A5F9-15F4など)のように本当に魚のようなものを思いついたのですか。不足しているものはありますか?とにかく、の正規表現の変更に続いて Gnathonicの ソリューションは私が有効なSDカードディレクトリを取得するのに役立ちました:
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;
これが有効なソリューションであるかどうか、また他のSamsungタブレットで結果が得られるかどうかはわかりませんが、今のところ問題は解決しています。以下は、Android(v6.0)でリムーバブルSDカードのパスを取得する別の方法です。私はAndroidマシュマロでメソッドをテストしましたが、動作します。その中で使用されるアプローチは非常に基本的で、他のバージョンでも確実に機能しますが、テストは必須です。それにいくつかの洞察が役立つでしょう:
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;
}
この問題を処理する他のアプローチがある場合は、親切に共有してください。ありがとう
//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);
Galaxy S3 Android 4.3では、私が使用するパスは./storage/extSdCard/Card/で、それが機能します。それが役に立てば幸い、
次の手順でうまくいきました。あなたはこの行を書くだけです:
String sdf = new String(Environment.getExternalStorageDirectory().getName());
String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));
最初の行はsdディレクトリの名前を示し、2番目の文字列のreplaceメソッドでそれを使用する必要があるだけです。2番目の文字列には、内部およびリムーバブルsd(私の場合は/ storage /)のパスが含まれます。アプリにこのパスが必要だったのですが、必要に応じてさらに先に進むことができます。