অপসারণযোগ্য এসডি কার্ডের অবস্থান সন্ধান করুন


204

বাহ্যিক এসডি কার্ডের অবস্থানটি খুঁজে পাওয়ার কোনও সর্বজনীন উপায় আছে কি?

দয়া করে, বাহ্যিক স্টোরেজ নিয়ে বিভ্রান্ত হবেন না ।

Environment.getExternalStorageState()"/ mnt / sdcard" এর মতো অভ্যন্তরীণ এসডি মাউন্ট পয়েন্টে পথ ফেরান। তবে প্রশ্নটি বাহ্যিক এসডি সম্পর্কে। আমি কীভাবে "/ mnt / sdcard / বহিরাগত_এসডি" এর মতো পাথ পাব (এটি ডিভাইস থেকে আলাদা হয়ে থাকতে পারে)?

আমার ধারণা আমি mountফাইল সিস্টেমের নামে কমান্ডের আউটপুট ফিল্টার করে শেষ করব with তবে আমি নিশ্চিত নই যে এই উপায়টি যথেষ্ট শক্ত।


এখানে আমার সমাধান যা নওগাট পর্যন্ত কাজ করে: stackoverflow.com/a/40205116/5002496
গোকুল এনসি

'এনভায়রনমেন্ট.জেটএক্সটার্নাল স্টোরেজ স্টেট () "/ mnt / sdcard" এর মতো অভ্যন্তরীণ এসডি মাউন্ট পয়েন্টের দিকে ফিরে আসে' ' আচ্ছা, অ্যান্ড্রয়েড শব্দটি ব্যবহার করে এমন অর্থে এটি অভ্যন্তরীণ নয়। আমি বিশ্বাস করি আপনি যে শব্দটির সন্ধান করছেন তা "অপসারণযোগ্য নয়"।
LarsH

উত্তর:


162

Environment.getExternalStorageState() "/ mnt / sdcard" এর মতো অভ্যন্তরীণ এসডি মাউন্ট পয়েন্টের দিকে ফেরার পথ

না, Environment.getExternalStorageDirectory()ডিভাইস নির্মাতাকে "বাহ্যিক স্টোরেজ" হিসাবে বিবেচনা করা যাই হোক না কেন বোঝায়। কিছু ডিভাইসে, এটি একটি এসডি কার্ডের মতো অপসারণযোগ্য মিডিয়া। কিছু ডিভাইসে এটি অন-ডিভাইস ফ্ল্যাশের একটি অংশ। এখানে, "বাহ্যিক স্টোরেজ" এর অর্থ "হোস্ট মেশিনে মাউন্ট করা অবস্থায় ইউএসবি মাস স্টোরেজ মোডের মাধ্যমে অ্যাক্সেসযোগ্য স্টাফ", কমপক্ষে অ্যান্ড্রয়েড 1.x এবং 2.x এর জন্য।

তবে প্রশ্নটি বাহ্যিক এসডি সম্পর্কে। "/ Mnt / sdcard / বহিরাগত_এসডি" এর মতো পাথ কীভাবে পাবেন (এটি ডিভাইস থেকে অন্য ডিভাইসে পৃথক হতে পারে)?

উপরে বর্ণিত হিসাবে বাহ্যিক স্টোরেজ বাদে অ্যান্ড্রয়েডের "বাহ্যিক এসডি" এর কোনও ধারণা নেই।

যদি কোনও ডিভাইস প্রস্তুতকারকের বাইরের স্টোরেজটি অন-বোর্ড ফ্ল্যাশ হওয়ার জন্য নির্বাচিত হয়ে থাকে এবং এর সাথে একটি এসডি কার্ডও থাকে, আপনি এসডি কার্ডটি ব্যবহার করতে পারবেন কিনা (গ্যারান্টিযুক্ত নয়) এবং নিয়মগুলি কী কী তা নির্ধারণ করার জন্য আপনাকে সেই নির্মাতার সাথে যোগাযোগ করতে হবে determine এটি ব্যবহার করে যেমন এর জন্য কোন পথ ব্যবহার করা উচিত।


হালনাগাদ

দুটি নোটের সাম্প্রতিক বিষয়:

প্রথমত, অ্যান্ড্রয়েড 4.4+, আপনি অপসারণযোগ্য মিডিয়া (যেমন, "বহিঃস্থ SD") লেখার অ্যাক্সেস, যে মিডিয়া দ্বারা ফিরে যেতে পারে যে কোনো অবস্থানে ছাড়া হবে না getExternalFilesDirs()এবং getExternalCacheDirs()। দেখুন ডেভ স্মিথ চমৎকার বিশ্লেষণ , বিশেষত যদি আপনি নিম্ন-স্তরের বিশদ চান।

দ্বিতীয়ত, অপসারণযোগ্য মিডিয়া অ্যাক্সেস অন্যথায় অ্যান্ড্রয়েড এসডিকে-র অংশ না হয় সে সম্পর্কে কেউ কেউ দ্বিধাদ্বন্দ্ব করবে , ডায়ান হ্যাকোবারের মূল্যায়ন এখানে :

... মনে রাখবেন: অ্যান্ড্রয়েড 4.4 পর্যন্ত, সরকারি অ্যান্ড্রয়েড প্ল্যাটফর্ম মুহুর্তে সমর্থিত করেননি SD কার্ড সব দুই বিশেষ ক্ষেত্রে ছাড়া: পুরানো স্কুল স্টোরেজ বিন্যাস যেখানে বাহ্যিক সঞ্চয় একটি SD কার্ড (যা আজও প্ল্যাটফর্ম দ্বারা সমর্থিত) হল এবং অ্যান্ড্রয়েড 3.0.০ এ একটি ছোট বৈশিষ্ট্য যুক্ত করা হয়েছে যেখানে এটি অতিরিক্ত এসডি কার্ডগুলি স্ক্যান করে মিডিয়া সরবরাহকারীর সাথে যুক্ত করে এবং অ্যাপ্লিকেশনগুলিকে তাদের ফাইলগুলিতে কেবল পঠনযোগ্য অ্যাক্সেস দেয় (যা আজও প্ল্যাটফর্মে সমর্থিত)।

অ্যান্ড্রয়েড ৪.৪ হ'ল প্ল্যাটফর্মের প্রথম প্রকাশ যা অ্যাপ্লিকেশনগুলিকে স্টোরেজের জন্য এসডি কার্ড ব্যবহারের অনুমতি দিয়েছে। এর আগে তাদের যে কোনও অ্যাক্সেস ছিল ব্যক্তিগত, অসমর্থিত এপিআইয়ের মাধ্যমে। প্ল্যাটফর্মে আমাদের কাছে এখন যথেষ্ট সমৃদ্ধ এপিআই রয়েছে যা অ্যাপ্লিকেশনগুলিকে আগের মতো সাধ্যের চেয়ে ভাল উপায়ে এসডি কার্ড ব্যবহার করতে দেয়: তারা কোনও অ্যাপ্লিকেশন-নির্দিষ্ট স্টোরেজ এরিয়া নিখরচায় ব্যবহার করতে পারে অ্যাপ্লিকেশনটিতে অনুমতি রয়েছে এবং এসডি কার্ডের অন্য কোনও ফাইল অ্যাক্সেস করতে পারে যতক্ষণ না তারা ফাইল পিকারের মধ্য দিয়ে যায়, আবার কোনও বিশেষ অনুমতি না নিয়েই।


4
এই সমস্যাটি আরও বেশি হয়ে উঠছে যেহেতু এইচসি এবং আইসিএস ডিভাইসগুলি "বহিরাগত স্টোরেজ ডিরেক্টরি" এবং অন্য যে কোনও কিছুই এটি অভ্যন্তরীণ শারীরিক সঞ্চয়স্থানে পছন্দ করে। এটি শীর্ষে যে, বেশিরভাগ ব্যবহারকারীর ফাইল সিস্টেমটিতে যেখানে তাদের এসডিকার্ড রয়েছে তা কীভাবে সনাক্ত করা যায় সে সম্পর্কে একেবারেই কোনও ধারণা নেই।
টনি মারো

283
সুতরাং আপনার উত্তরটি মূলত 'প্রস্তুতকারকের সাথে যোগাযোগ করুন'। দরকারী নয়।
ড্রাগনরুট

6
উত্তরের শেষ অংশটি মোটেও নির্ভুল নয় - নিচের উত্তরগুলি অনুসরণ করে (স্ক্যানিং / প্রোক / মাউন্টস, / সিস্টেমে /etc/vold.fstab, ইত্যাদি ...) এসডি কার্ডের পথটি সনাক্ত করা সত্যিই সম্ভব।
ওপেনজিএল ইএস

8
@ কমন্সওয়্যার: তবুও, এটি এখনও সঠিক নয় যে যখন সেখানে অনেকগুলি ডিভাইসে কাজ করে এমন সমাধান রয়েছে যখন কোনও প্রস্তুতকারকের সাথে যোগাযোগ করা প্রয়োজন তবে এটির কোনও গ্যারান্টি না থাকায় এসডিকে নিজেই সমস্ত ডিভাইসের সাথে সামঞ্জস্য রাখে না। এমনকি যদি এই সমাধানগুলি সমস্ত ডিভাইসে কাজ না করে তবে তারা পর্যাপ্ত ডিভাইসে কাজ করে যা বাজারের অনেক অ্যান্ড্রয়েড অ্যাপ্লিকেশনগুলি বাহ্যিক এসডি কার্ডের পথটি সনাক্ত করতে অন্যদের মধ্যে এই কৌশলগুলিতে নির্ভর করে। আমি মনে করি এই সমস্ত বিকাশকারীকে বোকা বলা কিছুটা কঠোর এবং অকাল আগে - গ্রাহক নিশ্চয়ই এর চূড়ান্ত বিচারক নন?
ওপেনজিএল ইএস

