Data storage and access - SharedPreferences saves user preference parameters


Introduction to this section:

This section introduces you to the second way to store user data, using SharedPreferences (save user preference parameters) to save data. When our application wants to save some of the user's preference parameters, such as whether to log in automatically, whether to remember the account password, and whether to use Wifi. For networking and other related information, if you use a database, it seems a bit overkill! We call the above configuration information user preferences Settings are user preference settings, and these configuration information are usually saved in specific files! For example, Windows uses ini files, In J2SE, properties files and xml files are used to save software configuration information; in Android we usually use A lightweight storage class - SharedPreferences to save user preference parameters! SharedPreferences also uses xml files, Then, similar to the Map collection, data is stored in the form of key-value; we only need to call getXxx(name) of SharedPreferences, You can get the corresponding value based on the key! It's so easy to use!


1. SharedPreferences usage example:

Use flow chart:

1.png

Implementation code example:

Running renderings:

The process is to enter the account password and click login to save the information to the SharedPreference file. Then restart the app and see that the data has been displayed in the text box

2.gif

In addition, after saving, we can open data/data/<Package Name> in File Expoler. See in the shared_prefs directory An xml file was generated (because the N5 does not have root, here are the previous renderings):

3.jpg

Click export to desktop to see the content inside:

4.jpg

Code implementation:

Preparation of layout fileactivity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MyActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="用户登陆" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="请输入用户名" />

    <EditText
        android:id="@+id/editname"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="用户名" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请输入密码" />

    <EditText
        android:id="@+id/editpasswd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="密码"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/btnlogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录" />
</LinearLayout>

Write simple SP tool class: SharedHelper.java:

/**
 * Created by Jay on 2015/9/2 0002.
 */
public class SharedHelper {

    private Context mContext;

    public SharedHelper() {
    }

    public SharedHelper(Context mContext) {
        this.mContext = mContext;
    }


    //定义一个保存数据的方法
    public void save(String username, String passwd) {
        SharedPreferences sp = mContext.getSharedPreferences("mysp", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString("username", username);
        editor.putString("passwd", passwd);
        editor.commit();
        Toast.makeText(mContext, "信息已写入SharedPreference中", Toast.LENGTH_SHORT).show();
    }

    //定义一个读取SP文件的方法
    public Map<String, String> read() {
        Map<String, String> data = new HashMap<String, String>();
        SharedPreferences sp = mContext.getSharedPreferences("mysp", Context.MODE_PRIVATE);
        data.put("username", sp.getString("username", ""));
        data.put("passwd", sp.getString("passwd", ""));
        return data;
    }
}

Finally, MainActivity.java implements related logic:

public class MainActivity extends AppCompatActivity {

    private EditText editname;
    private EditText editpasswd;
    private Button btnlogin;
    private String strname;
    private String strpasswd;
    private SharedHelper sh;
    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = getApplicationContext();
        sh = new SharedHelper(mContext);
        bindViews();
    }

    private void bindViews() {
        editname = (EditText)findViewById(R.id.editname);
        editpasswd = (EditText)findViewById(R.id.editpasswd);
        btnlogin = (Button)findViewById(R.id.btnlogin);
        btnlogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                strname = editname.getText().toString();
                strpasswd = editpasswd.getText().toString();
                sh.save(strname,strpasswd);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Map<String,String> data = sh.read();
        editname.setText(data.get("username"));
        editpasswd.setText(data.get("passwd"));
    }
}

2. Read SharedPreferences

Core of other applications: Obtain the Context of other apps, and this Context represents the interface for accessing the global information of the app, and determines the unique identification of the app. It is the package name of the application, so we can get the Context of the corresponding app through the application package name. Another thing to note is that the prerequisite for whether the SP files of other applications can be read and written is whether the SP file specifies readable or Writable permissions are not allowed if the one we created above is MODE_PRIVATE~ So you are like reading the data in someone else's SP. It's difficult. In addition, some key information, such as passwords saved in SP, are usually encrypted, so you can only write and play by yourself~ I will talk about the commonly used MD5 encryption method later!

