मैं एंड्रॉइड 4.0+ के लिए बाहरी एसडी कार्ड पथ कैसे प्राप्त कर सकता हूं?


94

सैमसंग गैलेक्सी एस 3 में एक बाहरी एसडी कार्ड स्लॉट है, जिसे माउंट किया गया है /mnt/extSdCard

मैं यह रास्ता कैसे प्राप्त कर सकता हूं Environment.getExternalStorageDirectory()?

यह वापस आ जाएगा mnt/sdcard, और मुझे बाहरी एसडी कार्ड के लिए एपीआई नहीं मिल सकता है। (या कुछ टेबलेट पर हटाने योग्य USB संग्रहण।)


आप ऐसा क्यों चाहते हैं? एंड्रॉइड पर इस तरह की चीजें करना बहुत ही असावधान है। शायद अगर आप अपनी प्रेरणा साझा करते हैं तो हम आपको इस प्रकार की चीज़ के लिए सर्वोत्तम अभ्यास की दिशा में इंगित कर सकते हैं।
23

2
जब आपका उपयोगकर्ता अपना फोन बदलता है, तो एसडी कार्ड को नए फोन में प्लग करें, और पहले फोन पर यह / sdcard है, दूसरे फोन पर यह / mnt / extSdCard है, फ़ाइल पथ का उपयोग करके कुछ भी दुर्घटनाग्रस्त हो जाता है। मुझे इसके सापेक्ष पथ से वास्तविक मार्ग उत्पन्न करने की आवश्यकता है।
रोमुलस उरागी त्सै

अब मैं यह विषय पुराना हो गया हूं, लेकिन इससे मदद मिल सकती है। आपको इस विधि का उपयोग करना चाहिए। System.getenv (); अपने डिवाइस से जुड़े सभी स्टोरेज को एक्सेस करने के लिए प्रोजेक्ट एनवायरनमेंट 3 देखें। github.com/omidfaraji/Environment3
ओमिद फ़राजी


यहाँ मेरा समाधान है जो नौगट तक काम करता है: stackoverflow.com/a/40205116/5002496
गोकुल NC

जवाबों:


58

मुझे यहां मिले एक समाधान पर भिन्नता है

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;
}

मूल विधि का परीक्षण किया गया और इसके साथ काम किया गया

  • हुआवेई एक्स 3 (स्टॉक)
  • गैलेक्सी एस 2 (स्टॉक)
  • गैलेक्सी एस 3 (स्टॉक)

मुझे यकीन नहीं है कि जब वे परीक्षण किए गए थे, तो ये कौन से Android संस्करण थे।

मैंने अपने संशोधित संस्करण का परीक्षण किया है

  • Moto Xoom 4.1.2 (स्टॉक)
  • गैलेक्सी नेक्सस (cyanogenmod 10) एक ओटीजी केबल का उपयोग कर
  • HTC अतुल्य (cyanogenmod 7.2) यह आंतरिक और बाहरी दोनों को लौटाता है। यह डिवाइस एक ऑडबॉल है जिसमें इसका आंतरिक काफी हद तक अप्रयुक्त हो जाता है क्योंकि getExternalStorage () इसके बजाय scard के लिए एक रास्ता देता है।

और कुछ एकल स्टोरेज डिवाइस जो अपने मुख्य स्टोरेज के रूप में sdcard का उपयोग करते हैं

  • एचटीसी जी 1 (सियानोजेनमॉड 6.1)
  • HTC G1 (स्टॉक)
  • एचटीसी विजन / जी 2 (स्टॉक)

अतुल्य को छोड़कर इन सभी उपकरणों ने केवल अपने हटाने योग्य भंडारण को वापस कर दिया। संभवत: कुछ अतिरिक्त जांचें हैं जो मुझे करनी चाहिए, लेकिन यह मेरे द्वारा अब तक किए गए किसी भी समाधान से कम से कम थोड़ा बेहतर है।


3
मुझे लगता है कि आप समाधान को अमान्य फ़ोल्डर नाम देंगे यदि मूल में / mnt / SdCard जैसे बड़े अक्षर हों
Eugene Popovich

1
मैंने कुछ मोटोरोला, सैमसंग और एलजी उपकरणों पर परीक्षण किया है और यह सही काम किया है।
पेपीडुतिको