5
@ কমন্সওয়্যার এটি যথেষ্ট ন্যায্য, যেমন চলছে। আমি অবশ্যই আপনার সাথে একমত হই যে কোনও বিকাশকারী এটি সর্বদা সর্বত্র কাজ করবে তা ধরে নিতে পারে না এবং এই জাতীয় কোনও কোডই সমস্ত ডিভাইসে বা অ্যান্ড্রয়েডের সমস্ত সংস্করণে কাজ করার গ্যারান্টিযুক্ত হতে পারে না। আশা করি এটি এসডিকে স্থির হয়ে উঠবে! ইতিমধ্যে, এখনও এমন অনেকগুলি বিকল্প রয়েছে যা অনেক ডিভাইসে কাজ করে এবং শেষ ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে পারে, এবং 80% সাফল্য এবং 0% সাফল্যের মধ্যে আমি 80% গ্রহণ করব given
ওপেনজিএল ইএস

64

আমি এখানে পাওয়া কিছু উত্তরের ভিত্তিতে নীচের সমাধানটি নিয়ে এসেছি।

কোড:

public class ExternalStorage {

    public static final String SD_CARD = "sdCard";
    public static final String EXTERNAL_SD_CARD = "externalSdCard";

    /**
     * @return True if the external storage is available. False otherwise.
     */
    public static boolean isAvailable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
    }

    public static String getSdCardPath() {
        return Environment.getExternalStorageDirectory().getPath() + "/";
    }

    /**
     * @return True if the external storage is writable. False otherwise.
     */
    public static boolean isWritable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        }
        return false;

    }

    /**
     * @return A map of all storage locations available
     */
    public static Map<String, File> getAllStorageLocations() {
        Map<String, File> map = new HashMap<String, File>(10);

        List<String> mMounts = new ArrayList<String>(10);
        List<String> mVold = new ArrayList<String>(10);
        mMounts.add("/mnt/sdcard");
        mVold.add("/mnt/sdcard");

        try {
            File mountFile = new File("/proc/mounts");
            if(mountFile.exists()){
                Scanner scanner = new Scanner(mountFile);
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("/dev/block/vold/")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[1];

                        // don't add the default mount path
                        // it's already in the list.
                        if (!element.equals("/mnt/sdcard"))
                            mMounts.add(element);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            File voldFile = new File("/system/etc/vold.fstab");
            if(voldFile.exists()){
                Scanner scanner = new Scanner(voldFile);
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("dev_mount")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[2];

                        if (element.contains(":"))
                            element = element.substring(0, element.indexOf(":"));
                        if (!element.equals("/mnt/sdcard"))
                            mVold.add(element);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        for (int i = 0; i < mMounts.size(); i++) {
            String mount = mMounts.get(i);
            if (!mVold.contains(mount))
                mMounts.remove(i--);
        }
        mVold.clear();

        List<String> mountHash = new ArrayList<String>(10);

        for(String mount : mMounts){
            File root = new File(mount);
            if (root.exists() && root.isDirectory() && root.canWrite()) {
                File[] list = root.listFiles();
                String hash = "[";
                if(list!=null){
                    for(File f : list){
                        hash += f.getName().hashCode()+":"+f.length()+", ";
                    }
                }
                hash += "]";
                if(!mountHash.contains(hash)){
                    String key = SD_CARD + "_" + map.size();
                    if (map.size() == 0) {
                        key = SD_CARD;
                    } else if (map.size() == 1) {
                        key = EXTERNAL_SD_CARD;
                    }
                    mountHash.add(hash);
                    map.put(key, root);
                }
            }
        }

        mMounts.clear();

        if(map.isEmpty()){
                 map.put(SD_CARD, Environment.getExternalStorageDirectory());
        }
        return map;
    }
}

ব্যবহার:

Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File sdCard = externalLocations.get(ExternalStorage.SD_CARD);
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);

1
নেক্সাস 4, নেক্সাস এস, গ্যালাক্সি এস 2, গ্যালাক্সি এস 3, এইচটিসি আকাঙ্ক্ষা =) দিয়ে পরীক্ষিত
রিচার্ড

2
হাই, আবার, রিচার্ড - এটি বিশ্বাস করুন বা না, আমাকে জিজ্ঞাসা করতে হবে: আপনি কি কেবল ডায়ার পান না, এইভাবে কোনও ফাইলের মধ্যে আবার লেখার চেষ্টা এবং পাঠ করার চেষ্টা করেছিলেন? আমাদের পুরানো "/ sdcard0" সমস্যাটি মনে আছে? আমি এই কোডটি চেষ্টা করেছিলাম এবং এটি একটি এস 3 এ ব্যর্থ হয়েছিল যখন আমি যে ফাইলটি লিখি তা আবার পড়ার চেষ্টা করেছি। ... এটি খুব উদ্ভট ... এবং বেদনাদায়ক :))
হাওয়ার্ড পাটজ

10
এটি এমন ডিভাইসে ব্যর্থ হয় যেগুলিতে 2 টি এসডি কার্ড নেই। এটি ধরে নেওয়া হয়েছে যে 1 ম পাওয়া গেছে এটি অভ্যন্তরীণ এবং 2 তম পাওয়া গেছে বাহ্যিক ...
ক্যানার

Nexus 5 এবং Nexus 7 এ OTG কেবলের মাধ্যমে সংযুক্ত USB ডিভাইসের জন্য কাজ করেনি
খয়ার রাজা

4
/system/etc/vold.fstab অ্যান্ড্রয়েড 4.3+ এ অ্যাক্সেসযোগ্য নয়
আলী

37

আমার কাছে একটি অ্যাপ্লিকেশন ছিল ListPreferenceযা ব্যবহারকারীর যেখানে তারা কিছু সংরক্ষণ করতে চেয়েছিল সেখানে তার অবস্থান নির্বাচন করার প্রয়োজন ছিল used

এই অ্যাপ্লিকেশনটিতে, আমি স্ক্যান করেছি /proc/mountsএবং /system/etc/vold.fstabএসডিকার্ড মাউন্ট পয়েন্টগুলির জন্য। আমি প্রতিটি ফাইল থেকে দুটি পৃথক করে মাউন্ট পয়েন্ট সংরক্ষণ করেছিArrayList এসগুলিতে সংরক্ষণ করেছি।

তারপরে, আমি একটি তালিকার সাথে অন্যের এবং ত্যাগ করা আইটেমগুলির সাথে তুলনা করেছি যা উভয় তালিকায় ছিল না। এটি আমাকে প্রতিটি এসডকার্ডে রুট পাথের একটি তালিকা দিয়েছে।

সেখান থেকে, আমি পাথ পরীক্ষিত সঙ্গে File.exists(), File.isDirectory()এবংFile.canWrite() । যদি এই পরীক্ষাগুলির কোনওটি মিথ্যা হয়, তবে আমি সেই পথটি তালিকা থেকে বাদ দিয়েছি।

তালিকায় যা কিছু অবশিষ্ট ছিল, আমি একটি String[]অ্যারে রূপান্তর করেছিলাম যাতে এটি ব্যবহার করেListPreference মান বৈশিষ্ট্য ।

আপনি কোডটি এখানে দেখতে পারেন: http://sapienmobile.com/?p=204


এফওয়াইআই, এটি গ্যালাক্সি এস 3, 2 এসডি কার্ডে কাজ করে না, কেবলমাত্র ভলডকনফ
3c71

1
@ 3c71 - আপনি আমাকে গ্যালাক্সি এস 3 এর জন্য ফাইল এবং মাউন্ট ফাইলগুলি পাঠাতে পারবেন? আমি কোডটি আবরণ করার জন্য টুইট করব।
ব্যারন

গ্যালাক্সি এস, পাওয়া সমস্ত পাথ লিপিযোগ্য, অদ্ভুত ছিল না। দুটি স্টোরেজ পাওয়া গেছে, ডিফল্ট / এমএনটি / এসডিকার্ড এবং / স্টোরেজ / এসডিকার্ড0, উভয়ই পরীক্ষায় ব্যর্থ হয়েছিল
পঞ্চম

1
আমি মাউন্টস ফাইলটি উপেক্ষা করার জন্য কোডটি টুইট করেছি। মটোরোলা এবং স্যামসাং ডিভাইসে এটি ছিল সমস্যা। মাউন্টস ফাইলটি বহিরাগত_এসডি ক্ষেত্রে কভার করেনি, তবে এটি ভল্টে তালিকাভুক্ত। আমার শ্রেণীর প্রাথমিক সংস্করণটি ভল্ট এবং ফেলে দেওয়া আইটেমগুলির সাথে মাউন্টগুলি তুলনা করে যা উভয়ের পক্ষে সাধারণ ছিল না। উপরের একই লিঙ্ক থেকে আপডেট ক্লাসটি ধরুন।
ব্যারন

1
ধন্যবাদ ব্যারন, এটি "দ্য" উত্তর; অন্তত দরকারী এক।
pstoppani

23

ContextCompat.getExternFilesDirs () নামে পরিচিত সমর্থন লাইব্রেরি ফাংশনটি ব্যবহার করার চেষ্টা করতে পারেন :

      final File[] appsDir=ContextCompat.getExternalFilesDirs(getActivity(),null);
      final ArrayList<File> extRootPaths=new ArrayList<>();
      for(final File file : appsDir)
        extRootPaths.add(file.getParentFile().getParentFile().getParentFile().getParentFile());