Implementation flow chart:

5.png

##Code example:

Running renderings:

6.png

Code implementation:

Our operation of reading SP is placed in MainActivity.java Completed, click the button to read the SP and display it through Toast:

public class MainActivity extends AppCompatActivity {

    private Context othercontext;
    private SharedPreferences sp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btnshow = (Button) findViewById(R.id.btnshow);
        btnshow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获得第一个应用的包名,从而获得对应的Context,需要对异常进行捕获
                try {
                    othercontext = createPackageContext("com.jay.sharedpreferencedemo", Context.CONTEXT_IGNORE_SECURITY);
                } catch (PackageManager.NameNotFoundException e) {
                    e.printStackTrace();
                }
                //根据Context取得对应的SharedPreferences
                sp = othercontext.getSharedPreferences("mysp", Context.MODE_WORLD_READABLE);
                String name = sp.getString("username", "");
                String passwd = sp.getString("passwd", "");
                Toast.makeText(getApplicationContext(), "Demo1的SharedPreference存的\n用户名为:" + name + "\n密码为:" + passwd, Toast.LENGTH_SHORT).show();
            }
        });
    }
}


3. Use MD5 to encrypt the important data of SharedPreference

Hehe, we have the above In this way, the account password is saved directly to the SP. If the phone is not rooted, other applications will not be able to access the phone. If you are rooted and the data is obtained by other applications, causing some consequences, then... you don’t have to blame us, haha, Who told you to root~, we don’t take the blame, that’s true! But as a responsible APP developer, we can’t always Is that right? We can use some encryption algorithms to encrypt user passwords. In addition, we generally encrypt user passwords! Below we draw a simple diagram to help everyone understand the encryption processing process:

1. Simple encryption processing process

The flow chart is as follows:

7.png

Flow chart analysis:

  • Step 1. The user registers the account and password. After the account and password are verified (whether the account is duplicated, the number of passwords is > 6 digits, etc.), That is, the account password is valid. After successful registration, we submit the account number and the locally encrypted password to the server!
  • Step 2. The server saves the account number and encrypted password submitted by the user to the database of the server, that is, the service The client does not save our clear text password (original) password!
  • Step 3. Back to the client, if the registration is successful or the login is successful, you want to save the account password to the SP, the saved password You also need to go through the encryption process! That is, plain text password——>Encrypt, then save! If you do not save it, the clear text password will be used every time you request it. You also need to go through the process at home, and then use the encrypted password to request the server!
  • Step 4. The server verifies the account and encrypted password. If successful, the client is assigned a session identifier, which the client can hold later. This session is used to access related services provided by the server!

Hey, you understand, there are many encryption methods, Xiaozhu is not an expert in this area, the encryption method used before is MD5 Encryption, this section also gives you a brief introduction to this MD5 encryption, and a demonstration of its usage~

2. A brief introduction to MD5:

1) What is MD5? :

Answer: Message Digest Algorithm MD5 (Chinese name is Message Digest Algorithm Fifth Edition) is widely used in the field of computer security. A hash function used to provide message integrity protection - excerpted from "Baidu Encyclopedia" To put it simply, it is an encryption algorithm that can encrypt a string, file, or compressed package using MD5. You can produce a string with a fixed length of 128 bits! This string is basically unique! In addition, we all know: a hexadecimal It needs to be represented by 4 bits, then the corresponding MD5 string length is: 128 / 4 = 32 bits! Another possibility You see that some md5 is 16 bits, but the first eight and last eight bits of the 32-bit MD5 code are removed! Don’t believe it, let’s try it Baidu: md5 online decryption, the first one: http://www.cmd5.com/

8.png

2) Can MD5 be cracked?

Answer: MD5 is irreversible, which means that there is no corresponding algorithm and the original data cannot be obtained reversely from the generated md5 value! Of course, except for brute force cracking, you can check the MD5 library after simple MD5 encryption~

3) Is the MD5 value unique?

