데이터 저장 및 액세스 - SharedPreferences는 사용자 기본 설정 매개변수를 저장합니다.


이 섹션 소개:

이 섹션에서는 SharedPreferences(사용자 기본 설정 매개변수 저장)를 사용하여 데이터를 저장하는 두 번째 방법을 소개합니다. 우리 애플리케이션이 자동 로그인 여부, 계정 비밀번호 기억 여부, Wi-Fi 사용 여부 등 사용자의 기본 설정 매개변수 중 일부를 저장하려고 할 때. 네트워킹이나 기타 관련 정보는 데이터베이스를 사용한다면 좀 과한 것 같더라구요! 위의 구성 정보를 사용자 기본 설정이라고 합니다. 설정은 사용자 기본 설정이며 이러한 구성 정보는 일반적으로 특정 파일에 저장됩니다! 예를 들어 Windows에서는 ini 파일을 사용합니다. J2SE에서는 속성 파일과 xml 파일을 사용하여 우리가 일반적으로 사용하는 Android의 소프트웨어 구성 정보를 저장합니다. 경량 스토리지 클래스 - 사용자 기본 설정 매개변수를 저장하는 SharedPreferences! SharedPreferences는 xml 파일도 사용합니다. 그런 다음 Map 컬렉션과 유사하게 데이터는 키-값 형식으로 저장됩니다. SharedPreferences의 getXxx(name)만 호출하면 됩니다. 키를 기준으로 해당 값을 얻을 수 있습니다! 사용하기가 너무 쉽습니다!


1. SharedPreferences 사용 예:

흐름도 사용 :

1.png

구현 코드 예 :

렌더링 실행 :

계정에 들어가는 과정입니다. 비밀번호를 입력하고 로그인을 클릭하세요 정보를 SharedPreference 파일에 저장하려면, 그런 다음 앱을 다시 시작하고 텍스트 상자에 데이터가 표시되었는지 확인하세요

2.gif

저장한 후 File Expoler에서 data/data/<패키지 이름>을 열고 shared_prefs 디렉토리에서 볼 수 있습니다. XML 파일이 생성되었습니다(N5에는 루트가 없기 때문에 이전 렌더링은 다음과 같습니다):

3.jpg

내 콘텐츠를 보려면 데스크톱으로 내보내기를 클릭하세요.

4.jpg

코드 구현:

레이아웃 파일 쓰기 activity_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>

간단한 SP 도구 클래스 작성: 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;
    }
}

마지막으로, MainActivity.java관련 로직 구현:

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. 다른 애플리케이션의 SharedPreferences

core을 읽어보세요. 다른 앱의 Context를 얻습니다. 이 Context는 앱의 전체 정보에 액세스하기 위한 인터페이스를 나타내며 앱의 고유 식별을 결정합니다. 애플리케이션의 패키지 이름이므로 애플리케이션 패키지 이름을 통해 해당 앱의 Context를 얻을 수 있습니다. 또 한 가지 주의할 점은 다른 응용 프로그램의 SP 파일을 읽고 쓸 수 있는지 여부에 대한 전제 조건은 SP 파일이 읽기 가능 또는 쓰기 가능을 지정하는지 여부입니다. 위에서 생성한 권한이 MODE_PRIVATE인 경우 쓰기 권한이 허용되지 않습니다. 즉, 다른 사람의 SP에 있는 데이터를 읽는 것과 같습니다. 게다가 SP에 저장된 비밀번호 등 일부 핵심 정보는 대개 암호화되어 있어서 혼자서만 작성하고 플레이할 수 있습니다~ 일반적으로 사용되는 MD5 암호화 방법에 대해서는 나중에 이야기하겠습니다!

구현 흐름도:

5.png

코드 예:

렌더링 실행:

6.png

코드 구현: SP 읽기 작업은 Ma inActivity.java에 있습니다. 완료되면 버튼을 클릭하여 SP를 읽고 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. MD5를 사용하여 SharedPreference

의 중요한 데이터를 암호화합니다. 위에서는 계정 비밀번호를 sp에 직접 저장합니다. 휴대폰이 루팅되어 다른 애플리케이션이 휴대폰에 접근할 수 없습니다. 루팅되어 다른 애플리케이션에서 데이터를 획득하여 어떤 결과를 초래한다면... 우리를 비난할 필요는 없습니다. 하하, 누가 루팅하라고 했어요~ 우리는 책임을 지지 않습니다, 맞습니다! 하지만 책임감 있는 APP 개발자로서 우리는 항상 그럴 수는 없습니다. 맞습니까? 우리는 일부 암호화 알고리즘을 사용하여 사용자 비밀번호를 암호화할 수 있습니다. 또한 일반적으로 사용자 비밀번호를 암호화합니다. 암호화 처리 과정을 모두가 이해할 수 있도록 간단한 다이어그램을 그려보겠습니다.

1. 간단한 암호화 처리 과정

흐름도는 다음과 같습니다

:

7.png

흐름도 분석