প্রথমটি হ'ল প্রাথমিক বাহ্যিক স্টোরেজ, এবং বাকিগুলি আসল এসডি-কার্ডের পাথ বলে মনে করা হয়।

একাধিক ".getParentFile ()" এর কারণটি হ'ল মূল পথটি হওয়ায় অন্য ফোল্ডারটি উপরে যাওয়া

.../Android/data/YOUR_APP_PACKAGE_NAME/files/

সম্পাদনা করুন: এসডি-কার্ড পাথগুলি পাওয়ার জন্য এখানে আমি তৈরি করেছি আরও বিস্তৃত উপায়:

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

এটি খুব ভাল উত্তর বলে মনে হচ্ছে, তবে কীভাবে একজন সাধারণ ক্রিয়াকলাপে এটি একীভূত করবেন? সেখানে সংজ্ঞায়িত করা বেশ কিছু ভেরিয়েবল, মত App, ContextCompact,EnvironmentCompact
আন্তোনিও

@ অ্যান্টোনিও কনটেক্সট কমপ্যাক্ট, এনভায়রনমেন্ট কমপ্যাক্ট সমর্থন লাইব্রেরির মাধ্যমে উপলব্ধ। "অ্যাপ্ল্যাব্লোবাল ()" হ'ল অ্যাপ্লিকেশন প্রসঙ্গ, যা আমি বিশ্বব্যাপী সেট করেছি যেহেতু আমি কোথাও একটি প্রসঙ্গ পরামিতি যুক্ত করতে পছন্দ করি না।
অ্যান্ড্রয়েড বিকাশকারী

1
গ্রেট! আমার ডিভাইস v4.4 স্যামসাং জিটি এস অ্যাডভান্সের জন্য কাজ করে, আশা করি এটি অন্যদের জন্য কাজ করবে
ব্যবহারকারী 25

@androiddeveloper সম্পাদিত উত্তরগুলি কি সমস্ত ডিভাইস এবং এসডি কার্ড আকারের জন্য কাজ করবে?
রাহুলর2602

1
এটি আমার পক্ষে নিখুঁতভাবে কাজ করেছে - গ্রহণযোগ্য উত্তর হওয়া উচিত।
প্যারাডক্স

17

সমস্ত বাহ্যিক স্টোরগুলি পুনরুদ্ধার করার জন্য (সেগুলি এসডি কার্ড বা অভ্যন্তরীণ অপসারণযোগ্য সঞ্চয় নয় ) আপনি নিম্নলিখিত কোডটি ব্যবহার করতে পারেন:

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

বিকল্পভাবে, আপনি প্রাথমিক বাইরের স্টোরেজ ডিরেক্টরি (উদাহরণস্বরূপ "/ স্টোরেজ / sdcard0" ) এবং System.getenv ("SECONDARY_STORAGE") পুনরুদ্ধারের জন্য System.getenv ("EXTERNAL_STORAGE") ব্যবহার করতে পারেন (যেমন " / স্টোরেজ / extSdCard: / স্টোরেজ / UsbDriveA: / স্টোরেজ / UsbDriveB " )। মনে রাখবেন যে, এই ক্ষেত্রেও, আপনি ইউএসবি ড্রাইভগুলি বাদ দিতে সেকেন্ডারি ডিরেক্টরিগুলির তালিকাটি ফিল্টার করতে চাইতে পারেন।

যাইহোক, দয়া করে নোট করুন যে হার্ড-কোডেড পাথগুলি ব্যবহার করা সর্বদা একটি খারাপ পন্থা (স্পষ্টত যখন প্রতিটি নির্মাতাকে খুশি হিসাবে এটি পরিবর্তন করতে পারে)।


2
কেবল যে কোনও ডাউনভোটারকে বিবেচনা করুন যারা কোনও মন্তব্য ট্রল ছেড়েছেন না, তাই আমি এটির ক্ষতিপূরণ দিতে অগ্রণী হয়েছি। ;) তবে, আমি অনুমান করি যে আপনার পদ্ধতিটি বরং স্বেচ্ছাসেবী: আমরা কীভাবে জানতে পারি যে এই "ইউএসবি ড্রাইভগুলি" এড়িয়ে যাওয়া কিন্তু অন্য সব কিছুরই রাখা "এসডকার্ডস" এর সমান, যেমন প্রশ্নটিতে জিজ্ঞাসা করা হয়েছিল? এছাড়াও আপনার প্রস্তাবিত System.getenv("SECONDARY_STORAGE")কিছু রেফারেন্সের সাথে এটি করতে পারে, কারণ এটি অনিবন্ধিত বলে মনে হচ্ছে।
জেড

1
আমি যতদূর জানি, অ্যান্ড্রয়েড এপিআইতে সমস্ত বাহ্যিক স্টোর পুনরুদ্ধার করার জন্য কোনও মানক পদ্ধতির উল্লেখ নেই। তবে প্রস্তাবিত পদ্ধতিটি মোটেও স্বেচ্ছাচারিতা নয়। অ্যান্ড্রয়েডে, প্রতিটি ইউনিক্স / লিনাক্স সিস্টেমের মতো, সমস্ত মাউন্টিং স্টোরেজ ডিভাইসগুলি একটি সাধারণ ডিরেক্টরিতে সংরক্ষণ করা / সংযুক্ত করা হয়: "/ এমএনটি" (স্টোরেজ ডিভাইসগুলি মাউন্ট করার জন্য স্ট্যান্ডার্ড ইউনিক্স / লিনাক্স ডিরেক্টরি) বা নতুন সংস্করণগুলিতে, "/ স্টোরেজ "। এ কারণেই আপনি বেশ নিশ্চিত হতে পারেন যে আপনি এই ফোল্ডারে লিঙ্কযুক্ত সমস্ত এসডি কার্ড পাবেন।
পাওলো রোভেলি

1
সিস্টেম.জেটেনভ ("এক্সটার্নাল্প্পরেজ") পদ্ধতি সম্পর্কে, আমার কাছে পিপিআই পৃষ্ঠার পরিবর্তে কোনও রেফারেন্স নেই (যা অনেক কিছুই ব্যাখ্যা করে না): developer.android.com/references/java/lang/… আমি কোনও খুঁজে পাইনি অ্যান্ড্রয়েড সিস্টেম পরিবেশের পরিবর্তনশীলগুলির জন্য অফিসিয়াল পৃষ্ঠা। তবে এখানে আপনি তাদের একটি সংক্ষিপ্ত তালিকা পেতে পারেন: herongyang.com/Android/…
পাওলো

এসডিকার্ড সম্পর্কে নিশ্চিত না হয়ে আমি যা বোঝাতে চেয়েছি তা হ'ল /mntকেবল এসডি কার্ড এবং ইউএসবি ড্রাইভই নয়, অন্যান্য বিভিন্ন এসএস গাছ থাকতে পারে। আপনার কোডটি কোনও অভ্যন্তরীণ (সম্ভবত ভার্চুয়াল এমনকি) ফাইল সিস্টেমের মাউন্টগুলিও তালিকাভুক্ত করবে, যদি আমি এটি সঠিকভাবে বুঝতে পারি, যখন প্রশ্নটি কেবল এসডিকার্ডস চায় ।
জেড

1
আমি দেখি. হ্যাঁ তুমিই ঠিক. আমার পদ্ধতির সাহায্যে আপনি অভ্যন্তরীণ (অপসারণযোগ্য) এসডি স্মৃতিও পুনরুদ্ধার করতে পারবেন।
পাওলো রোভেলি

15

রিচার্ডের মতো আমিও উপলভ্য স্টোরেজ বিকল্পগুলির তালিকা পেতে ফাইল / প্রোগ / মাউন্ট ফাইল ব্যবহার করি

public class StorageUtils {

    private static final String TAG = "StorageUtils";

    public static class StorageInfo {

        public final String path;
        public final boolean internal;
        public final boolean readonly;
        public final int display_number;

        StorageInfo(String path, boolean internal, boolean readonly, int display_number) {
            this.path = path;
            this.internal = internal;
            this.readonly = readonly;
            this.display_number = display_number;
        }

        public String getDisplayName() {
            StringBuilder res = new StringBuilder();
            if (internal) {
                res.append("Internal SD card");
            } else if (display_number > 1) {
                res.append("SD card " + display_number);
            } else {
                res.append("SD card");
            }
            if (readonly) {
                res.append(" (Read only)");
            }
            return res.toString();
        }
    }

    public static List<StorageInfo> getStorageList() {

        List<StorageInfo> list = new ArrayList<StorageInfo>();
        String def_path = Environment.getExternalStorageDirectory().getPath();
        boolean def_path_internal = !Environment.isExternalStorageRemovable();
        String def_path_state = Environment.getExternalStorageState();
        boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
                                    || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
        boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
        BufferedReader buf_reader = null;
        try {
            HashSet<String> paths = new HashSet<String>();
            buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
            String line;
            int cur_display_number = 1;
            Log.d(TAG, "/proc/mounts");
            while ((line = buf_reader.readLine()) != null) {
                Log.d(TAG, line);
                if (line.contains("vfat") || line.contains("/mnt")) {
                    StringTokenizer tokens = new StringTokenizer(line, " ");
                    String unused = tokens.nextToken(); //device
                    String mount_point = tokens.nextToken(); //mount point
                    if (paths.contains(mount_point)) {
                        continue;
                    }
                    unused = tokens.nextToken(); //file system
                    List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
                    boolean readonly = flags.contains("ro");

                    if (mount_point.equals(def_path)) {
                        paths.add(def_path);
                        list.add(0, new StorageInfo(def_path, def_path_internal, readonly, -1));
                    } else if (line.contains("/dev/block/vold")) {
                        if (!line.contains("/mnt/secure")
                            && !line.contains("/mnt/asec")
                            && !line.contains("/mnt/obb")
                            && !line.contains("/dev/mapper")
                            && !line.contains("tmpfs")) {
                            paths.add(mount_point);
                            list.add(new StorageInfo(mount_point, false, readonly, cur_display_number++));
                        }
                    }
                }
            }

            if (!paths.contains(def_path) && def_path_available) {
                list.add(0, new StorageInfo(def_path, def_path_internal, def_path_readonly, -1));
            }

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (buf_reader != null) {
                try {
                    buf_reader.close();
                } catch (IOException ex) {}
            }
        }
        return list;
    }    
}