2
@ KhawarRaza, इस विधि ने किटकैट के रूप में काम करना बंद कर दिया। दिमित्री लोज़ेंको की विधि का उपयोग करें, इस के साथ एक कमबैक के रूप में यदि आप पूर्व-ईआईसी उपकरणों का समर्थन कर रहे हैं।
Gnathonic

1
HUAWEI ऑनर 3 सी पर काम करता है। धन्यवाद।
ली

2
यह मेरे लिए 4.0+ पर लौटा रहा है / बजाय / भंडारण MNT पर एक गैलेक्सी नोट 3
ओनो

54

मुझे सिस्टम में सभी एसडी-कार्ड्स के रास्ते प्राप्त करने के लिए अधिक विश्वसनीय तरीका मिला। यह सभी एंड्रॉइड संस्करणों पर काम करता है और सभी स्टोरेज (वापसी सहित) के लिए पथ देता है।

मेरे सभी उपकरणों पर सही ढंग से काम करता है।

PS: पर्यावरण वर्ग के स्रोत कोड के आधार पर।

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()]);
}

5
DIR_SEPORATOR क्या माना जाता है?
cYrixmorten

1
@ cYrixmorten कोड के शीर्ष पर प्रदान किया गया है .. इसके Patternलिए/
अंकित बंसल

किसी ने लॉलीपॉप पर इस समाधान का परीक्षण किया?
lenrok258

मैं lenovo P780 पर इस विधि की कोशिश की। यह काम नहीं कर रहा है।
सतीश कुमार

2
लॉलीपॉप तक काम करता है; मार्शमैलो पर काम नहीं कर रहा है (गैलेक्सी टैब ए w / 6.0.1) जहां System.getenv("SECONDARY_STORAGE")रिटर्न मिलता है /storage/sdcard1। वह स्थान मौजूद नहीं है, लेकिन वास्तविक स्थान वह है /storage/42CE-FD0A, जहां 42CE-FD0A स्वरूपित विभाजन का वॉल्यूम क्रमांक है।
डेवल्डन सेप

32

मुझे लगता है कि बाहरी sdcard का उपयोग करने के लिए आपको इसका उपयोग करने की आवश्यकता है:

new File("/mnt/external_sd/")

या

new File("/mnt/extSdCard/")

आपके मामले में...

के स्थान पर Environment.getExternalStorageDirectory()

मेरे लिये कार्य करता है। आप पहले निर्देशिका में whats की जाँच करें और वहाँ से काम करें ।।


आपको किस प्रकार का sdcard उपयोग करना है, यह चुनने के लिए आपको कुछ प्रकार की चयन विधि का उपयोग करना चाहिए:

File storageDir = new File("/mnt/");
if(storageDir.isDirectory()){
    String[] dirList = storageDir.list();
    //TODO some type of selecton method?
}

1
वैसे वास्तव में मुझे हार्ड-कोड पथ के बजाय एक विधि चाहिए, लेकिन / mnt / सूची ठीक होनी चाहिए। धन्यवाद।
रोमुलस उरागी त्सै

कोई दिक्कत नहीं है। सेटिंग्स में एक विकल्प है, जिसमें से आप रास्ता चुनते हैं, फिर इसे पुनः प्राप्त करने के लिए विधि का उपयोग करें।
FabianCook

10
दुर्भाग्य से बाहरी एसडी कार्ड / mnt की तुलना में एक अलग फ़ोल्डर में हो सकता है। उदाहरण के लिए सैमसंग GT-I9305 पर यह / स्टोरेज / एक्सटर्डकार्ड है जबकि इन-बिल्ट एसडी कार्ड में पथ / स्टोरेज / sdcard0 है
iseeall

2
ठीक है फिर आपको sdcard स्थान मिलेगा, फिर इसकी मूल निर्देशिका प्राप्त होगी।
FabianCook

एंड्रॉइड 4.0+ के लिए बाहरी एसडी कार्ड (ओटीजी केबल के माध्यम से टैबलेट से जुड़े पेनड्राइव के लिए) का रास्ता क्या होगा?
ओसिमेर पोथे

15

