2016年10月24日 星期一

Context 的 openFileOutput/openFileInput、SharedPreferences (Android)

※Context的openFileOutput/openFileInput

從data/data/com.example~~~/files資料夾裡,讀或寫
其中com.example~~~是getApplicationContext().getPackageName()


※strings.xml

<resources>
    <string name="login_practice">登入練習</string>
    <string name="enter_account">請輸入帳號</string>
    <string name="enter_password">請輸入密碼</string>
    <string name="remember_account_and_password">記住帳號密碼</string>
    <string name="login">登錄</string>
    <string name="account_and_password_require">帳號密碼必須輸入</string>
</resources>

※需要用到的字串,集中在這個檔案管理


※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="com.example.bruce_java.myapplication.MainActivity">
    
    <EditText
        android:id="@+id/account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/enter_account"
        android:layout_marginTop="80dp"/>
    
    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword"
        android:hint="@string/enter_password"
        android:layout_marginBottom="10dp"/>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <CheckBox
            android:id="@+id/cb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/remember_account_and_password"
            android:layout_alignParentLeft="true"/>
    
        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/login"
            android:layout_alignParentRight="true"
            android:onClick="login"/>
    </RelativeLayout>
</LinearLayout>

※模擬一個登入頁面


※AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bruce_java.myapplication20161022">
    
    <!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>-->
    <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/login_practice"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivityButton">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

※注意android:label本來是@string/app_name,我改了,要對應到strings.xml

※如果需要加權限,就打開註解的部分,當然還有很多


※MainActivity.java

public class MainActivity extends AppCompatActivity {
    EditText accText = null;
    EditText passText = null;
    CheckBox cb = null;
    final String fileName = "login.txt";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        accText = (EditText) findViewById(R.id.account);
        passText = (EditText) findViewById(R.id.password);
        cb = (CheckBox) findViewById(R.id.cb);
    
        Map<String, String> map = this.readAccountAndPassword();
        if (!map.isEmpty()) {
            accText.setText(map.get("account"));
            passText.setText(map.get("password"));
            cb.setChecked(true);
        } else {
            cb.setChecked(false);
        }
    }
    
    private Map<String, String> readAccountAndPassword() {
        Map<String, String> map = new HashMap<>();
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(super.getApplicationContext().openFileInput(fileName)));
            map.put("account", in.readLine());
            map.put("password", in.readLine());
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return map;
    }
    
    public void login(View view){
        String account = accText.getText().toString().trim();
        String password = passText.getText().toString().trim();
    
        if(TextUtils.isEmpty(account) || TextUtils.isEmpty(password)){
            Toast.makeText(getApplicationContext(), R.string.account_and_password_require, Toast.LENGTH_SHORT).show();
            return;
        } else {
            if(cb.isChecked()) {
                OutputStream out = null;
                try {
                    //data/data/com.example~~~/files
                    out = super.getApplicationContext().openFileOutput(fileName, super.MODE_PRIVATE);
                    out.write((account + "\r\n" + password).getBytes());
                } catch (FileNotFoundException fnfe) {
                    fnfe.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (out != null) {
                            out.close();
                            Toast.makeText(getApplicationContext(), "已儲存帳號和密碼", Toast.LENGTH_SHORT).show();
                        }
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }
                }
            }
        }
    }
}

※MODE_PRIVATE會寫入檔案,如果發現已有檔案會覆蓋,
如果改成MODE_APPEND,會附加資料在最後面

※readAccountAndPassword方法是讀;login方法是寫



※SharedPreferences 讀寫XML

從data/data/com.example~~~/shared_prefs資料夾裡,讀或寫
會自動加副檔名xml(不管你有沒有加xml,都會在後面多個.xml)
只有MainActivity.java和openFileOutput/openFileInput不一樣

※MainActivity.java

public class MainActivity extends AppCompatActivity {
    EditText accText = null;
    EditText passText = null;
    CheckBox cb = null;
    final String fileName = "login";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        accText = (EditText) findViewById(R.id.account);
        passText = (EditText) findViewById(R.id.password);
        cb = (CheckBox) findViewById(R.id.cb);
    
        Map<String, String> map = this.readAccountAndPassword();
        if (map.get("account") != null && map.get("password") != null) {
            accText.setText(map.get("account"));
            passText.setText(map.get("password"));
            cb.setChecked(true);
        } else {
            cb.setChecked(false);
        }
    }
    
    public void login(View view){
        String account = accText.getText().toString().trim();
        String password = passText.getText().toString().trim();
    
        if(TextUtils.isEmpty(account) || TextUtils.isEmpty(password)){
            Toast.makeText(getApplicationContext(), R.string.account_and_password_require, Toast.LENGTH_SHORT).show();
            return;
        } else {
            if(cb.isChecked()) {
                // data/data/com.example~~~/shared_prefs/login.xml
                // fileName後會自動加副檔名xml
                SharedPreferences sp = super.getSharedPreferences(fileName, super.MODE_PRIVATE);
                SharedPreferences.Editor editor = sp.edit();
                editor.putString("account", account);
                editor.putString("password", password);
                editor.commit();
                Toast.makeText(getApplicationContext(), "已儲存帳號和密碼", Toast.LENGTH_SHORT).show();
            }
        }
    }
    
    private Map<String, String> readAccountAndPassword() {
        Map<String, String> map = new HashMap<>();
        SharedPreferences sp = super.getSharedPreferences(fileName, super.MODE_PRIVATE);
        // 第二個參數是取不到時的預設值
        map.put("account", sp.getString("account", null));
        map.put("password", sp.getString("password", null));
        return map;
    }
}

※readAccountAndPassword方法是讀;login方法是寫

沒有留言:

張貼留言