Answer: Not unique. One original data only corresponds to one MD5 value, but one MD5 value may correspond to multiple original data!


3. MD5 encryption implementation example:

In fact, there are many well-written MD5 examples on the Internet. You can search a lot of them on Baidu or Google. Here are the Xiaozhu MD5 encryption tool class used!

Md5Util.java

/**
 * Created by Jay on 2015/9/2 0002.
 */
public class MD5 {
    public static String getMD5(String content) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(content.getBytes());
            return getHashString(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String getHashString(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString();
    }
}

MainActivity.java Directly call the static method getMD5:

Log.e("HeHe", MD5.getMD5("呵呵"));

We can see the Logcat printed out:

9.png

This is what happens after encryption. We can copy this string of ciphertext to the md5 online decryption website above:

10.png

Hey, sure enough, it’s just encrypted once like this. Just crack it directly. It seems a bit unsafe, so just encrypt it 100 times. That is to re-encrypt the encrypted string and repeat it 100 times. We add a method of encrypting it a hundred times on the original basis:

public static String getMD5x100(String content){
    String s1 = content;
    for(int i = 0;i < 100;i++){
        s1 = getMD5(s1);
    }
    return s1;
}

Then call it and find the Log that prints this:

11.png

On the copy interface website:

12.png

Okay, the installation is successful~


4.SharedPreference Tool class:

It must be very troublesome to instantiate SP-related classes by yourself every time. Here is the SP tool class, you can post it In my own project, the tool class comes from Hong Yang’s blog~

SPUtils.java

package com.jay.sharedpreferencedemo3;

import android.content.Context;
import android.content.SharedPreferences;

import java.util.Map;

/**
 * Created by Jay on 2015/9/2 0002.
 */
public class SPUtils {
    /**
     * 保存在手机里的SP文件名
     */
    public static final String FILE_NAME = "my_sp";

    /**
     * 保存数据
     */
    public static void put(Context context, String key, Object obj) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        if (obj instanceof Boolean) {
            editor.putBoolean(key, (Boolean) obj);
        } else if (obj instanceof Float) {
            editor.putFloat(key, (Float) obj);
        } else if (obj instanceof Integer) {
            editor.putInt(key, (Integer) obj);
        } else if (obj instanceof Long) {
            editor.putLong(key, (Long) obj);
        } else {
            editor.putString(key, (String) obj);
        }
        editor.commit();
    }


    /**
     * 获取指定数据
     */
    public static Object get(Context context, String key, Object defaultObj) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
        if (defaultObj instanceof Boolean) {
            return sp.getBoolean(key, (Boolean) defaultObj);
        } else if (defaultObj instanceof Float) {
            return sp.getFloat(key, (Float) defaultObj);
        } else if (defaultObj instanceof Integer) {
            return sp.getInt(key, (Integer) defaultObj);
        } else if (defaultObj instanceof Long) {
            return sp.getLong(key, (Long) defaultObj);
        } else if (defaultObj instanceof String) {
            return sp.getString(key, (String) defaultObj);
        }
        return null;
    }

    /**
     * 删除指定数据
     */
    public static void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        editor.commit();
    }


    /**
     * 返回所有键值对
     */
    public static Map<String, ?> getAll(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
        Map<String, ?> map = sp.getAll();
        return map;
    }

    /**
     * 删除所有数据
     */
    public static void clear(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        editor.commit();
    }

    /**
     * 检查key对应的数据是否存在
     */
    public static boolean contains(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
        return sp.contains(key);
    }

}

5. Code download:

SharedPreferenceDemo.zipDownload SharedPreferenceDemo.zipSharedPreferenceDemo2.zipDownload SharedPreferenceDemo2.zipSharedPreferenceDemo3.zip Download SharedPreferenceDemo3.zip


Summary of this section:

Okay, about the second way to store data in Android: SharedPreference So much for saving user preference parameters. It should be able to meet your needs for daily development and use of SP. If there is anything missing, please feel free to mention it, thank you~