सभी बाहरी स्टोरेज (चाहे वे एसडी कार्ड हों या आंतरिक नॉन-रिमूवेबल स्टोरेज ) को पुनः प्राप्त करने के लिए , आप निम्न कोड का उपयोग कर सकते हैं:

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") प्राथमिक बाह्य संग्रह डायरेक्ट्री पुनः प्राप्त करने (जैसे "/ भंडारण / sdcard0" ) और System.getenv ( "SECONDARY_STORAGE") सभी माध्यमिक निर्देशिका की सूची retieve लिए (उदाहरण के लिए " / संग्रहण / extSdCard: / संग्रहण / UsbDriveA: / संग्रहण / UsbDriveB " )। याद रखें कि, इस मामले में भी, आप USB ड्राइव को बाहर करने के लिए द्वितीयक निर्देशिकाओं की सूची को फ़िल्टर करना चाह सकते हैं।

किसी भी मामले में, कृपया ध्यान दें कि हार्ड-कोडेड रास्तों का उपयोग करना हमेशा एक बुरा दृष्टिकोण होता है (स्पष्ट रूप से जब प्रत्येक निर्माता इसे प्रसन्नता के रूप में बदल सकता है)।


System.getenv ("SECONDARY_STORAGE") नेक्सस 5 और नेक्सस 7. पर OTG केबल के माध्यम से संलग्न USB उपकरणों के लिए काम नहीं किया।
खरवार रजा

यहाँ मेरा समाधान है जो नौगट तक काम करता है: stackoverflow.com/a/40205116/5002496
गोकुल NC

14

मैं दिमित्री लोज़ेंको के समाधान का उपयोग कर रहा था जब तक कि मैं एक असूस ज़ेनफोन 2 , मार्शमैलो 6.0.1 पर जाँच नहीं करता और समाधान काम नहीं कर रहा है। EMULATED_STORAGE_TARGET प्राप्त करते समय समाधान विफल हो गया , विशेष रूप से माइक्रोएसडी पथ के लिए, अर्थात: / संग्रहण / F99C-10F4 / । मैंने अनुकरण किए गए एप्लिकेशन पथों से सीधे रूट किए गए रूट पथ प्राप्त करने context.getExternalFilesDirs(null);और अधिक ज्ञात फ़ोन-मॉडल-विशिष्ट भौतिक पथों को जोड़ने के लिए कोड को संपादित किया ।

हमारे जीवन को आसान बनाने के लिए, मैंने यहां एक पुस्तकालय बनाया । आप इसे ढाल, मावेन, एसबीटी और लिनिंजेन बिल्ड सिस्टम के माध्यम से उपयोग कर सकते हैं।

यदि आपको पुराने जमाने का तरीका पसंद है, तो आप फ़ाइल को सीधे यहां से कॉपी पेस्ट भी कर सकते हैं , लेकिन आपको यह नहीं पता होगा कि भविष्य में कोई अपडेट मैन्युअल रूप से जांचे बिना है।

यदि आपके कोई प्रश्न या सुझाव हैं, तो कृपया मुझे बताएं


1
मैंने इसे बड़े पैमाने पर इस्तेमाल नहीं किया है, लेकिन यह मेरी समस्या के लिए अच्छा काम करता है।
डेविड

1
महान समाधान! एक नोट हालांकि - यदि आवेदन सक्रिय होने पर एसडी कार्ड हटा दिया जाता है, context.getExternalFilesDirs(null)तो nullएक फाइल के लिए वापस आ जाएगा और निम्नलिखित लूप में अपवाद होगा। मैं if (file == null) continue;लूप में पहली पंक्ति के रूप में जोड़ने का सुझाव देता हूं ।
Koger

1
@Koger आपको सुझाव के लिए धन्यवाद, मैंने इसे जोड़ा है और मेरे जवाब के लिए एक टाइपो तय किया है
HendraWD

13

खुशखबरी! किटकैट में अब इन सेकेंडरी शेयर्ड स्टोरेज डिवाइसों के साथ बातचीत करने के लिए एक सार्वजनिक एपीआई है।

