利用Java反射机制改变SharedPreferences存储路径

来源:互联网 发布:软件开发平台有哪些 编辑:程序博客网 时间:2024/05/24 00:11

      最近在做一个项目,想到要使用SharedPreferences类去存储一些简单的数据,但是我们知道,使用SharedPreferences保存数据,其实质是采用了xml文件存放数据,路径为:/data/data/<package name>/shared_prefs. 但是有些时候,我们不想将xml文件存储到SharedPreferences累指定的目录下,比如说,我想将xml文件存储到sdcard下面,这个时候,我们该怎么办呢?

   我们知道,SharedPreferences是封装好的类,我们只能使用类提供的方法,但是我们也知道,使用java的反射机制,类在我们面前就是透明的,我们可以任意使用类中的方法,变量,构造器等等。所以,这里,我想到使用java的反射机制去解决这个问题。但是在使用java的反射机制之前,有些概念我们还是要了解的。


 Context类    路径: /frameworks/base/core/java/android/content/Context.java

            说明:  抽象类,提供了一组通用的API。

      源代码(部分)如下:   

[java] view plaincopyprint?
  1. public abstract class Context {  
  2.      ...  
  3.      public abstract Object getSystemService(String name);  //获得系统级服务  
  4.      public abstract void startActivity(Intent intent);     //通过一个Intent启动Activity  
  5.      public abstract ComponentName startService(Intent service);  //启动Service  
  6.      //根据文件名得到SharedPreferences对象  
  7.      public abstract SharedPreferences getSharedPreferences(String name,int mode);  
  8.      ...  
  9. }  

ContextIml.java类  路径 :/frameworks/base/core/java/android/app/ContextImpl.java

          说明:该Context类的实现类为ContextIml,该类实现了Context类的功能。请注意,该函数的大部分功能都是直接调用

      其属性mPackageInfo去完成。    

         源代码(部分)如下:

[java] view plaincopyprint?
  1. /** 
  2.  * Common implementation of Context API, which provides the base 
  3.  * context object for Activity and other application components. 
  4.  */  
  5. class ContextImpl extends Context{  
  6.     //所有Application程序公用一个mPackageInfo对象  
  7.     /*package*/ ActivityThread.PackageInfo mPackageInfo;  
  8.       
  9.     @Override  
  10.     public Object getSystemService(String name){  
  11.         ...  
  12.         else if (ACTIVITY_SERVICE.equals(name)) {  
  13.             return getActivityManager();  
  14.         }   
  15.         else if (INPUT_METHOD_SERVICE.equals(name)) {  
  16.             return InputMethodManager.getInstance(this);  
  17.         }  
  18.     }   
  19.     @Override  
  20.     public void startActivity(Intent intent) {  
  21.         ...  
  22.         //开始启动一个Activity  
  23.         mMainThread.getInstrumentation().execStartActivity(  
  24.             getOuterContext(), mMainThread.getApplicationThread(), nullnull, intent, -1);  
  25.     }  
  26. }  

 

  ContextWrapper类 路径 :\frameworks\base\core\java\android\content\ContextWrapper.java

        说明: 正如其名称一样,该类只是对Context类的一种包装,该类的构造函数包含了一个真正的Context引用,即ContextIml

       对象。    源代码(部分)如下:

[java] view plaincopyprint?
  1. public class ContextWrapper extends Context {  
  2.     Context mBase;  //该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值  
  3.       
  4.     //创建Application、Service、Activity,会调用该方法给mBase属性赋值  
  5.     protected void attachBaseContext(Context base) {  
  6.         if (mBase != null) {  
  7.             throw new IllegalStateException("Base context already set");  
  8.         }  
  9.         mBase = base;  
  10.     }  
  11.     @Override  
  12.     public void startActivity(Intent intent) {  
  13.         mBase.startActivity(intent);  //调用mBase实例方法  
  14.     }  
  15. }  

Context相关类的继承关系




SharedPreferences原则上只能保存在当前应用程序私有的Shared_prefs目录中,但利用Java的反射机制可以改变系统内定的文件存储路径。

例如:将config.xml文件保存在SD卡的根目录中。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. private void savePreToSDcard() {  
  2.         try {  
  3.             Field field;  
  4.             // 获取ContextWrapper对象中的mBase变量。该变量保存了ContextImpl对象  
  5.             field = ContextWrapper.class.getDeclaredField("mBase");  
  6.             field.setAccessible(true);  
  7.             // 获取mBase变量  
  8.             Object obj = field.get(this);  
  9.             // 获取ContextImpl.mPreferencesDir变量,该变量保存了数据文件的保存路径  
  10.             field = obj.getClass().getDeclaredField("mPreferencesDir");  
  11.             field.setAccessible(true);  
  12.             // 创建自定义路径  
  13.             File file = new File("/sdcard");  
  14.             // 修改mPreferencesDir变量的值  
  15.             field.set(obj, file);  
  16.             SharedPreferences mySharedPreferences = getSharedPreferences(  
  17.                     "config", Activity.MODE_PRIVATE);  
  18.             SharedPreferences.Editor editor = mySharedPreferences.edit();  
  19.             editor.putString("name""20130310");  
  20.             editor.commit();  
  21.         } catch (NoSuchFieldException e) {  
  22.             // TODO Auto-generated catch block  
  23.             e.printStackTrace();  
  24.         } catch (IllegalArgumentException e) {  
  25.             // TODO Auto-generated catch block  
  26.             e.printStackTrace();  
  27.         } catch (IllegalAccessException e) {  
  28.             // TODO Auto-generated catch block  
  29.             e.printStackTrace();  
  30.         }  
  31.     }  
0 0
原创粉丝点击