এর ধন্যবাদ। নিখুঁতভাবে কাজ করেছেন। এবং আপনি যেভাবে স্টোরেজআইএনফোকে নন পরিবর্তনযোগ্য করে তুলেছেন তা আমি পছন্দ করি। অন্যদিকে printStackTrace? আমরা কখন android.util.Log.e?
মার্টিন

1
নেক্সাস 5 এবং নেক্সাস 7
খয়ার রাজা

1
আমি এসডিকার্ড
Eu Vid

@ ইইউভিড হিসাবে একই ইস্যুটি ভিএম / এভিডি তে কাজ করে তবে হার্ডওয়্যারে নয়
গুপ্তচর

11

ভোল্ট ডেটা ( ) এর /proc/mountsবিপরীতে ক্রম -চেক করে (অতিরিক্ত স্ট্যান্ডার্ড লিনাক্স ফাইল) পড়ার মাধ্যমে যেখানে কোনও অতিরিক্ত এসডি কার্ড মাউন্ট করা আছে তা সন্ধান করা সম্ভব /system/etc/vold.conf। এবং দ্রষ্টব্য, যে ফিরিয়ে দেওয়া Environment.getExternalStorageDirectory()অবস্থানটি ভল্ড কনফিগারেশনে উপস্থিত নাও হতে পারে (কিছু ডিভাইসে এটি অভ্যন্তরীণ স্টোরেজ যা আনমাউন্ট করা যায় না) তবে তবুও তালিকায় অন্তর্ভুক্ত করতে হবে। তবে আমরা তাদের ব্যবহারকারীর কাছে বর্ণনা করার জন্য কোনও ভাল উপায় পাইনি ।


তবে, ফাইল সিস্টেম mountপড়ার চেয়ে বেশি ব্যবহারযোগ্য /proc। সমস্যাটি হ'ল এসডি কার্ড FAT হিসাবে ফর্ম্যাট করা আবশ্যক। এছাড়াও, কার্ড মাউন্ট পয়েন্ট ROM থেকে ROM এ পরিবর্তিত হতে পারে। এছাড়াও, আরও বেশ কয়েকটি ভিএফএটি পার্টিশন থাকতে পারে ...
বরিস্টিস্ট

1
@ বোরিস্ট্রাস্ট: এইচএম, আসলে অ্যান্ড্রয়েড ভাঁজ ব্যবহার করে , তাই এটির কনফিগারেশনটিও দেখানো উপযুক্ত।
জানু হুডেক

উপরের আমার পোস্টটি থেকে আমি যে ফাইল ফাইলটি ভাগ করেছি তাতে ব্যবহারকারীর কাছে আবিষ্কার করা মূল পাথ বর্ণনা করার একটি পদ্ধতি অন্তর্ভুক্ত রয়েছে। এ setProperties () পদ্ধতি।
ব্যারন

1
@ বরিস্ট্রিট, আসলে না, mountএক্সিকিউটেবল চালু করার চেয়ে অ্যান্ড্রয়েড ডিভাইসে রিডিং / প্রোক / মাউন্টগুলি বেশি বহনযোগ্য , বিশেষত এক্সিকিউটেবলের প্রবর্তনকে নিরুৎসাহিত করার কারণে।
ক্রিস স্ট্রাটন

7

আমি এই মুহুর্তে এই বিষয়ের ভিতরে সমস্ত সমাধান চেষ্টা করি। তবে এগুলির সমস্তই একটি বাহ্যিক (অপসারণযোগ্য) এবং একটি অভ্যন্তরীণ (অপসারণযোগ্য) কার্ড সহ ডিভাইসে সঠিকভাবে কাজ করে নি। বাহ্যিক কার্ডের পথ 'মাউন্ট' কমান্ড থেকে 'প্রোক / মাউন্টস' ফাইল ইত্যাদি থেকে পাওয়া সম্ভব নয়

এবং আমি আমার নিজস্ব সমাধান তৈরি করেছি (পাওলো লুয়ান্সে):

String sSDpath = null;
File   fileCur = null;
for( String sPathCur : Arrays.asList( "ext_card", "external_sd", "ext_sd", "external", "extSdCard",  "externalSdCard")) // external sdcard
{
   fileCur = new File( "/mnt/", sPathCur);
   if( fileCur.isDirectory() && fileCur.canWrite())
   {
     sSDpath = fileCur.getAbsolutePath();
     break;
   }
}
fileCur = null;
if( sSDpath == null)  sSDpath = Environment.getExternalStorageDirectory().getAbsolutePath();

6

আপনি যদি উত্স কোডটি android.os.Environmentদেখেন তবে দেখবেন অ্যান্ড্রয়েড পাথগুলির জন্য পরিবেশের ভেরিয়েবলের উপর প্রচুর নির্ভর করে। অপসারণযোগ্য এসডি কার্ডের পথ খুঁজে পেতে আপনি "SECONDARY_STORAGE" পরিবেশ পরিবর্তনশীল ব্যবহার করতে পারেন।

/**
 * Get a file using an environmental variable.
 *
 * @param variableName
 *         The Environment variable name.
 * @param paths
 *         Any paths to the file if the Environment variable was not found.
 * @return the File or {@code null} if the File could not be located.
 */
private static File getDirectory(String variableName, String... paths) {
    String path = System.getenv(variableName);
    if (!TextUtils.isEmpty(path)) {
        if (path.contains(":")) {
            for (String _path : path.split(":")) {
                File file = new File(_path);
                if (file.exists()) {
                    return file;
                }
            }
        } else {
            File file = new File(path);
            if (file.exists()) {
                return file;
            }
        }
    }
    if (paths != null && paths.length > 0) {
        for (String _path : paths) {
            File file = new File(_path);
            if (file.exists()) {
                return file;
            }
        }
    }
    return null;
}

ব্যবহারের উদাহরণ:

public static final File REMOVABLE_STORAGE = getDirectory("SECONDARY_STORAGE");

5

কেবল এটি ব্যবহার করুন:

String primary_sd = System.getenv("EXTERNAL_STORAGE");
if(primary_sd != null)
    Log.i("EXTERNAL_STORAGE", primary_sd);
String secondary_sd = System.getenv("SECONDARY_STORAGE");
if(secondary_sd != null)
    Log.i("SECONDARY_STORAGE", secondary_sd)

কিছু ডিভাইসে SECONDARY_STORAGEএকটি কোলন (":") দিয়ে পৃথক করা বেশ কয়েকটি পাথ রয়েছে। এই কারণেই আমি স্ট্রিংকে বিভক্ত করলাম (উপরে আমার উত্তর দেখুন)।
জারেড রুম্মার

এই দু'জনেই আমার কাছে ফিরছে return
টিম কুপার

5

বাহ্যিক এসডি কার্ডের অবস্থানটি খুঁজে পাওয়ার কোনও সর্বজনীন উপায় আছে কি?

দ্বারা সার্বজনীন উপায় , আপনি সরকারী ভাবে মানে যদি; হ্যাঁ একটি আছে।

Android সংস্করণ 4.4 Kitkat মধ্যে এপিআই 19 অর্থাত স্তর, তারা যুক্ত করেছেন File[] getExternalFilesDirs (String type)মধ্যে Contextক্লাস যে মাইক্রো এসডি কার্ড ডেটা সংরক্ষণ / ফাইল অ্যাপ্লিকেশন পারেন।

অ্যান্ড্রয়েড ৪.৪ হ'ল প্ল্যাটফর্মের প্রথম প্রকাশ যা অ্যাপ্লিকেশনগুলিকে স্টোরেজের জন্য এসডি কার্ড ব্যবহারের অনুমতি দিয়েছে। এপিআই স্তর 19 এর আগে এসডি কার্ডগুলিতে যে কোনও অ্যাক্সেস ব্যক্তিগত, অসমর্থিত এপিআইয়ের মাধ্যমে ছিল।

getExternFilesDirs (স্ট্রিং টাইপ) সমস্ত ভাগ করা / বাহ্যিক স্টোরেজ ডিভাইসে অ্যাপ্লিকেশন-নির্দিষ্ট ডিরেক্টরিগুলিতে পরম পাথ দেয় returns এর অর্থ এটি অভ্যন্তরীণ এবং বহিরাগত উভয় স্মৃতিতে ফিরে আসবে। সাধারণত, দ্বিতীয় ফেরত পথ হ'ল মাইক্রোএসডি কার্ডের সঞ্চয় স্থান (যদি থাকে)।

তবে মনে রাখবেন,

ভাগ করা সঞ্চয়স্থান সর্বদা উপলব্ধ না থাকায় অপসারণযোগ্য মিডিয়া ব্যবহারকারীর দ্বারা নির্গত করা যেতে পারে by মিডিয়া অবস্থা ব্যবহার করে চেক করা যায় getExternalStorageState(File)

