SharedPreferences詳解


很多時候我們開發的軟件需要向用戶提供軟件參數設置功能,例如我們常用的QQ,用戶可以設置是否允許陌生人添加自己為好友。對於軟件配置參數的保存,如果是window軟件通常我們會采用ini文件進行保存,如果是j2se應用,我們會采用properties屬性文件進行保存。如果是Android應用,我們最適合采用什么方式保存軟件配置參數呢?Android平台給我們提供了一個SharedPreferences類,它是一個輕量級的存儲類,特別適合用於保存軟件配置參數。使用SharedPreferences保存數據,其背后是用xml文件存放數據,文件存放在/data/data/<package name>/shared_prefs目錄下:
SharedPreferences sharedPreferences = getSharedPreferences("itcast", Context.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();//獲取編輯器
editor.putString("name", "傳智播客");
editor.putInt("age", 4);
editor.commit();//提交修改
生成的itcast.xml文件內容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="name">傳智播客</string>
<int name="age" value="4" />
</map>
因為SharedPreferences背后是使用xml文件保存數據,getSharedPreferences(name,mode)方法的第一個參數用於指定該文件的名稱,名稱不用帶后綴,后綴會由Android自動加上。方法的第二個參數指定文件的操作模式,共有四種操作模式,這四種模式前面介紹使用文件方式保存數據時已經講解過。如果希望SharedPreferences背后使用的xml文件能被其他應用讀和寫,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權限。
另外Activity還提供了另一個getPreferences(mode)方法操作SharedPreferences,這個方法默認使用當前類不帶包名的類名作為文件的名稱。
-----------------------------------------------------------------------

訪問SharedPreferences中的數據代碼如下:
SharedPreferences sharedPreferences = getSharedPreferences("itcast", Context.MODE_PRIVATE);
//getString()第二個參數為缺省值,如果preference中不存在該key,將返回缺省值
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 1);

如果訪問其他應用中的Preference,前提條件是:該preference創建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE權限。如:有個<package name>為cn.itcast.action的應用使用下面語句創建了preference。
getSharedPreferences("itcast", Context.MODE_WORLD_READABLE);
其他應用要訪問上面應用的preference,首先需要創建上面應用的Context,然后通過Context 訪問preference ,訪問preference時會在應用所在包下的shared_prefs目錄找到preference :
Context otherAppsContext = createPackageContext("cn.itcast.action", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppsContext.getSharedPreferences("itcast", Context.MODE_WORLD_READABLE);
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 0);

如果不通過創建Context訪問其他應用的preference,可以以讀取xml文件方式直接訪問其他應用preference對應的xml文件,如:
File xmlFile = new File(“/data/data/<package name>/shared_prefs/itcast.xml”);//<package name>應替換成應用的包名

 

 

—————————————又一個———————————————————————————————

——————————————————————————————————————————

我們在開發軟件的時候,常需要向用戶提供軟件參數設置功能,例如我們常用的微信,用戶可以設置是否允許陌生人添加自己為好友.對於軟件配置參數的保存,如果是在window下通常我們會采用ini文件進行保存.如果是J2EE下面,我們會采用properties屬性文件或者xml進行保存.在我們的Android應用中又適合采用什么方式保存軟件配置參數呢?Android平台給我們提供了一個SharedPreferences類,它是一個輕量級應用程序內部輕量級的存儲方案,特別適合用於保存軟件配置參數,比如boolean,int,float,long,String等數據.使用SharedPreferences保存數據,其實質是采用了xml文件存放數據,路徑為:/data/data/<package name>/shared_prefs.

獲取SharedPreferences的兩種方式:
1 調用Context對象的getSharedPreferences()方法
2 調用Activity對象的getPreferences()方法
兩種方式的區別:
調用Context對象的getSharedPreferences()方法獲得的SharedPreferences對象可以被同一應用程序下的其他 組件共享.
調用Activity對象的getPreferences()方法獲得的SharedPreferences對象只能在該Activity中使用.
 
