1方案设计
  在各种应用设计的需求里,有可能涉及文件的存储路径的选择问题。本文介绍Android应用中涉及允许选择SD卡和手机存储,初步设想的方案:(1)在手机安装SD卡的情况下,优先选择存储在SD卡中,当用户卸载SD卡、拔出SD卡以及用户在设置中选择使用手机存储时,将选择存储在手机存储中;(2)在手机未安装SD卡的情况下,将存储在手机存储中,当用户安装入SD卡后,将主动选择存储在SD卡中。软件流程如下图所示。

  具体的路径如下:
SD卡:/storage/603E-5ED9/Movies/RecordVideo/
手机存储:/storage/emulated/0/Movies/RecordVideo/
2.实施方案
1)获取用户设置中选择的路径
  本应用创建了SettingFragment,并将路径选项用ListPreference实例化,在设置路径时,供用户在设置界面选择相应的路径。
  程序获取用户在设置中选择的路径,能通过获取此时设置界面中路径的选择项来判断此时的路径。由于我们提供给用户的只有2个选项:存储在手机内存中和存储在SD卡中。因此,在程序中使用布尔变量来判断用户是否选择使用SD卡存储视频。具体代码如下:

        SharedPreferences preferences = getSharedPreferences("recordscreensettings", MODE_PRIVATE);
        String typeView=preferences.getString(Config.ViewType, "0");
        String location=preferences.getString(Config.Location, "0");
        Log.v(tag, "location is "+location);
        if (location.equals("0")) {
            isUseSDcard=true;
            Log.v(tag, "isUseSDcard is "+isUseSDcard);
        }else  {
            isUseSDcard=false;
            Log.v(tag, "isUseSDcard is "+isUseSDcard);
        }

  可以通过判断isUseSDcard的值获取用户当前在设置中选择的路径。
2)获取手机中当前SD卡的挂载情况
  在获取用户在当前设置中选择的存储路径的同时,必须确定的是当前手机的SD卡是否挂载。有下面的情况是有可能存在的:手机中没有安装SD卡,手机中安装的SD卡没有识别和用户将SD卡卸载了。针对这种情况,我们在选择路径时应该判断当前SD卡的挂载情况。我们创建一个StorageUtils类管理应用的存储路径,写一个判断当前SD卡的挂载情况的方法。代码如下:

   public static boolean isSDCardExist(Context context, Object storageVolume) {
        boolean sdcardExist = isVolumeMounted(storageVolume);

        DebugLog.d(TAG, "isSDCardExist(): " + sdcardExist);

        return sdcardExist;
    }
     private static boolean isVolumeMounted(Object storageVolume) {
        boolean mountble = false;
        String storagePath = null;
        String state = null;
        try {
            if (null == storageVolume) {
                Log.d(TAG, "null == storageVolume failed in isVolumeRemoveble");
            }
            if (null == mStorageManager) {
                mStorageManager = mContext.getSystemService(Context.STORAGE_SERVICE);
            }
            storagePath = (String) storageVolume.getClass().getMethod("getPath").invoke(storageVolume);
            if (null == storagePath || 0 == storagePath.length()) {
                return false;
            }

            state = (String) mStorageManager.getClass().getMethod("getVolumeState", String.class)
                    .invoke(mStorageManager, storagePath);

            if (Environment.MEDIA_MOUNTED.equalsIgnoreCase(state)) {
                mountble = true;
            }
        } catch (Exception e) {
            Log.e(TAG, "Storage_Standard.isVolumeRemoveble()", e);
        }
        return mountble;
    }

  通过判断isSDCardExist方法返回的布尔值判断此时SD卡是否挂载。
3)对获取存储路径进行有效的选择
  对于路径的选择该应用只提供了2种选择方式。当选择SD卡成为视频存储的路径时,必须满足2个条件:

(1)用户在设置界面选择使用SD卡作为存储路径;

(2)使用SD卡存储视频时,SD卡挂载。通过上述分析,在获取视频存储路径时,应该对存储路径进行有效的选择,也就是路径选择正确且路径可用。

       if (isHaveSDcard&&isUseSDcard) {
            String pathSDStorage=storageUtils.getStorageDirectory(SdCardType.SDStorage);
            Log.v(tag, "pathSDStorage is "+pathSDStorage);
            pathstring=pathSDStorage;
        }else {
            String pathInternelStorage=storageUtils.getStorageDirectory(SdCardType.InternelStorage);
            Log.v(tag, "pathInternelStorage is "+pathInternelStorage);
            Log.v(tag, "the system of storage is"+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).toString());
            pathstring=pathInternelStorage;
        }

4)创建视频的文件名
  及时创建的文件应该给文件取一个合适的名称,本应用是即时软件,为了方便用户区别存储的文件,我们采用生成文件时的时间有关名称。名称格式如下:年-月-日_时_分_秒。

        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd_hh_mm_ss");

        String date = "/myscreen_" + sDateFormat.format(new java.util.Date());
    

5)创建完整的视频存储路径
  通过上述的步骤,我们就获取到了文件的存储路径以及文件的名称,接下来需要完成创建完整的文件存储路径。为了方便用户在文件夹目录下查找,不论在SD卡还是手机中存储录文件,我们将存储的文件放置在../Movies/RecordVideo/(根据自己的应用取名)的文件夹下。具体代码如下。

        sampleDir=new File(pathstring+File.separator+"Movies"+ File.separator + "RecordVideo/");
        if (!sampleDir.exists()) {
            sampleDir.mkdirs();
            Log.v(tag, "创建文件夹"+sampleDir.mkdirs());
        }
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd_hh_mm_ss");

        String date = "/myscreen_" + sDateFormat.format(new java.util.Date());
        Log.v(tag, "date=" + date);

        mVecordFile = new File(sampleDir.toString() + date + ".mp4");
        Log.v(tag, mVecordFile.toString());

3.总结
  我们在获取存储路径时,应该充分考虑用户在设置中的路径选择以及存储路径是否存在的情况。