এই ফাইলগুলির সাথে কোনও সুরক্ষা প্রয়োগ করা হয়নি। উদাহরণস্বরূপ, যে কোনও অ্যাপ্লিকেশনধারী WRITE_EXTERNAL_STORAGEএই ফাইলগুলিতে লিখতে পারে।

গুগল / অফিসিয়াল অ্যান্ড্রয়েড ডক্স অনুসারে অভ্যন্তরীণ এবং বহিরাগত স্টোরেজ পরিভাষা আমাদের ধারণা থেকে কিছুটা আলাদা


"গুগল / অফিসিয়াল অ্যান্ড্রয়েড ডক্স অনুসারে অভ্যন্তরীণ এবং বাহ্যিক স্টোরেজ পরিভাষা আমাদের ধারণা থেকে কিছুটা পৃথক" " হ্যাঁ, প্রকৃতপক্ষে প্রশ্নের শিরোনাম পরিষ্কার করে যে ওপি একটি অপসারণযোগ্য এসডি কার্ড সম্পর্কে জিজ্ঞাসা করছে । getExternalFilesDirs()প্রায়শই অপসারণযোগ্য নয় এমন এসডি কার্ডগুলি ফেরত দেয়, তাই না, অপসারণযোগ্য এসডি কার্ডের অবস্থান সন্ধানের এটি সর্বজনীন উপায় নয়।
লার্শ

"getExternFilesDirs (স্ট্রিং টাইপ) সমস্ত ভাগ করা / বাহ্যিক স্টোরেজ ডিভাইসে অ্যাপ্লিকেশন-নির্দিষ্ট ডিরেক্টরিগুলিতে নিখুঁত পাথ ফেরায় It এই জোড়া বাক্যটি খুব বিভ্রান্তিকর, কারণ তাদের উভয়ই সত্য হওয়ার জন্য, "বাহ্যিক" এর অর্থ দুটি পৃথক এবং বিবাদমান জিনিস things
LarsH

4

বাহ্যিক কার্ডটি খুঁজে পেতে আমি যেভাবে ব্যবহার করি তা এখানে। মাউন্ট সেন্টিমিডি রিটার্ন ব্যবহার করুন তারপরে ভিফ্যাট অংশটি পার্স করুন।

String s = "";
try {
Process process = new ProcessBuilder().command("mount")
        .redirectErrorStream(true).start();

process.waitFor();

InputStream is = process.getInputStream();
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
    s = s + new String(buffer);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}

//用行分隔mount列表
String[] lines = s.split("\n");
for(int i=0; i<lines.length; i++) {
//如果行内有挂载路径且为vfat类型,说明可能是内置或者外置sd的挂载点
if(-1 != lines[i].indexOf(path[0]) && -1 != lines[i].indexOf("vfat")) {
    //再用空格分隔
    String[] blocks = lines[i].split("\\s");
    for(int j=0; j<blocks.length; j++) {
        //判断是否是挂载为vfat类型
        if(-1 != blocks[j].indexOf(path[0])) {
            //Test if it is the external sd card.
        }
    }
}
}

4

এই সমাধানটি সত্যটি পরিচালনা করে System.getenv("SECONDARY_STORAGE") মার্শমেলোর সাথে কোনও উপকারে আসেনি।

পরীক্ষিত এবং কাজ করছে:

  • স্যামসং গ্যালাক্সি ট্যাব 2 (অ্যান্ড্রয়েড 4.1.1 - স্টক)
  • স্যামসং গ্যালাক্সি নোট 8.0 (অ্যান্ড্রয়েড 4.2.2 - স্টক)
  • স্যামসং গ্যালাক্সি এস 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;
    }

2

আমার উপরের উত্তরটি যেহেতু, স্ক্যানিং ভলডটি বিভিন্ন নির্মাতারা জুড়ে আর কার্যকর হয় না।

আমি আরও নির্ভরযোগ্য এবং সরাসরি এগিয়ে যাওয়ার পদ্ধতি তৈরি করেছি।

File mnt = new File("/storage");
if (!mnt.exists())
    mnt = new File("/mnt");

File[] roots = mnt.listFiles(new FileFilter() {

    @Override
    public boolean accept(File pathname) {
        return pathname.isDirectory() && pathname.exists()
                && pathname.canWrite() && !pathname.isHidden()
                && !isSymlink(pathname);
    }
});

শিকড়গুলিতে সিস্টেমের সমস্ত লিখনযোগ্য রুট ডিরেক্টরি থাকবে, কোনও ইউএসবি সংযুক্ত ইউএসবি ডিভাইস সহ।

দ্রষ্টব্য: ক্যান রাইট পদ্ধতিটির জন্য android.permission.WRITE_EXTERNAL_STORAGE অনুমতি প্রয়োজন।


পদ্ধতিটি হ'ল সিমলিংক (ফাইল) নতুন ফাইলফিলার () {for টাইপের জন্য অপরিজ্ঞাত
ওমিড ওমিদি

কোনও ধারণা যদি ক্যান রাইটের কারণে অ্যান্ড্রয়েড ৪.৪-এ বাহ্যিক এসডি কার্ডগুলি খুঁজে পেতে ব্যর্থ হয়?
অ্যান্টনি

এটি অবশ্যই আপনার অন্যান্য পদ্ধতির তুলনায় আরও সোজা, তবে এটি কি নির্ভরযোগ্য? যেমন আমি পড়েছি যে কয়েকটি স্যামসাং ডিভাইসে, /external_sdএটি বাহ্যিক মাইক্রোএসডি কার্ড; কিছু এলজির উপর, এটি /_ExternalSD; কিছু ডিভাইসে এটি /sdcard। সম্ভবত পরেরটি একটি /storage/sdcard0অনুরূপ বা অনুরূপ, তবে এই অন্যান্যরা কি সত্যই নির্ভরযোগ্যভাবে আচ্ছাদিত হয়ে যাবে /storage/*এবং /mount/*?
লার্শ

এছাড়াও, এটি ব্যবহার করা pathname.canWrite()এবং WRITE_EXTERNAL_STORAGE অনুমতি প্রয়োজন? কেন শুধু ফোন pathname.canRead()করবেন না ?
লার্শ

1

এটি এত দেরি হয়ে গেছে তবে অবশেষে আমি এমন কিছু পেয়েছি যা আমি বেশিরভাগ ডিভাইস (প্রস্তুতকারক এবং অ্যান্ড্রয়েড সংস্করণ দ্বারা) এর অ্যান্ড্রয়েড ২.২++ এ কাজ করে পরীক্ষা করেছি। যদি আপনি দেখতে পান যে এটি কাজ করছে না, আপনার ডিভাইসের নামের সাথে মন্তব্য করুন। আমি এটা ঠিক করব. যদি কেউ আগ্রহী আমি এটি কীভাবে কাজ করে তা ব্যাখ্যা করব।

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;

import android.util.Log;


/**
 * @author ajeet
 *05-Dec-2014  2014
 *
 */
public class StorageUtil {

