Android设置里面默认存储器选项(default write disk)的实现
原生的Android设置里面没有默认存储器的选项,但是MTK偏偏加上了这个功能,可能MTK觉得这个比较有用吧,所以,他们在原生的基础上面做了修改,加上了这个功能。但是高通平台没有这个功能,相对MTK来说,高通比较严谨一点,不会随随便便加上一些功能,但是MTK平台优化了很多东西(有有点也有缺点),开发者这可能是很多山寨手机选择MTK平台的原因吧。
我给“默认存储器”做了一个简单的定义:一些内置应用的数据存放位置。当然,如果其他应用知道这个接口(不是标准接口,所以只有开发者本人知道,或者MTK的人),也可以使用该功能。
之前接到一个在高通平台上的手机里面加上默认存储器的选项,即如果选择本地内存,一些内置应用的数据将存储到本地内存里面,如果选择SD卡存储,则这些应用的数据将会存储到SD卡里面。借鉴MTK平台的实现方法,整理其思路是:通过SystemProperties接口往系统内存里面写入存储路径(set),然后在一些指定应用里面存储数据的时候判断当前默认存储器,使用get方法读取这个属性。为什么使用SystemProperties,因为其设置的值全局都可以使用,即不同应用都可以通过共享内存取出其值,解决了进程间通信的问题。
1:我们先在framework层加上一些自定义的接口文件。我加的位置是 ....../frameworks/base/core/java/android/os/storage/,添加的文件名StorageManagerEx.java,内容如下:
package android.os.storage; import android.util.Log; import com.android.internal.R; import android.os.SystemProperties; import java.io.File; import android.os.Environment; public class StorageManagerEx { » private static final String TAG ="StorageManagerEx"; » private static final String PROP_SD_DEFAULT_PATH = "persist.sys.sd.defaultpath"; » » private static final String STORAGE_PATH_SD1 ="/storage/sdcard0"; » private static final String STORAGE_PATH_SD2 ="/storage/sdcard1"; » private static final String STORAGE_PATH_SD1_ICS = "/mnt/sdcard"; » private static final String STORAGE_PATH_SD2_ICS = "/mnt/sdcard2"; » » private static final String STORAGE_PATH_SHARE_SD = "/storage/emulated/0"; » » /** » * Return default path for writing. » * @return default path. » * @hide » * @internal » */ public static String getDefaultPath(){ » String path = STORAGE_PATH_SD1; » try { » » path = SystemProperties.get(PROP_SD_DEFAULT_PATH); » » Log.i(TAG,"default path = "+path); » } catch (IllegalArgumentException e) { » » Log.e(TAG,"IllegalArgumentException when get default path:"+e); » } » //Property will be empty when first boot should set to default » if(path.equals("")){ » » Log.i(TAG,"getDefaultPath empty! set to default"); » » //Here may be some problems.refer to MTK:only share sd and no swap,internal path is » » //"/storage/emulated/0",i don't know "share" and "no swap",so i skip. » » // if (FeatureOption.MTK_SHARED_SDCARD && !FeatureOption.MTK_2SDCARD_SW AP) {» » » » // setDefaultPath(STORAGE_PATH_SHARE_SD); » » // path = STORAGE_PATH_SHARE_SD; » » // } else { » » // setDefaultPath(STORAGE_PATH_SD1); » » // path = STORAGE_PATH_SD1; » » // } » » setDefaultPath(STORAGE_PATH_SD1); » » path = STORAGE_PATH_SD1; » } » » //Here we don't care multi user which will be used by google,ignore and go on. » » //MOTA upgrade from ICS to JB,update defaultPath to JB. » if(path.equals(STORAGE_PATH_SD1_ICS)){ » » path = STORAGE_PATH_SD1; » » setDefaultPath(path); » }else if(path.equals(STORAGE_PATH_SD2_ICS)){ » » path = STORAGE_PATH_SD2; » » setDefaultPath(path); » } » » Log.i(TAG,"getDefaultPath path="+path); » return path; } /** * set default path for Appto storage data * this only can used by settings. * * @param path * @hide * @internal */ public static void setDefaultPath(String path){ » Log.i(TAG,"setDefaultPath path = " + path); » if (path == null) { » » Log.e(TAG,"setDefaultPath error! path = null"); » » return; » } » » try { » » SystemProperties.set(PROP_SD_DEFAULT_PATH,path); » } catch (IllegalArgumentException e) { » » Log.e(TAG,"IllegalArgumentException when setDefaultPath:" + e); » } } /** * Returns external SD card path.» /sdcard2 * @hide * @internal */ // public static String getExternalStoragePath(){» //method 1: //» String sdCardDir = null; // android.os.storage.StorageManager storageManager = // (android.os.storage.StorageManager) context // .getSystemService(Context.STORAGE_SERVICE); // StorageVolume[] volumes = storageManager.getVolumeList(); // for (int i = 0; i < volumes.length; i++) { // if (volumes[i].isRemovable() && volumes[i].allowMassStorage()) { // sdCardDir = volumes[i].getPath(); // break; // } // } // return sdCardDir; // } public static String getExternalStoragePath(){» //method 2: String sdCardDir = null; String state = Environment.getStorageState(new File(STORAGE_PATH_SD2)); if(state.equals(Environment.MEDIA_MOUNTED)){ » sdCardDir = STORAGE_PATH_SD2; }else if(state.equals(Environment.MEDIA_UNMOUNTED)){ » sdCardDir = Environment.MEDIA_UNMOUNTED; }else{ » sdCardDir = STORAGE_PATH_SD2; } return sdCardDir; } /** * Returns internal storage path. * @return * @hide * @internal */ public static String getInternalStoragePath(){ » String sdCardDir = null; » String state = Environment.getStorageState(new File(STORAGE_PATH_SHARE_SD)); » » if(state.equals(Environment.MEDIA_MOUNTED)){ » » sdCardDir = STORAGE_PATH_SD1; » }else if(state.equals(Environment.MEDIA_UNMOUNTED)){ » » sdCardDir = Environment.MEDIA_UNMOUNTED; » }else{ » » sdCardDir = STORAGE_PATH_SD1; » } » return sdCardDir; } 1 }
定义的主要作用是往系统内存的属性里面添加属性presist.sys.sd.default.我们可以进入adb里面查看和修改一些属性1:adb shell 2:getprop + 键(或不加) tip:我们也可以setprop + 键 +值
2:在设置里面添加默认存储器的选项:
在Settings的工程里面的.....res/xml/device_info_memory.xml的文件里面添加
......<span style="white-space:pre"> </span><PreferenceCategory android:key="memory_select" android:title="@string/select_memory" /> ......然后在PreferenceCategory里面添加RadioButtonPreference (此处省略)
在Memroy.java文件里面添加
private void initDefaultWriteDisk(){ » mDefaultWriteCategory = (PreferenceCategory)findPreference(DEFAULT_WRITE_CATEGORY_KEY); List<RadioButtonPreference> defaultWritePreference = new ArrayList<RadioButtonPreference>(); StorageVolume[] volumes = mStorageManager.getVolumeList(); List<StorageVolume> storageVolumesEx = initVolumeList(volumes); for (int i = 0; i < storageVolumesEx.size(); i++) { » StorageVolume volumn = storageVolumesEx.get(i); » RadioButtonPreference avalibileDisk = new RadioButtonPreference(getActivity()); » String path = volumn.getPath();» //volumn path » android.util.Log.i("haiyong.liu","volumn.path="+path); » String state = Environment.getStorageState(new File(path)); » » avalibileDisk.setKey(path); » avalibileDisk.setTitle(volumn.getDescription(getActivity())); » avalibileDisk.setPath(path); » avalibileDisk.setOnPreferenceChangeListener(this); » defaultWritePreference.add(avalibileDisk); » android.util.Log.e("haiyong.liu","Environment="+state); » if(state.equals(Environment.MEDIA_UNMOUNTED)||state.equals(Environment.MEDIA_REMOVED )){ » » » }else { » » mDefaultWriteCategory.addPreference(avalibileDisk); » » if(path.equals(StorageManagerEx.getDefaultPath())){ » » » avalibileDisk.setChecked(true); » » » mDeafultWritePathPref = avalibileDisk; » » }else{ » » » avalibileDisk.setChecked(false); » » } » } » » } } private List<StorageVolume> initVolumeList(StorageVolume[] volumes){ » List<StorageVolume> storageVolumes = new ArrayList<StorageVolume>(); » /*if(UserManager.supportsMultipleUsers()){» //return the current user's volumn lis t if supported,otherwise ignore. » » StorageVolume[] sv = mStorageManager.getVolumeListAsUser(); » » for (int i = 0; i < sv.length; i++) { if (!"not_present".equals(mStorageManager.getVolumeState(volumes[i].getPath()))) { storageVolumes.add(volumes[i]); } } » » return storageVolumes; » }*/ » for (int i = 0; i < volumes.length; i++) { if (!"not_present".equals(mStorageManager.getVolumeState(volumes[i].getPath()))) { storageVolumes.add(volumes[i]); } } return storageVolumes; } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference != null && preference instanceof RadioButtonPreference) { if (mDeafultWritePathPref != null) { mDeafultWritePathPref.setChecked(false); } StorageManagerEx.setDefaultPath(preference.getKey()); mDeafultWritePathPref = (RadioButtonPreference) preference; return true; } return false; }
然后在oncreate方法里面调用
initDefaultWriteDisk()这个方法,这个方法放在Memory.java的onCreate(...)方法里面,另外,StorageManagerEx.setDefaultPath(),这个方法只可以在settings这个apk里面使用,即只有settings这个apk可以写入。
3:找到对应需要添加该功能的工程,我们需要添加的是Camrea2,蓝牙,下载器,录音这几个Apk,找到这几个源码存储数据的地方,将存储位置改为StorageManagerEx.getDefaultPath()
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。