SharedPreferences的四種操作模式:
Context.MODE_PRIVATE
Context.MODE_APPEND
Context.MODE_WORLD_READABLE
Context.MODE_WORLD_WRITEABLE
 
Context.MODE_PRIVATE:為默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容
Context.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件.
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應用是否有權限讀寫該文件.
MODE_WORLD_READABLE:表示當前文件可以被其他應用讀取.
MODE_WORLD_WRITEABLE:表示當前文件可以被其他應用寫入.
將數據保存至SharedPreferences:
SharedPreferences preferences=getSharedPreferences("user",Context.MODE_PRIVATE);
Editor editor=preferences.edit();
String name="xixi";
String age="22";
editor.putString("name", name);
editor.putString("age", age);
editor.commit();
 
從SharedPreferences獲取數據:
SharedPreferences preferences=getSharedPreferences("user", Context.MODE_PRIVATE);
String name=preferences.getString("name", "defaultname");
String age=preferences.getString("age", "0");

 

 

 

———————————————又有一個—————————————————————————————

——————————————————————————————————————————————————

這是我最近碰到過的一個問題,之前並沒有一個清晰的認識!唯一的印象是,SharedPreferences 是可以用來存取數據。直到前些日子,在360漏洞掃描應用后,才意識到這個問題,如何正確的使用SharedPreferences呢?以下是360漏洞掃描的信息:

 

關於SharedPreferences順便再復習一下:

 

SharedPreferences 是Android 中的內置API,它允許我們存取鍵值對形式的基礎類型數據,像:boolean,float ,int , long , string 。這些數據將會持久化的存在,即使你的應用程序結束之后(注意:如果應用從手機上寫在掉后,該程序對應的SharedPreferences將會消失,保存在路徑:/data/data/<package_name>/shared_prefs 目錄下)

 

注意:User Preferences 用戶配置

 

嚴格來說,SharedPreferences最好不要用來保存“用戶配置”,比如,用戶選擇了什么鈴聲,是否自動更新等等。如果要為應用創建用戶配置,可以使用PreferenceActivity,它可以用來創建“用戶配置”。(PreferenceActivity用來創建程序中的設置界面)

 

 

如何在應用程序中獲取SharedPreferences呢?有兩個方法:

 

getSharedPreferences(name , mode) - 如果你的應用需要多個preferences文件可以使用該方法。該方法的第一個參數,用來區別不同的preferences文件。

比如:

 

SharedPreferences sp1 = getSharedPreferences("sp_1" , Context.MODE_PRIVATE);

SharedPreferences sp2 = getSharedPreferences("sp_2" , Context.MODE_PRIVATE);

是同一個應用程序的兩個不同的配置文件。

 

該方法的第二個參數支持如下幾種值:

Context.MODE_PRIVATE:指定該SharedPreferences數據只能被本應用程序或者是擁有相同user ID的應用讀、寫。

 

Context.MODE_WORLD_READABLE :指定該SharedPreferences數據能被其它應用程序讀,但不能寫。

這個變量在API 17以后已經不建議使用了。創建全局可讀文件是非常危險的事,這樣會引起程序的安全漏洞。程序之間的交互應該更多的使用正規的途徑,比如:ContentProvider, BroadcastReceiver, and Service.當程序通過備份和恢復后,並不能保證這種獲取方式依然對該文件有效。文件創建模式:允許所有的其它程序來讀取創建的文件。

Context.MODE_WORLD_WRITEABLE:指定該SharedPreferences數據能被其它應用程序讀,寫。

 

這個變量在API 17以后已經不建議使用了。創建全局可寫文件是非常危險的事,這樣會引起程序的安全漏洞.程序之間的交互應該更多的使用正規的途徑,比如:ContentProvider, BroadcastReceiver, and Service.當程序通過備份和恢復后,並不能保證這種獲取方式依然對文件有效。文件創建模式:允許所有的其它程序來修改創建的文件。

 

Context.MODE_MULTI_PROCESS