    public boolean isRemovebleSDCardMounted() {
        File file = new File("/sys/class/block/");
        File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$"));
        boolean flag = false;
        for (File mmcfile : files) {
            File scrfile = new File(mmcfile, "device/scr");
            if (scrfile.exists()) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    public String getRemovebleSDCardPath() throws IOException {
        String sdpath = null;
        File file = new File("/sys/class/block/");
        File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$"));
        String sdcardDevfile = null;
        for (File mmcfile : files) {
            Log.d("SDCARD", mmcfile.getAbsolutePath());
            File scrfile = new File(mmcfile, "device/scr");
            if (scrfile.exists()) {
                sdcardDevfile = mmcfile.getName();
                Log.d("SDCARD", mmcfile.getName());
                break;
            }
        }
        if (sdcardDevfile == null) {
            return null;
        }
        FileInputStream is;
        BufferedReader reader;

        files = file.listFiles(new MmcblkFilter(sdcardDevfile + "p\\d+"));
        String deviceName = null;
        if (files.length > 0) {
            Log.d("SDCARD", files[0].getAbsolutePath());
            File devfile = new File(files[0], "dev");
            if (devfile.exists()) {
                FileInputStream fis = new FileInputStream(devfile);
                reader = new BufferedReader(new InputStreamReader(fis));
                String line = reader.readLine();
                deviceName = line;
            }
            Log.d("SDCARD", "" + deviceName);
            if (deviceName == null) {
                return null;
            }
            Log.d("SDCARD", deviceName);

            final File mountFile = new File("/proc/self/mountinfo");

            if (mountFile.exists()) {
                is = new FileInputStream(mountFile);
                reader = new BufferedReader(new InputStreamReader(is));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    // Log.d("SDCARD", line);
                    // line = reader.readLine();
                    // Log.d("SDCARD", line);
                    String[] mPonts = line.split("\\s+");
                    if (mPonts.length > 6) {
                        if (mPonts[2].trim().equalsIgnoreCase(deviceName)) {
                            if (mPonts[4].contains(".android_secure")
                                    || mPonts[4].contains("asec")) {
                                continue;
                            }
                            sdpath = mPonts[4];
                            Log.d("SDCARD", mPonts[4]);

                        }
                    }

                }
            }

        }

        return sdpath;
    }

    static class MmcblkFilter implements FilenameFilter {
        private String pattern;

        public MmcblkFilter(String pattern) {
            this.pattern = pattern;

        }

        @Override
        public boolean accept(File dir, String filename) {
            if (filename.matches(pattern)) {
                return true;
            }
            return false;
        }

    }

}

আরে ডাউনভোটার দয়া করে প্রথমে চেষ্টা করুন .এটি যদি কাজ না করে থাকে তবে আপনার ডিভাইসে মন্তব্য করুন। আমরা এটিকে অ্যানড্রয়েড ২.২++ সহ হাজার হাজারেরও বেশি ডিভাইস ব্যবহার করছি
আজিত 47

আপনার ক্লাসটি আমাকে স্যামসাং গ্যালাক্সি এস 4, জিটি-আই 9500, অ্যান্ড্রয়েড 5.0.1 (ডিভাইসটি মূলী নয়) এ / mnt / media_rw / extSdCard দেয়। তবে ES ফাইল ম্যানেজারের সাথে / mnt / media_rw ফোল্ডারে কিছুই দৃশ্যমান নেই ...
isabmitted

@ (অনুপস্থিত ব্যবহার) যদি (বিল্ড.ওআরএসইএন.এসডি কেএনটিটি> = বিল্ড.VERSION_CODES.KITKAT) {ফাইল [] ফাইল = প্রসঙ্গ.জিটএক্সটার্নাল ফাইলস ডিয়ারস (নাল); ফাইলটি ফেরান le দৈর্ঘ্য> 1? ফাইল [1]: নাল; }
আজিত 47

আপনি স্ট্যাকওভারফ্লো . com/a/27197248/753575 সম্পর্কে কী ভাবেন ? এই দৃষ্টিভঙ্গি কি বিল্ডের ক্ষেত্রে আরও বিস্তৃত =
isabmitted


1

নীচে কোড লিখে আপনি স্থান পাবেন:

/ স্টোরেজ / 663D-554E / অ্যান্ড্রয়েড / ডেটা / app_package_name / ফাইল /

যা আপনার অ্যাপ্লিকেশন ডেটা / অ্যান্ড্রয়েড / এসডি_কার্ডের মধ্যে ডেটা অবস্থানের উপর সঞ্চয় করে।

File[] list = ContextCompat.getExternalFilesDirs(MainActivity.this, null);

list[1]+"/fol" 

অভ্যন্তরের জন্য অবস্থান পাস 0 পাওয়ার জন্য এবং অ্যারে ফাইলের জন্য এসডকার্ডের জন্য 1 পাস করুন।

আমি এই কোডটি মোটো জি 4 প্লাস এবং স্যামসাং ডিভাইসে পরীক্ষা করেছি (সমস্ত কাজ ঠিকঠাক করে)।

আশা করি এটি সহায়ক হতে পারে।


কখনও কখনও এসডি কার্ড পথ না সূচক 1, আমি ক্ষেত্রে যেখানে এটা সূচক 0 ভাল ছিল অন্য কিছু অনুসরণ করতে দেখা যায়
রাঘব Satyadev

1

অপসারণযোগ্য এসডি কার্ড খুঁজতে আমি যে পদ্ধতিটি ব্যবহার করি তা এখানে । এটি জটিল, এবং সম্ভবত কিছু পরিস্থিতিতে ওভারকিল, তবে এটি গত কয়েক বছর ধরে আমি পরীক্ষিত বিভিন্ন অ্যান্ড্রয়েড সংস্করণ এবং ডিভাইস প্রস্তুতকারকের উপর কাজ করে। আমি এমন কোনও ডিভাইস সম্পর্কে জানি না যে এপিআই স্তর 15 এর পরে এটিতে এসডি কার্ডটি খুঁজে পাওয়া যায় না, যদি কোনও মাউন্ট থাকে তবে। এটি বেশিরভাগ ক্ষেত্রেই মিথ্যা ইতিবাচক প্রত্যাবর্তন করবে না, বিশেষত যদি আপনি এটির জন্য কোনও পরিচিত ফাইলের নাম দেন।

আপনি যদি এমন কোনও ক্ষেত্রে কাজ করেন না তবে দয়া করে আমাকে জানান।

import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.regex.Pattern;

public class SDCard {
    private static final String TAG = "SDCard";

    /** In some scenarios we can expect to find a specified file or folder on SD cards designed
     * to work with this app. If so, set KNOWNFILE to that filename. It will make our job easier.
     * Set it to null otherwise. */
    private static final String KNOWNFILE = null;

    /** Common paths for microSD card. **/
    private static String[] commonPaths = {
            // Some of these taken from
            // /programming/13976982/removable-storage-external-sdcard-path-by-manufacturers
            // These are roughly in order such that the earlier ones, if they exist, are more sure
            // to be removable storage than the later ones.
            "/mnt/Removable/MicroSD",
            "/storage/removable/sdcard1", // !< Sony Xperia Z1
            "/Removable/MicroSD", // Asus ZenPad C
            "/removable/microsd",
            "/external_sd", // Samsung
            "/_ExternalSD", // some LGs
            "/storage/extSdCard", // later Samsung
            "/storage/extsdcard", // Main filesystem is case-sensitive; FAT isn't.
            "/mnt/extsd", // some Chinese tablets, e.g. Zeki
            "/storage/sdcard1", // If this exists it's more likely than sdcard0 to be removable.
            "/mnt/extSdCard",
            "/mnt/sdcard/external_sd",
            "/mnt/external_sd",
            "/storage/external_SD",
            "/storage/ext_sd", // HTC One Max
            "/mnt/sdcard/_ExternalSD",
            "/mnt/sdcard-ext",

            "/sdcard2", // HTC One M8s
            "/sdcard1", // Sony Xperia Z
            "/mnt/media_rw/sdcard1",   // 4.4.2 on CyanogenMod S3
            "/mnt/sdcard", // This can be built-in storage (non-removable).
            "/sdcard",
            "/storage/sdcard0",
            "/emmc",
            "/mnt/emmc",
            "/sdcard/sd",
            "/mnt/sdcard/bpemmctest",
            "/mnt/external1",
            "/data/sdext4",
            "/data/sdext3",
            "/data/sdext2",
            "/data/sdext",
            "/storage/microsd" //ASUS ZenFone 2

            // If we ever decide to support USB OTG storage, the following paths could be helpful:
            // An LG Nexus 5 apparently uses usb://1002/UsbStorage/ as a URI to access an SD
            // card over OTG cable. Other models, like Galaxy S5, use /storage/UsbDriveA
            //        "/mnt/usb_storage",
            //        "/mnt/UsbDriveA",
            //        "/mnt/UsbDriveB",
    };

    /** Find path to removable SD card. */
    public static File findSdCardPath(Context context) {
        String[] mountFields;
        BufferedReader bufferedReader = null;
        String lineRead = null;

        /** Possible SD card paths */
        LinkedHashSet<File> candidatePaths = new LinkedHashSet<>();

        /** Build a list of candidate paths, roughly in order of preference. That way if
         * we can't definitively detect removable storage, we at least can pick a more likely
         * candidate. */

        // Could do: use getExternalStorageState(File path), with and without an argument, when
        // available. With an argument is available since API level 21.
        // This may not be necessary, since we also check whether a directory exists and has contents,
        // which would fail if the external storage state is neither MOUNTED nor MOUNTED_READ_ONLY.

        // I moved hard-coded paths toward the end, but we need to make sure we put the ones in
        // backwards order that are returned by the OS. And make sure the iterators respect
        // the order!
        // This is because when multiple "external" storage paths are returned, it's always (in
        // experience, but not guaranteed by documentation) with internal/emulated storage
        // first, removable storage second.

        // Add value of environment variables as candidates, if set:
        // EXTERNAL_STORAGE, SECONDARY_STORAGE, EXTERNAL_SDCARD_STORAGE
        // But note they are *not* necessarily *removable* storage! Especially EXTERNAL_STORAGE.
        // And they are not documented (API) features. Typically useful only for old versions of Android.

        String val = System.getenv("SECONDARY_STORAGE");
        if (!TextUtils.isEmpty(val)) addPath(val, null, candidatePaths);
        val = System.getenv("EXTERNAL_SDCARD_STORAGE");
        if (!TextUtils.isEmpty(val)) addPath(val, null, candidatePaths);

        // Get listing of mounted devices with their properties.
        ArrayList<File> mountedPaths = new ArrayList<>();
        try {
            // Note: Despite restricting some access to /proc (http://stackoverflow.com/a/38728738/423105),
            // Android 7.0 does *not* block access to /proc/mounts, according to our test on George's Alcatel A30 GSM.
            bufferedReader = new BufferedReader(new FileReader("/proc/mounts"));

            // Iterate over each line of the mounts listing.
            while ((lineRead = bufferedReader.readLine()) != null) {
                Log.d(TAG, "\nMounts line: " + lineRead);
                mountFields = lineRead.split(" ");

                // columns: device, mountpoint, fs type, options... Example:
                // /dev/block/vold/179:97 /storage/sdcard1 vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0002,dmask=0002,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
                String device = mountFields[0], path = mountFields[1], fsType = mountFields[2];

                // The device, path, and fs type must conform to expected patterns.
                if (!(devicePattern.matcher(device).matches() &&
                        pathPattern.matcher(path).matches() &&
                        fsTypePattern.matcher(fsType).matches()) ||
                        // mtdblock is internal, I'm told.
                        device.contains("mtdblock") ||
                        // Check for disqualifying patterns in the path.
                        pathAntiPattern.matcher(path).matches()) {
                    // If this mounts line fails our tests, skip it.
                    continue;
                }

                // TODO maybe: check options to make sure it's mounted RW?
                // The answer at http://stackoverflow.com/a/13648873/423105 does.
                // But it hasn't seemed to be necessary so far in my testing.

                // This line met the criteria so far, so add it to candidate list.
                addPath(path, null, mountedPaths);
            }
        } catch (IOException ignored) {
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ignored) {
                }
            }
        }