नए Context.getExternalFilesDirs()और Context.getExternalCacheDirs()तरीके प्राथमिक और माध्यमिक दोनों उपकरणों सहित कई पथ वापस कर सकते हैं। इसके बाद आप पुनरावृति उन पर और जांच कर सकते हैं Environment.getStorageState()और File.getFreeSpace()अपनी फाइलों को स्टोर करने के लिए सबसे अच्छी जगह निर्धारित करने के लिए। ये तरीके ContextCompatsupport-v4 लाइब्रेरी में भी उपलब्ध हैं ।

यह भी ध्यान दें कि यदि आप केवल द्वारा निर्देशित निर्देशिकाओं का उपयोग करने में रुचि रखते हैं Context, तो आपको अब READ_या WRITE_EXTERNAL_STORAGEअनुमतियों की आवश्यकता नहीं है । आगे बढ़ते हुए, आपको हमेशा इन निर्देशिकाओं तक पहुंच / लिखना होगा, जिनमें कोई अतिरिक्त अनुमति नहीं होगी।

ऐप्स अपने पुराने अनुरोध को इस तरह से समाप्त करके पुराने उपकरणों पर काम करना जारी रख सकते हैं:

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />

धन्यवाद। मैंने कुछ कोड बनाए हैं जो आपके द्वारा लिखे गए हैं, और मुझे लगता है कि यह सभी एसडी कार्ड पथों को खोजने में अच्छा काम करता है। क्या आप देख सकते हैं? यहाँ: stackoverflow.com/a/27197248/878126 BTW, आपको "getFreeSpace" का उपयोग नहीं करना चाहिए क्योंकि सैद्धांतिक रूप से, फ्री स्पेस रनटाइम के दौरान बदल सकता है।
Android डेवलपर

सामने संदर्भ developer.android.com/reference/android/content/...
Strubbl

10

मैं सभी बाहरी एसडी कार्ड के लिए acces पाने के लिए निम्नलिखित किया है।

साथ में:

File primaryExtSd=Environment.getExternalStorageDirectory();

आपको प्राथमिक बाहरी एसडी का रास्ता मिलता है:

File parentDir=new File(primaryExtSd.getParent());

आपको प्राथमिक बाह्य संग्रहण का मूल अभिभावक मिलता है, और यह सभी बाहरी एसडी का अभिभावक भी है। अब, आप सभी स्टोरेज को सूचीबद्ध कर सकते हैं और जो आप चाहते हैं उसे चुन सकते हैं।

आशा है कि यह उपयोगी है।


यह स्वीकृत उत्तर होना चाहिए, और धन्यवाद यह उपयोगी है।
मीनमन

9