:

  • 1단계 사용자는 계정과 비밀번호를 확인한 후(계정 중복 여부, 비밀번호 개수 > 6자리 등), 즉, 계정 비밀번호가 유효합니다. 등록이 성공적으로 완료되면 계정 번호와 로컬로 암호화된 비밀번호를 제출합니다!
  • 2단계 서버는 사용자가 제출한 계정과 암호화된 비밀번호를 서버의 데이터베이스, 즉 서비스에 저장합니다. 클라이언트는 일반 텍스트 비밀번호(원본) 비밀번호를 저장하지 않습니다!
  • 3단계 클라이언트로 돌아가서 등록이 성공했거나 로그인이 성공했다면 계정 비밀번호를 저장된 비밀번호인 SP에 저장하고 싶습니다. 암호화 과정도 거쳐야 합니다! 즉, 일반 텍스트 비밀번호——>암호화 후 저장! 저장하지 않으면 요청할 때마다 일반 텍스트 비밀번호가 사용됩니다. 집에서도 절차를 거쳐야 하고, 암호화된 비밀번호를 사용해 서버를 요청해야 해요!
  • 4단계. 서버는 계정과 암호화된 비밀번호를 확인합니다. 성공하면 클라이언트가 나중에 보유할 수 있는 세션 식별자가 할당됩니다. 이 세션은 서버에서 제공하는 관련 서비스에 접근하기 위해 사용됩니다!

이봐, 암호화 방법은 여러 가지가 있지만 Xiaozhu는 이 분야의 전문가가 아니며 이전에 사용된 암호화 방법은 MD5입니다. 암호화, 이 섹션에서는 MD5 암호화에 대한 간략한 소개와 사용법 시연도 제공합니다~

2. MD5에 대한 간략한 소개:

1) MD5란 무엇인가요? :

답변: 메시지 다이제스트 알고리즘 MD5(중국어 이름은 메시지 다이제스트 알고리즘 제5판)는 컴퓨터 보안 분야에서 널리 사용됩니다. 메시지 무결성 보호를 제공하는 데 사용되는 해시 함수 - "Baidu Encyclopedia"에서 발췌 쉽게 말하면 MD5를 이용하여 문자열, 파일, 압축패키지를 암호화할 수 있는 암호화 알고리즘입니다. 128비트의 고정된 길이를 가진 문자열을 생성할 수 있습니다! 이 문자열은 기본적으로 고유합니다! 게다가 우리 모두는 다음을 알고 있습니다. 4비트로 표현되어야 하며 해당 MD5 ​​문자열 길이는 128/4 = 32비트입니다! 또 다른 가능성 일부 md5는 16비트이지만 32비트 MD5 코드의 처음 8비트와 마지막 8비트가 제거되었습니다. 믿지 말고 한번 해보자 Baidu: md5 온라인 암호 해독, 첫 번째: http://www.cmd5.com/

8.png

2) MD5를 크랙할 수 있나요?

답변: MD5는 되돌릴 수 없습니다. 즉, 해당 알고리즘이 없으며 생성된 md5 값에서 원본 데이터를 역으로 얻을 수 없습니다! 물론, 무차별 크래킹을 제외한 간단한 MD5 암호화 후 MD5 라이브러리를 확인하실 수 있습니다~

3) MD5 값이 고유한가요?

답변: 고유하지 않습니다. 하나의 원본 데이터는 하나의 MD5 값에만 해당하지만 하나의 MD5 값은 여러 원본 데이터에 해당할 수 있습니다!


3. MD5 암호화 구현 예:

실제로 인터넷에는 잘 작성된 MD5 예가 많이 있습니다. Baidu나 Google에서 검색해 보면 Xiaozhu에서 사용하는 MD5 암호화 도구가 있습니다.

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 getMD5 정적 메소드를 직접 호출합니다:

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

Logcat이 인쇄하는 것을 볼 수 있습니다:

9.png

이것은 암호화된 것입니다. 하하, 이 암호문 문자열을 위의 md5 온라인 암호 해독에 복사할 수 있습니다. 웹사이트:

10.png

ㅋㅋㅋ 물론 한 번만 암호화해도 바로 크랙이 되니까 좀 불안한 것 같으니 100번만 암호화해 보세요. 즉, 암호화된 문자열을 다시 암호화하고 이를 100번 반복합니다. 원래 기준으로 100번 암호화하는 방법을 추가합니다:

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

그런 다음 호출하고 다음을 인쇄하는 로그를 찾습니다.

11.png

복사 인터페이스 웹사이트 위:

12.png

좋아요, 설치가 성공했습니다~


4. SharedPreference 도구 클래스:

SP 도구 클래스를 매번 직접 인스턴스화하는 것은 매우 번거로울 것입니다. 누구나 게시할 수 있습니다. 내 프로젝트에서 도구 클래스는 Hong Yang의 블로그에서 가져왔습니다~

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. 코드 다운로드:

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


이 섹션 요약:

좋아, Android가 데이터를 저장하는 두 번째 방법에 대해: SharedPreference는 사용자 기본 설정 매개변수의 내용을 저장합니다. 그게 전부입니다. , SP 개발 및 사용에 필요한 일상적인 요구 사항을 충족할 수 있어야 합니다. 부족한 점이 있으면 언제든지 언급해 주세요. 감사합니다~