        // Append the paths from mount table to candidate list, in reverse order.
        if (!mountedPaths.isEmpty()) {
            // See https://stackoverflow.com/a/5374346/423105 on why the following is necessary.
            // Basically, .toArray() needs its parameter to know what type of array to return.
            File[] mountedPathsArray = mountedPaths.toArray(new File[mountedPaths.size()]);
            addAncestors(candidatePaths, mountedPathsArray);
        }

        // Add hard-coded known common paths to candidate list:
        addStrings(candidatePaths, commonPaths);

        // If the above doesn't work we could try the following other options, but in my experience they
        // haven't added anything helpful yet.

        // getExternalFilesDir() and getExternalStorageDirectory() typically something app-specific like
        //   /storage/sdcard1/Android/data/com.mybackuparchives.android/files
        // so we want the great-great-grandparent folder.

        // This may be non-removable.
        Log.d(TAG, "Environment.getExternalStorageDirectory():");
        addPath(null, ancestor(Environment.getExternalStorageDirectory()), candidatePaths);

        // Context.getExternalFilesDirs() is only available from API level 19. You can use
        // ContextCompat.getExternalFilesDirs() on earlier APIs, but it only returns one dir anyway.
        Log.d(TAG, "context.getExternalFilesDir(null):");
        addPath(null, ancestor(context.getExternalFilesDir(null)), candidatePaths);

        // "Returns absolute paths to application-specific directories on all external storage
        // devices where the application can place persistent files it owns."
        // We might be able to use these to deduce a higher-level folder that isn't app-specific.
        // Also, we apparently have to call getExternalFilesDir[s](), at least in KITKAT+, in order to ensure that the
        // "external files" directory exists and is available.
        Log.d(TAG, "ContextCompat.getExternalFilesDirs(context, null):");
        addAncestors(candidatePaths, ContextCompat.getExternalFilesDirs(context, null));
        // Very similar results:
        Log.d(TAG, "ContextCompat.getExternalCacheDirs(context):");
        addAncestors(candidatePaths, ContextCompat.getExternalCacheDirs(context));

        // TODO maybe: use getExternalStorageState(File path), with and without an argument, when
        // available. With an argument is available since API level 21.
        // This may not be necessary, since we also check whether a directory exists,
        // which would fail if the external storage state is neither MOUNTED nor MOUNTED_READ_ONLY.

        // A "public" external storage directory. But in my experience it doesn't add anything helpful.
        // Note that you can't pass null, or you'll get an NPE.
        final File publicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
        // Take the parent, because we tend to get a path like /pathTo/sdCard/Music.
        addPath(null, publicDirectory.getParentFile(), candidatePaths);
        // EXTERNAL_STORAGE: may not be removable.
        val = System.getenv("EXTERNAL_STORAGE");
        if (!TextUtils.isEmpty(val)) addPath(val, null, candidatePaths);

        if (candidatePaths.isEmpty()) {
            Log.w(TAG, "No removable microSD card found.");
            return null;
        } else {
            Log.i(TAG, "\nFound potential removable storage locations: " + candidatePaths);
        }

        // Accept or eliminate candidate paths if we can determine whether they're removable storage.
        // In Lollipop and later, we can check isExternalStorageRemovable() status on each candidate.
        if (Build.VERSION.SDK_INT >= 21) {
            Iterator<File> itf = candidatePaths.iterator();
            while (itf.hasNext()) {
                File dir = itf.next();
                // handle illegalArgumentException if the path is not a valid storage device.
                try {
                    if (Environment.isExternalStorageRemovable(dir)
                        // && containsKnownFile(dir)
                            ) {
                        Log.i(TAG, dir.getPath() + " is removable external storage");
                        return dir;
                    } else if (Environment.isExternalStorageEmulated(dir)) {
                        Log.d(TAG, "Removing emulated external storage dir " + dir);
                        itf.remove();
                    }
                } catch (IllegalArgumentException e) {
                    Log.d(TAG, "isRemovable(" + dir.getPath() + "): not a valid storage device.", e);
                }
            }
        }

        // Continue trying to accept or eliminate candidate paths based on whether they're removable storage.
        // On pre-Lollipop, we only have singular externalStorage. Check whether it's removable.
        if (Build.VERSION.SDK_INT >= 9) {
            File externalStorage = Environment.getExternalStorageDirectory();
            Log.d(TAG, String.format(Locale.ROOT, "findSDCardPath: getExternalStorageDirectory = %s", externalStorage.getPath()));
            if (Environment.isExternalStorageRemovable()) {
                // Make sure this is a candidate.
                // TODO: Does this contains() work? Should we be canonicalizing paths before comparing?
                if (candidatePaths.contains(externalStorage)
                    // && containsKnownFile(externalStorage)
                        ) {
                    Log.d(TAG, "Using externalStorage dir " + externalStorage);
                    return externalStorage;
                }
            } else if (Build.VERSION.SDK_INT >= 11 && Environment.isExternalStorageEmulated()) {
                Log.d(TAG, "Removing emulated external storage dir " + externalStorage);
                candidatePaths.remove(externalStorage);
            }
        }

        // If any directory contains our special test file, consider that the microSD card.
        if (KNOWNFILE != null) {
            for (File dir : candidatePaths) {
                Log.d(TAG, String.format(Locale.ROOT, "findSdCardPath: Looking for known file in candidate path, %s", dir));
                if (containsKnownFile(dir)) return dir;
            }
        }

        // If we don't find the known file, still try taking the first candidate.
        if (!candidatePaths.isEmpty()) {
            Log.d(TAG, "No definitive path to SD card; taking the first realistic candidate.");
            return candidatePaths.iterator().next();
        }

        // If no reasonable path was found, give up.
        return null;
    }

    /** Add each path to the collection. */
    private static void addStrings(LinkedHashSet<File> candidatePaths, String[] newPaths) {
        for (String path : newPaths) {
            addPath(path, null, candidatePaths);
        }
    }

    /** Add ancestor of each File to the collection. */
    private static void addAncestors(LinkedHashSet<File> candidatePaths, File[] files) {
        for (int i = files.length - 1; i >= 0; i--) {
            addPath(null, ancestor(files[i]), candidatePaths);
        }
    }

    /**
     * Add a new candidate directory path to our list, if it's not obviously wrong.
     * Supply path as either String or File object.
     * @param strNew path of directory to add (or null)
     * @param fileNew directory to add (or null)
     */
    private static void addPath(String strNew, File fileNew, Collection<File> paths) {
        // If one of the arguments is null, fill it in from the other.
        if (strNew == null) {
            if (fileNew == null) return;
            strNew = fileNew.getPath();
        } else if (fileNew == null) {
            fileNew = new File(strNew);
        }

        if (!paths.contains(fileNew) &&
                // Check for paths known not to be removable SD card.
                // The antipattern check can be redundant, depending on where this is called from.
                !pathAntiPattern.matcher(strNew).matches()) {

            // Eliminate candidate if not a directory or not fully accessible.
            if (fileNew.exists() && fileNew.isDirectory() && fileNew.canExecute()) {
                Log.d(TAG, "  Adding candidate path " + strNew);
                paths.add(fileNew);
            } else {
                Log.d(TAG, String.format(Locale.ROOT, "  Invalid path %s: exists: %b isDir: %b canExec: %b canRead: %b",
                        strNew, fileNew.exists(), fileNew.isDirectory(), fileNew.canExecute(), fileNew.canRead()));
            }
        }
    }

    private static final String ANDROID_DIR = File.separator + "Android";

    private static File ancestor(File dir) {
        // getExternalFilesDir() and getExternalStorageDirectory() typically something app-specific like
        //   /storage/sdcard1/Android/data/com.mybackuparchives.android/files
        // so we want the great-great-grandparent folder.
        if (dir == null) {
            return null;
        } else {
            String path = dir.getAbsolutePath();
            int i = path.indexOf(ANDROID_DIR);
            if (i == -1) {
                return dir;
            } else {
                return new File(path.substring(0, i));
            }
        }
    }

    /** Returns true iff dir contains the special test file.
     * Assumes that dir exists and is a directory. (Is this a necessary assumption?) */
    private static boolean containsKnownFile(File dir) {
        if (KNOWNFILE == null) return false;

        File knownFile = new File(dir, KNOWNFILE);
        return knownFile.exists();
    }

    private static Pattern
            /** Pattern that SD card device should match */
            devicePattern = Pattern.compile("/dev/(block/.*vold.*|fuse)|/mnt/.*"),
    /** Pattern that SD card mount path should match */
    pathPattern = Pattern.compile("/(mnt|storage|external_sd|extsd|_ExternalSD|Removable|.*MicroSD).*",
            Pattern.CASE_INSENSITIVE),
    /** Pattern that the mount path should not match.
     * 'emulated' indicates an internal storage location, so skip it.
     * 'asec' is an encrypted package file, decrypted and mounted as a directory. */
    pathAntiPattern = Pattern.compile(".*(/secure|/asec|/emulated).*"),
    /** These are expected fs types, including vfat. tmpfs is not OK.
     * fuse can be removable SD card (as on Moto E or Asus ZenPad), or can be internal (Huawei G610). */
    fsTypePattern = Pattern.compile(".*(fat|msdos|ntfs|ext[34]|fuse|sdcard|esdfs).*");
}