यहां बताया गया है कि मुझे एसडी-कार्ड पथ (प्राथमिक बाहरी भंडारण को छोड़कर) की सूची कैसे मिलती है:

  /**
   * 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 या गलत रास्ता मिल जाएगा।
23

@ अक्षर सही। इस मुद्दे को भी तय किया। कृपया एक नज़र डालें।
Android डेवलपर

डॉक्स ( developer.android.com/reference/android/content/… ) कहते हैं, "यहां लौटे बाहरी स्टोरेज डिवाइस को डिवाइस का एक स्थायी हिस्सा माना जाता है, जिसमें एम्युलेटेड एक्सटर्नल स्टोरेज और फिजिकल मीडिया स्लॉट, जैसे कि बैटरी में एसडी कार्ड दोनों शामिल हैं। कम्पार्टमेंट। लौटे हुए रास्तों में क्षणिक उपकरण शामिल नहीं हैं, जैसे USB फ्लैश ड्राइव। " ऐसा लगता है कि वे एसडी कार्ड स्लॉट भी शामिल नहीं करते हैं, यानी जिन जगहों पर आप बैटरी के बिना एसडी कार्ड निकाल सकते हैं। हालांकि बताना मुश्किल है।
लार्स

1
@ लार्स खैर, मैंने इसे खुद एसजीएस 3 (और असली एसडी-कार्ड) पर परीक्षण किया है, इसलिए मुझे लगता है कि इसे अन्य उपकरणों पर भी काम करना चाहिए।
Android डेवलपर

5

आप लोगों द्वारा प्रदान किए गए सुरागों के लिए धन्यवाद, विशेष रूप से @SmartLemon, मुझे समाधान मिला। यदि किसी और को इसकी आवश्यकता है, तो मैंने अपना अंतिम समाधान यहां रखा (पहला सूचीबद्ध बाहरी एसडी कार्ड खोजने के लिए):

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;
}

यदि कोई बाहरी एसडी कार्ड नहीं है, तो यह ऑन बोर्ड स्टोरेज लौटाता है। मैं इसका उपयोग करूंगा यदि sdcard मौजूद नहीं है, तो आपको इसे बदलने की आवश्यकता हो सकती है।


1
यह एंड्रॉइड वर्जन 19 पर null फेंक रहा है। rootDir.listFiles () रिटर्न null है। मैंने इसे नेक्सस 7, एमुलेटर और गैलेक्सी नोट के साथ परीक्षण किया है।
मनु ज़ी

3

मेरे कोड का संदर्भ लें, आशा है कि आपके लिए उपयोगी:

    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);

2

वास्तव में कुछ उपकरणों में बाहरी sdcard डिफ़ॉल्ट नाम के रूप में 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);
         }

इससे मुझे काफी मदद मिली।
Droid Chris

कुछ डिवाइस हैं जो "/ स्टोरेज / एक्सटर्नल_एसडी" (एलजी जी 3 किटकैट) का उपयोग करते हैं, मार्शमैलो की कुछ अलग योजना है, एंड्रॉइड 6.0 का उपयोग करते हुए नेक्सस 5 एक्स पर आंतरिक भंडारण "/ mnt / sdcard" है और बाहरी प्रोसेसर "/ स्टोरेज" के तहत पाया जाता है। / XXXX-XXXX "
एबी

2

हाँ। अलग-अलग निर्माता सैमसंग टैब 3 में अपने एसडीएसटी जैसे अलग एसडीकार्ड नाम का उपयोग करते हैं, और अन्य सैमसंग डिवाइस एसडीकार्ड का उपयोग करते हैं जैसे यह अलग-अलग निर्माता अलग-अलग नामों से करते हैं।

मुझे आपकी जैसी आवश्यकता थी। इसलिए मैंने अपने प्रोजेक्ट गोटो से आपके लिए एक नमूना उदाहरण बनाया है इस लिंक एंड्रॉइड डायरेक्टरी चॉसर उदाहरण जो androi-dirchooser लाइब्रेरी का उपयोग करता है। यह उदाहरण एसडीकार्ड का पता लगाता है और सभी सबफोल्डरों को सूचीबद्ध करता है और यह भी पता लगाता है कि डिवाइस में एक एसडीकार्ड है या नहीं।

कोड का हिस्सा इस तरह दिखता है पूर्ण उदाहरण के लिए लिंक एंड्रॉइड डायरेक्टरी चयनकर्ता गोटो

/**
* 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);
        }


    }
});

2

यह समाधान (इस प्रश्न के अन्य उत्तरों से इकट्ठा) तथ्य को संभालता है (जैसा कि @ono द्वारा उल्लेख किया गया है) जो कि मार्शमैलो के System.getenv("SECONDARY_STORAGE")साथ कोई फायदा नहीं है।

परीक्षण किया गया और इस पर काम किया जा रहा है:

  • सैमसंग गैलेक्सी टैब 2 (एंड्रॉयड 4.1.1 - स्टॉक)
  • सैमसंग गैलेक्सी नोट 8.0 (एंड्रॉयड 4.2.2 - स्टॉक)
  • सैमसंग गैलेक्सी एस 4 (एंड्रॉइड 4.4 - स्टॉक)
  • सैमसंग गैलेक्सी एस 4 (एंड्रॉइड 5.1.1 - सियानोजेनमॉड)
  • सैमसंग गैलेक्सी टैब ए (एंड्रॉइड 6.0.1 - स्टॉक)

    /**
     * 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); ऐसा लगता है कि विभिन्न विक्रेताओं ने इसे बिना किसी मानक के अलग तरीके से लागू किया था ..
गोकुल नेकां

यहाँ मेरा समाधान है जो नौगट तक काम करता है: stackoverflow.com/a/40205116/5002496
गोकुल NC

1

कुछ उपकरणों पर (उदाहरण के लिए सैमसंग गैलेक्सी sII) आंतरिक मेमोरी कार्ड mabe 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;
}

1
       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);
                }

0

मुझे यकीन है कि यह कोड निश्चित रूप से आपके मुद्दों को हल करेगा ... यह मेरे लिए ठीक काम कर रहा है ... \

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();
        } 

Environment.getExternalStorageDirectory () आपको अपने बाहरी sdcard या usb लोकेशन का सही स्थान नहीं देना चाहिए। बस "/ proc / mounts" स्थान पर पार्स करें / फिर / dev / fuse / storage / sdcard1 "आपको वह स्थान देगा जहाँ आपका sdcard ठीक से है usb के लिए भी घुड़सवार या समान नहीं। इस तरह से आप इसे आसानी से प्राप्त कर सकते हैं।चेयरर्स।साम
सैम

0

यह सच नहीं है। / mnt / sdcard / external_sd तब भी मौजूद हो सकता है, जब एसडी कार्ड माउंट न हो। जब आप माउंट नहीं होते हैं तो आप / mnt / sdcard / external_sd को लिखने की कोशिश करने पर आपका एप्लिकेशन क्रैश हो जाएगा।

आपको यह जांचने की आवश्यकता है कि पहले एसडी कार्ड का उपयोग करके माउंट किया गया है या नहीं:

boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);

7
जब getExternalStorageState()मैं बाहरी एसडी कार्ड के बजाय आंतरिक भंडारण को वापस करता हूं तो यह अर्थहीन है।
रोमुलस उराकगी त्सै

क्या वे बाहरी एसडी कार्ड प्राप्त करने के लिए एक फ़ंक्शन प्रदान करते हैं? एक घंटे तक आसपास तलाश करने के बाद भी मुझे कोई सुराग नहीं मिला। यदि यह मामला है, तो इतने सारे संस्करणों को अपडेट करने के बाद यह बहुत अजीब है।
आरएल

जब आपने कहा कि "यह सच नहीं है", तो आप क्या कर रहे थे? मुझे पता है, वह 2.5 साल पहले था ...
लार्स

0
 String path = Environment.getExternalStorageDirectory()
                        + File.separator + Environment.DIRECTORY_PICTURES;
                File dir = new File(path);

4
यह काम नहीं करता है। यह आंतरिक संग्रहण का पथ देता है। यानी / भंडारण /

0

आप कुछ का उपयोग कर सकते हैं जैसे - Context.getExternalCacheDirs () या Context.getExternalFilesDirs () या Context.getObbDirs ()। वे सभी बाहरी भंडारण उपकरणों में एप्लिकेशन विशिष्ट निर्देशिकाएं देते हैं जहां एप्लिकेशन अपनी फ़ाइलों को संग्रहीत कर सकता है।

तो कुछ इस तरह से - Context.getExternalCacheDirs () [i] .getParentFile ()। GetParentFile ()। GetParentFile ()। GetParent () आपको बाहरी स्टोरेज डिवाइस का रूट पा सकता है।

मुझे पता है कि ये आदेश एक अलग उद्देश्य के लिए हैं, लेकिन अन्य उत्तर मेरे लिए काम नहीं करते हैं।

इस लिंक ने मुझे अच्छे संकेत दिए - https://possiblemobile.com/2014/03/android-external-storage/


0

System.getenv("SECONDARY_STORAGE")मार्शमैलो के लिए शून्य देता है। यह सभी बाहरी डेयरियों को खोजने का एक और तरीका है। आप जाँच सकते हैं कि क्या यह हटाने योग्य है जो निर्धारित करता है कि आंतरिक / बाहरी

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
        }
    }
}

0

मैंने अपने सैमसंग गैलेक्सी टैब S2 (मॉडल: T819Y) पर दिमित्री लोज़ेंको और ग्नथोनिक द्वारा प्रदान किए गए समाधानों की कोशिश की है, लेकिन किसी ने भी मुझे एक बाहरी एसडी कार्ड निर्देशिका के लिए रास्ता निकालने में मदद नहीं की। कमांड निष्पादन में बाहरी एसडी कार्ड निर्देशिका (यानी / संग्रहण / A5F9-15F4) के लिए आवश्यक पथ शामिल था, लेकिन यह नियमित अभिव्यक्ति से मेल नहीं खाता था इसलिए इसे वापस नहीं किया गया था। मैं सैमसंग के बाद निर्देशिका नामकरण तंत्र नहीं मिलता है। क्यों वे मानकों (यानी extsdcard) से विचलित होते हैं और मेरे मामले में वास्तव में कुछ गड़बड़ करते हैं (जैसे / भंडारण / A5F9-15F4) । क्या मुझसे कुछ छूट रहा है? वैसे भी, Gnathonic की नियमित अभिव्यक्ति में परिवर्तन के बादmount समाधान से मुझे वैध एसडीकार्ड निर्देशिका प्राप्त करने में मदद मिली:

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;

मुझे यकीन नहीं है कि यह एक वैध समाधान है और यदि यह अन्य सैमसंग टैबलेट के लिए परिणाम देगा, लेकिन इसने अभी के लिए मेरी समस्या को ठीक कर दिया है। एंड्रॉइड (v6.0) में हटाने योग्य एसडी कार्ड पथ को पुनः प्राप्त करने के लिए एक और तरीका निम्नलिखित है। मैंने 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;
}

कृपया साझा करें यदि आपके पास इस मुद्दे को संभालने के लिए कोई अन्य दृष्टिकोण है। धन्यवाद


यहाँ मेरा समाधान है जो नौगट तक काम करता है: stackoverflow.com/a/40205116/5002496
गोकुल NC

मैं वास्तव में Asus जेनफोन 2 पर आप के साथ एक ही समस्या है, लेकिन मैं डिमिट्री Lozenko बजाय समस्या को हल करने से कोड बदलने stackoverflow.com/a/40582634/3940133
HendraWD

@ केंद्र सरकार जिस समाधान का सुझाव दे रही है वह एंड्रॉइड मार्शमैलो (6.0) के साथ काम नहीं कर सकता है क्योंकि इसमें पर्यावरण चर का समर्थन हटा दिया गया है। मैं बिल्कुल याद नहीं कर सकता, लेकिन मुझे लगता है कि मैंने इसे आज़मा लिया है।
अब्दुल रहमान

@ गोकुलएनसी मैं इसे आजमाऊंगा। वैध लगता है :)
अब्दुल रहमान 5

@ गोकुलएनसी हाँ, इसीलिए मैं संदर्भ का उपयोग करता हूं ।getExternalFilesDirs (नल); सीधे के बजाय भौतिक पथ का उपयोग करते हैं संस्करण> है Marshmallow
HendraWD

0
String secStore = System.getenv("SECONDARY_STORAGE");

File externalsdpath = new File(secStore);

इससे बाहरी एसडी सेकेंडरी स्टोरेज का रास्ता मिल जाएगा।


0
//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);

यह वैकल्पिक रूप से शुरुआती के लिए कम से कम डिवाइस में माउंट किए गए सभी ड्राइवरों के स्ट्रिंगलिस्ट है।
एम्रे किल्कि अर्सलान

0

अपने एसडी कार्ड में फ़ाइलों को एक्सेस करने के लिए , मेरे एचटीसी वन एक्स (एंड्रॉइड) पर, मैं इस रास्ते का उपयोग करता हूं:

file:///storage/sdcard0/folder/filename.jpg

त्रिक "/" पर ध्यान दें !


-1

गैलेक्सी S3 एंड्रॉइड 4.3 पर मैं जिस रास्ते का उपयोग करता हूं वह है ।/storage/extSdCard/Card/ और यह काम करता है। आशा करता हूँ की ये काम करेगा,


-1

निम्नलिखित चरणों ने मेरे लिए काम किया। आपको बस यह पंक्तियाँ लिखने की आवश्यकता है:

String sdf = new String(Environment.getExternalStorageDirectory().getName());
String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));

पहली पंक्ति एसडी निर्देशिका का नाम देगी, और आपको इसे दूसरे स्ट्रिंग के लिए प्रतिस्थापित विधि में उपयोग करने की आवश्यकता है। दूसरी स्ट्रिंग में आंतरिक और हटाने योग्य एसडी (/ भंडारण / मेरे मामले में) के लिए पथ होगा । मुझे बस अपने ऐप के लिए इस रास्ते की आवश्यकता थी लेकिन अगर आपको इसकी आवश्यकता है तो आप आगे बढ़ सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.