从SD卡播放音乐只能在模拟器上使用,而不能在手机上使用

问题描述:

我正在创建一个播放用户音乐的android应用程序.我已经使其在仿真器上可以正常工作,但是当我将其安装在手机上时却无法正常工作,它在此行崩溃:

I'm creating an android application that plays the users music. I've got it to work fine on an emulator but it's not working when I install it on a phone, it crashes at this line:

int songIndex = new Random().nextInt(songsList.size());

因为songList.size()返回0,因为在手机上运行时似乎找不到音乐.我已将Micro SD卡放入手机中,并将音乐加载到手机中(位于根文件夹中).我正在使用以下方法来获取路径:

Because songList.size() is returning 0, since it seems the music can't be found when it runs on a phone. I've put a Micro SD card in the phone, and have loaded music onto it (in the root folder). I'm using the following to get the path:

final String MEDIA_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();

在模拟器和电话上,从此返回的字符串是/mnt/sdcard.但这仅适用于仿真器.我的清单文件中还包含以下权限:

On both the emulator and the phone, the returned string from this is /mnt/sdcard. But it's only working on the emulator. I've also included the following permission in my manifest file:

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

有什么想法吗?

我之所以没有包含它,是因为我认为这不会有多大帮助,但这是我用来实际获取songList的代码:

I didn't include this because I didn't think it would help much, but this is the code I'm using to actually get the songList:

public ArrayList<HashMap<String, String>> getPlaylist(){
    File home = new File(MEDIA_PATH);

    if(home.listFiles(new FileExtensionFilter()).length > 0) {
        for(File file : home.listFiles(new FileExtensionFilter())){
            HashMap<String, String> song = new HashMap<String, String>();
            song.put("songTitle", file.getName().substring(0, (file.getName().length() -4)));
            song.put("songPath", file.getPath());

            //Add song to song list
            songsList.add(song);
        }
    }

    return songsList;
}

关于

return Environment.getExternalStorageDirectory().toString() + "/Music";

这会将路径返回到内部SD挂载点,例如"/mnt/sdcard"

This will return the path to internal SD mount point like "/mnt/sdcard"

与路径中的硬编码相比,这是一种更好的编码方式.

This is a better way of coding than hard coding in the path.

编辑

要使其在所有设备上都能正常工作,请尝试从此线程中使用以下代码他们讨论了Android除了外部存储之外没有外部SD"的概念.随后,OP给出了所有答案和评论,为他的问题提出了以下解决方案.

To get it working on all devices try the code below from this thread where they discuss that Android has no concept of "external SD", aside from external storage. OP then came up with the following solution for his problem as a result of all the answers and comments he was given.

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import android.os.Environment;
import android.util.Log;

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