在API11中添加,SharedPreferences加載標記:被設置后,在硬盤上的文件在被修改是將會被檢查如果當前的SharedPreferences實例已經被加載進進程后。這種情況通常發生在,當程序有多個進程在修改同一個SharedPreferences文件的時候。通常來說這種方式在進程之間交互表現是非常好的。

 

 

 

在API 2.3之前,發布release版本時,這個標記是默認存在的,當發布release版本時。對於使用2.3以上的sdk進行編譯的時候,如果想使用那么

必須明確的設置。

 

getPreferences() - 如果你的Activity僅僅需要一個preferences文件可以使用這個方法。因為你的Activity只要一個preferences文件,所以不需要提供名字。

 

如何往SharedPreferences中寫數據呢?

 

1、需要獲取SharedPreferences的編輯對象即:SharedPreferences.Editor :  使用 edit()。

比如:SharedPreferences.Editor  editor = sp1.edit();

2、使用putXXX()方法,向preferences寫入數據:

比如:editor.putXXX(“key” , value);

3、向preferences文件中提交數據:

比如:editor.commit();

 

如何讀取數據呢?

使用方法getXXX()等方法讀取。

比如:

boolean silent = settings.getBoolean("silentMode", false);

 

 

下面是Google doc提供的一個demo:

  1. public class Calc extends Activity {  
  2.     public static final String PREFS_NAME = "MyPrefsFile";  
  3.   
  4.     @Override  
  5.     protected void onCreate(Bundle state){  
  6.        super.onCreate(state);  
  7.        . . .  
  8.   
  9.        // Restore preferences  
  10.        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);  
  11.        boolean silent = settings.getBoolean("silentMode", false);  
  12.        setSilent(silent);  
  13.     }  
  14.   
  15.     @Override  
  16.     protected void onStop(){  
  17.        super.onStop();  
  18.   
  19.       // We need an Editor object to make preference changes.  
  20.       // All objects are from android.context.Context  
  21.       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);  
  22.       SharedPreferences.Editor editor = settings.edit();  
  23.       editor.putBoolean("silentMode", mSilentMode);  
  24.   
  25.       // Commit the edits!  
  26.       editor.commit();  
  27.     }  
  28. }  
public class Calc extends Activity {
    public static final String PREFS_NAME = "MyPrefsFile";

    @Override
    protected void onCreate(Bundle state){
       super.onCreate(state);
       . . .

       // Restore preferences
       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
       boolean silent = settings.getBoolean("silentMode", false);
       setSilent(silent);
    }

    @Override
    protected void onStop(){
       super.onStop();

      // We need an Editor object to make preference changes.
      // All objects are from android.context.Context
      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
      SharedPreferences.Editor editor = settings.edit();
      editor.putBoolean("silentMode", mSilentMode);

      // Commit the edits!
      editor.commit();
    }
}

 

接下來看Google doc 中關於sharedpreferences的文檔。

 

SharedPreferences 本身是一個接口,用來獲取和修改程序的配置數據,位於:android.content.SharedPreferences。程序無法直接創建SharedPreferences實例,只能通過conext的getSharedPreferences(String, int)的獲取接口實例。

 

注意:當前類不支持跨進程調用,將會在之后的版本中支持。

 

它提供了如下方法來訪問perferences數據:

 

boolean contains(String key) :判斷當前preferences是否包含key所對應的數據。

 

abstract SharedPreferences.Editor edit():為preferences創建一個新的Editor,因此你可以修改preferences的數據並且提交給SharedPreferences對象。

 

 

abstract Map<String, ?> getAll() :獲取preferences中所包含的所有數據。

 

 

abstract XXX getXXX(String key, boolean defValue):獲取perferences里指定的key對應的value。如果該key不存在,則返回默認defValue .其中XXX是基礎數據類型:boolean、float、int、long、String等。

 

SharedPreferences接口本身並沒有提供寫入數據的能力,而是通過SharedPreferences的內部接口,SharedPreferences調用edit()方法即可獲取它所對應的Editor對象。

 

Editor提供了如下方法來寫向perferences入數據:

 

 