পুনশ্চ

  • <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />ম্যানিফেস্টে ভুলে যাবেন না । এবং এপিআই স্তরের 23 এবং উচ্চতর সময়ে, checkSelfPermission/requestPermissions
  • আপনি এসডি কার্ডে খুঁজে পাওয়ার আশা করছেন এমন কোনও ফাইল বা ফোল্ডার যদি থাকে তবে KNOWNFILE = "মায়াপফল" সেট করুন। এটি সনাক্তকরণকে আরও সঠিক করে তোলে।
  • অবশ্যই আপনি এর মান ক্যাশে করতে চান findSdCardPath(), প্রতিটি বার যখন এটি প্রয়োজন তখন এটির পুনর্নির্মাণের চেয়ে ।
  • উপরের কোডটিতে লগিংয়ের একটি গুচ্ছ রয়েছে Log.d()। এটি সঠিক ক্ষেত্রে খুঁজে পাওয়া যায় না এমন কোনও ক্ষেত্রে নির্ণয় করতে সহায়তা করে। আপনি লগিং করতে না চাইলে এটি মন্তব্য করুন।

ডাউনভোটার্স, আপনি কি এই উত্তরটির উন্নতি করার জন্য কোনও উপায়ের পরামর্শ দিতে পারেন?
LarsH

1

আমি খুঁজে পাওয়া একমাত্র কার্যকরী সমাধান হ'ল এটিই প্রতিফলন ব্যবহার করে

 /**
 * Get external sd card path using reflection
 * @param mContext
 * @param is_removable is external storage removable
 * @return
 */
private static String getExternalStoragePath(Context mContext, boolean is_removable) {

    StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
    Class<?> storageVolumeClazz = null;
    try {
        storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
        Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
        Method getPath = storageVolumeClazz.getMethod("getPath");
        Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
        Object result = getVolumeList.invoke(mStorageManager);
        final int length = Array.getLength(result);
        for (int i = 0; i < length; i++) {
            Object storageVolumeElement = Array.get(result, i);
            String path = (String) getPath.invoke(storageVolumeElement);
            boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
            if (is_removable == removable) {
                return path;
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

আমি ব্যক্তিগতভাবে প্রতিবিম্বটি ব্যবহার করতে পছন্দ করি না কারণ গুগল অ্যান্ড্রয়েডের নতুন সংস্করণগুলিতে পশ্চাদপদ সামঞ্জস্যের প্রশংসা করে না!
বেহরোজ.এম

0

আমি জানি না তবে এটি ব্যবহারের আগে আমাকে পাবলিক স্টোরেজ ডিরেক্টরিতে তৈরি করা একটি ফাইলে .createNewFile () কল করতে হবে। কাঠামোটিতে এই পদ্ধতির জন্য মন্তব্যগুলি বলে যে এটি কার্যকর নয়। এখানে একটি নমুনা ...


 String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS) + File.separator + "My Directory";
            final File myDir = new File(myPath);
            try {
                myDir.mkdirs();
            } catch (Exception ex) {
                Toast.makeText(this, "error: " + ex.getMessage(), Toast.LENGTH_LONG).show();
            }

        String fname = "whatever";
        File newFile = new File(myDir, fname);

        Log.i(TAG, "File exists --> " + newFile.exists()) //will be false  
    try {
            if (newFile.createNewFile()) {

                 //continue 

              } else {

                Log.e(TAG, "error creating file");

            }

        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }


0

আমি এসডি কার্ডটি ডিভাইসে উপলব্ধ কিনা তা যাচাই করার জন্য একটি ব্যবহার পদ্ধতি তৈরি করেছি এবং যদি পাওয়া যায় তবে ডিভাইসে এসডি কার্ডের পাথ পান।

আপনার প্রজেক্টের ক্লাসে আপনার প্রয়োজন মতো দুটি পদ্ধতি অনুলিপি করতে পারেন। এখানেই শেষ.

public String isRemovableSDCardAvailable() {
    final String FLAG = "mnt";
    final String SECONDARY_STORAGE = System.getenv("SECONDARY_STORAGE");
    final String EXTERNAL_STORAGE_DOCOMO = System.getenv("EXTERNAL_STORAGE_DOCOMO");
    final String EXTERNAL_SDCARD_STORAGE = System.getenv("EXTERNAL_SDCARD_STORAGE");
    final String EXTERNAL_SD_STORAGE = System.getenv("EXTERNAL_SD_STORAGE");
    final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE");

    Map<Integer, String> listEnvironmentVariableStoreSDCardRootDirectory = new HashMap<Integer, String>();
    listEnvironmentVariableStoreSDCardRootDirectory.put(0, SECONDARY_STORAGE);
    listEnvironmentVariableStoreSDCardRootDirectory.put(1, EXTERNAL_STORAGE_DOCOMO);
    listEnvironmentVariableStoreSDCardRootDirectory.put(2, EXTERNAL_SDCARD_STORAGE);
    listEnvironmentVariableStoreSDCardRootDirectory.put(3, EXTERNAL_SD_STORAGE);
    listEnvironmentVariableStoreSDCardRootDirectory.put(4, EXTERNAL_STORAGE);

    File externalStorageList[] = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        externalStorageList = getContext().getExternalFilesDirs(null);
    }
    String directory = null;
    int size = listEnvironmentVariableStoreSDCardRootDirectory.size();
    for (int i = 0; i < size; i++) {
        if (externalStorageList != null && externalStorageList.length > 1 && externalStorageList[1] != null)
            directory = externalStorageList[1].getAbsolutePath();
        else
            directory = listEnvironmentVariableStoreSDCardRootDirectory.get(i);

        directory = canCreateFile(directory);
        if (directory != null && directory.length() != 0) {
            if (i == size - 1) {
                if (directory.contains(FLAG)) {
                    Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory);
                    return directory;
                } else {
                    return null;
                }
            }
            Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory);
            return directory;
        }
    }
    return null;
}

/**
 * Check if can create file on given directory. Use this enclose with method
 * {@link BeginScreenFragement#isRemovableSDCardAvailable()} to check sd
 * card is available on device or not.
 * 
 * @param directory
 * @return
 */
public String canCreateFile(String directory) {
    final String FILE_DIR = directory + File.separator + "hoang.txt";
    File tempFlie = null;
    try {
        tempFlie = new File(FILE_DIR);
        FileOutputStream fos = new FileOutputStream(tempFlie);
        fos.write(new byte[1024]);
        fos.flush();
        fos.close();
        Log.e(getClass().getSimpleName(), "Can write file on this directory: " + FILE_DIR);
    } catch (Exception e) {
        Log.e(getClass().getSimpleName(), "Write file error: " + e.getMessage());
        return null;
    } finally {
        if (tempFlie != null && tempFlie.exists() && tempFlie.isFile()) {
            // tempFlie.delete();
            tempFlie = null;
        }
    }
    return directory;
}

-1

এটি সমস্ত বাহ্যিক ডিভাইসের জন্য কাজ করে, তবে কেবলমাত্র বাহ্যিক ডিভাইস ফোল্ডারের নাম পাওয়া যায় তা নিশ্চিত করুন এবং তারপরে আপনাকে ফাইল বর্গ ব্যবহার করে প্রদত্ত অবস্থান থেকে ফাইল আনতে হবে।

public static List<String> getExternalMounts() {
        final List<String> out = new ArrayList<>();
        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;
    }

কল করা হচ্ছে:

List<String> list=getExternalMounts();
        if(list.size()>0)
        {
            String[] arr=list.get(0).split("/");
            int size=0;
            if(arr!=null && arr.length>0) {
                size= arr.length - 1;
            }
            File parentDir=new File("/storage/"+arr[size]);
            if(parentDir.listFiles()!=null){
                File parent[] = parentDir.listFiles();

                for (int i = 0; i < parent.length; i++) {

                    // get file path as parent[i].getAbsolutePath());

                }
            }
        }

বাহ্যিক স্টোরেজে অ্যাক্সেস পাওয়া

বাহ্যিক স্টোরেজে ফাইলগুলি পড়তে বা লেখার জন্য, আপনার অ্যাপ্লিকেশনটিকে অবশ্যই READ_EXTERNAL_STORAGE বা WRITE_EXTERNAL_STORAGE সিস্টেম অনুমতি গ্রহণ করতে হবে। উদাহরণ স্বরূপ:

<manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...
</manifest>

-2

/ sdcard => অভ্যন্তরীণ স্টোরেজ (এটি একটি সিমিলিংক তবে কাজ করা উচিত)

/ mnt / extSdCard => বাহ্যিক এসডিকার্ড

এটি স্যামসাং গ্যালাক্সি এস 3 এর জন্য

আপনি সম্ভবত এটি বেশিরভাগের পক্ষে সত্য হয়ে উঠতে পারেন ... তবে ডাবল চেক করুন!


8
আমার বেশ কয়েকটি বিভিন্ন অ্যান্ড্রয়েড ফোন রয়েছে যার মধ্যে প্রায় অর্ধেক স্যামসুং রয়েছে এবং এই অবস্থানটি কখনও ব্যবহার করা হয়নি। এটি এস 3 এর ক্ষেত্রে সত্য হতে পারে, তবে "আপনি সম্ভবত এটি বেশিরভাগের পক্ষে সত্য বলেই ব্যাংক করতে পারেন" বলা সম্পূর্ণ ভুল।
Geobits

ভুল। /sdcardআমার সোনি 2305 এ বাহ্যিকের জন্য একটি সিমিলিংক
জিগগঞ্জর

2
আমি বলিনি যে এটি নাও হতে পারে?
robbyoconnor
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.