abstract SharedPreferences.Editor clear()

在Editor中標記出:清除所有preferences保存的數據。(注意此方法並沒有實質性的清除,只是在Editor上進行了標記,需要commit后才可以進行真正的清除)

 

abstract boolean commit():

將Editor對preferences的修改提交給SharedPreferences對象,完成對preferences中數據的修改。

 

abstract SharedPreferences.Editor putXXX(String key, boolean value)

向preferences中存入key及其所對應的數據 <key-value>。其中xxx可以是boolean、float、int、long、String等各種基本類型的數值。

 

abstract SharedPreferences.Editor remove(String key):

在Editor中標記出preference中以key以鍵的鍵值對應該被移除,而實際的移除動作將會在commit()執行之后才會作用於真正的preferences。

 

如何讀取其它應用的SharedPreferences:

 

 如上所述,如果想讀、寫其它應用的SharedPreferences,前提是創建該SharedPreferences的應用程序指定相應的訪問權限,例如指定了MODE_WORLD_READABLE , 這表明該SharedPreferences可被其它應用程序讀取。指定了MODE_WORLD_WRITEABLE,這表明該SharedPreferences可被其它程序寫入。

 

為了讀取其它程序對應的Context,可按照如下步驟進行:

1、需要創建其它程序對應的Context,例如如下代碼:

Context userCount  = createPackageContext(“com.sharedpreferencesdemo.zhanggeng” , Context.CONTEXT_IGNORE_SECURITY);

 

上面的程序中:com.sharedpreferencesdemo.zhanggeng 就是其他程序的包名——實際上Android系統就是用應用程序的報名來作為程序的標識的。

2、調用其它程序的conext的getSharedPreferences(String name , int mode) 即可獲取相應的SharedPreferences對象。

3、調用SharedPreferences的edit()方法獲取相應的Editor即可。

 

如下demo所示:

  1. private void readOtherAppSp() {  
  2.         Context useCount = null;  
  3.   
  4.         try {  
  5.             //獲取其它程序對應的Context  
  6.             useCount = createPackageContext("com.sharedpreferencesdemo.zhanggeng" , Context.CONTEXT_IGNORE_SECURITY);  
  7.         } catch (PackageManager.NameNotFoundException e) {  
  8.             e.printStackTrace();  
  9.         }  
  10.         //使用其它程序的Context獲取對應的SharedPreferences  
  11.         SharedPreferences prefs = useCount.getSharedPreferences("count" , Context.MODE_WORLD_READABLE);  
  12.         //讀取數據  
  13.         int count = prefs.getInt("count" , 0);  
  14.         //后續處理.....  
  15.     }  
private void readOtherAppSp() {
        Context useCount = null;

        try {
            //獲取其它程序對應的Context
            useCount = createPackageContext("com.sharedpreferencesdemo.zhanggeng" , Context.CONTEXT_IGNORE_SECURITY);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        //使用其它程序的Context獲取對應的SharedPreferences
        SharedPreferences prefs = useCount.getSharedPreferences("count" , Context.MODE_WORLD_READABLE);
        //讀取數據
        int count = prefs.getInt("count" , 0);
        //后續處理.....
    }

 

那么回到最初的問題,改如何正確的使用SharedPreferences?

1、設置相應的權限:如果只供本程序或者有相同user id的程序使用 使用Context.MODE_PRIVATE權限;如果允許其它程序可讀設置權限;如果允許其它程序可寫設置相應權限;

2、SharedPreferences保存的數據最好是基礎數據類型(當然也可以用來保存用戶配置,官方推薦PreferenceActivtiy )。

3、如果想讓程序有多個preferences文件使用getSharedPreferences(xxx , xxx);如果想讓程序只有一個preferences使用getPreferences()。

4、SharedPreferences最好不要用來保存多個程序交互使用的共享數據,建議使用ContentProvider, BroadcastReceiver, and Service 來完成多個程序之間的數據共享。

 

參考文檔:

1、http://developer.android.com/reference/android/content/SharedPreferences.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM