上鎖功能相當簡單,基本上只需要 EditText 和 SharedPreferences(也可以使用其它的儲存類別如 fileoutputstream,SQLite) 就能完成,,不過為了操作的方便,我還加上了 button 和 textview ,基本介面如下
開鎖畫面
輸入密碼畫面
而實作原理也相當簡單,為了不把主流程複雜化,我把解鎖(UnLock_Flow.java)和加鎖(Lock_Flow.java)分開成2個類別,首先在主流程開始前先判斷是否有密碼鎖,有就先進解鎖,沒有就直接開始主流程,而在主流程中會有個選項是加入密碼鎖的選擇,點選進入 Lock_Flow.java,相當簡單吧
首先在主流程中判斷的方法如下
void lock() { // get data for accountdetail SharedPreferences sp = getSharedPreferences("bcn", 0); // get accountdetail count String passstr = sp.getString("adlock", ""); // no lock if(passstr.equals("")){ } //lock exist else { //call Lock_Flow Intent inte = new Intent(); inte.setClass(All_List.this, UnLock_Flow.class); startActivityForResult(inte, 3); overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit); } }
其中 SharedPreferences 的用法請參考這篇,本篇不再多加詳述
第 9 行判斷內容是否為空,是的話代表沒有密碼鎖直接進入主流程,否的話就呼叫解鎖類別(16 ~ 20 行)
解鎖類別(UnLock_Flow.java)如下
package com.example.helloworld; import FoXxLib.FP; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; @SuppressLint("NewApi") public class UnLock_Flow extends Activity { EditText et; Button byes; Button bno; TextView tv; int tryNum = 2; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initXml(); } void initXml() { setContentView(R.layout.unlockflow); tv = (TextView) findViewById(R.id.textView1); tv.setText("請輸入密碼解鎖"); et = (EditText) findViewById(R.id.username_edit); et.setHint("輸入密碼"); byes = (Button) findViewById(R.id.buttonYes); byes.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub checkPassWord(); } }); bno = (Button) findViewById(R.id.buttonNo); bno.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // use AlertDialog AlertDialog ad = new AlertDialog.Builder(UnLock_Flow.this, AlertDialog.THEME_TRADITIONAL).create(); ad.setTitle("警告!!");// 設定警告標題 ad.setMessage("確定離開程序??"); ad.setButton2("確定", new DialogInterface.OnClickListener() {// 設定按鈕2 @Override public void onClick(DialogInterface dialog, int which) { // 點選按鈕2後執行的動作 finishEdit(1); } }); ad.setButton("取消", new DialogInterface.OnClickListener() {// 設定按鈕2 @Override public void onClick(DialogInterface dialog, int which) { // 點選按鈕2後執行的動作 } }); ad.setCanceledOnTouchOutside(true);// 當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true ad.setCancelable(true);// 當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true ad.show(); } }); } void checkPassWord() { if (et.getText() == null) { // use Toast tryNum--; Toast.makeText(UnLock_Flow.this, "未輸入密碼!!!" + "還剩" + tryNum + "次", Toast.LENGTH_SHORT).show(); et.setText(""); } else { String tempstr = et.getText().toString(); // get data for accountdetail SharedPreferences sp = getSharedPreferences("bcn", 0); // get accountdetail count String passstr = sp.getString("adlock", ""); if (tempstr.equals(passstr)) { Toast.makeText(UnLock_Flow.this, "密碼正確!!!", Toast.LENGTH_SHORT) .show(); finishEdit(0); } else { Toast.makeText(UnLock_Flow.this, "密碼錯誤!!!" + "還剩" + tryNum + "次", Toast.LENGTH_SHORT) .show(); tryNum--; } } if (tryNum < 0) { finishEdit(1); } } public boolean onKeyDown(int keycode, KeyEvent event) { FP.p("keycode:" + keycode); FP.p("event:" + event.getAction()); finishEdit(1); switch (keycode) { // menu key case 82: break; } return super.onKeyDown(keycode, event); } /** * * @param result * 0 ok */ void finishEdit(int result) { if (result == 0) { UnLock_Flow.this.setResult(0); UnLock_Flow.this.finish(); overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit); } else if (result == 1) { UnLock_Flow.this.setResult(1); UnLock_Flow.this.finish(); } } }
其中比較重要的為 101 行的 checkPassWord() 方法,會取得 在 et 中輸入的字串內容並與 passstr 字串做比較(120行),相同則解鎖成功(finishEdit(0)),失敗則嘗試次數減少,當嘗試次數減為 0 ,那麼會直接回到主程序再結束 (finishEdit(1))
以上是解鎖的部分,接下來是上鎖的部分,在主程序中會有個按鈕,用來觸發加鎖動作,如下
//call Lock_Flow Intent inte = new Intent(); inte.setClass(All_List.this, Lock_Flow.class); startActivityForResult(inte, 4); overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
接著是 Lock_Flow.java的內容,必須注意在沒有上鎖的情況下,可以直接設定密碼,完成上鎖,但相反的若已經有上鎖過,則必須先輸入原先的密碼以解鎖,再上鎖,如下
package com.example.helloworld; import FoXxLib.FP; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; @SuppressLint("NewApi") public class Lock_Flow extends Activity{ EditText et; Button byes; Button bno; TextView tv; int tryNum =2; //0:lock exist 1:no lock int flow =0; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); initXml(); } void initXml(){ setContentView(R.layout.lockflow); tv = (TextView)findViewById(R.id.textView1); // get data for accountdetail SharedPreferences sp = getSharedPreferences("bcn", 0); // get accountdetail count String passstr = sp.getString("adlock", ""); //no lock if(passstr.equals("")){ flow =1; tv.setText("請輸入密碼:"); } //lock exist else{ flow =0; tv.setText("請輸入原始密碼:"); } et = (EditText)findViewById(R.id.username_edit); et.setHint("輸入密碼"); byes = (Button)findViewById(R.id.buttonYes); byes.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub checkPassWord(); } }); bno = (Button)findViewById(R.id.buttonNo); bno.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub //use AlertDialog AlertDialog ad = new AlertDialog.Builder(Lock_Flow.this,AlertDialog.THEME_TRADITIONAL).create(); ad.setTitle("警告!!");//設定警告標題 ad.setMessage("未上鎖,確定返回程序??"); ad.setButton2("確定", new DialogInterface.OnClickListener() {// 設定按鈕2 @Override public void onClick(DialogInterface dialog, int which) { // 點選按鈕2後執行的動作 finishEdit(1); } }); ad.setButton("取消", new DialogInterface.OnClickListener() {// 設定按鈕2 @Override public void onClick(DialogInterface dialog, int which) { // 點選按鈕2後執行的動作 } }); ad.setCanceledOnTouchOutside(true);//當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true ad.setCancelable(true);//當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true ad.show(); } }); } void checkPassWord(){ if(flow==0){ if(et.getText().toString().equals("")){ // use Toast Toast.makeText(Lock_Flow.this, "未輸入密碼!!!"+"還剩"+tryNum+"次",Toast.LENGTH_SHORT).show(); tryNum--; et.setText(""); } else{ String tempstr = et.getText().toString(); // get data for accountdetail SharedPreferences sp = getSharedPreferences("bcn", 0); // get accountdetail count String passstr = sp.getString("adlock",""); if(tempstr.equals(passstr)){ Toast.makeText(Lock_Flow.this, "密碼正確!!!",Toast.LENGTH_SHORT).show(); flow =1; tv.setText("輸入新密碼:"); } else{ Toast.makeText(Lock_Flow.this, "密碼錯誤!!!"+"還剩"+tryNum+"次",Toast.LENGTH_SHORT).show(); tryNum--; } } if(tryNum<0){ //use AlertDialog AlertDialog ad = new AlertDialog.Builder(Lock_Flow.this,AlertDialog.THEME_TRADITIONAL).create(); ad.setTitle("更改密碼失敗!!");//設定警告標題 ad.setMessage("原始密碼不正確"); ad.setButton("返回", new DialogInterface.OnClickListener() {// 設定按鈕2 @Override public void onClick(DialogInterface dialog, int which) { finishEdit(0); } }); ad.setCanceledOnTouchOutside(false);//當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true ad.setCancelable(false);//當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true ad.show(); } } else if(flow==1){ if(et.getText().toString().equals("")){ // use Toast Toast.makeText(Lock_Flow.this, "未輸入密碼!!!",Toast.LENGTH_SHORT).show(); et.setText(""); } else{ String tempstr = et.getText().toString(); // get data for accountdetail SharedPreferences sp = getSharedPreferences("bcn", 0); SharedPreferences.Editor spe = sp.edit(); spe.putString("adlock", tempstr);// for more putXXX spe.commit(); //use AlertDialog AlertDialog ad = new AlertDialog.Builder(Lock_Flow.this,AlertDialog.THEME_TRADITIONAL).create(); ad.setTitle("上鎖完成!!");//設定警告標題 ad.setMessage("密碼為"+tempstr); ad.setButton("返回", new DialogInterface.OnClickListener() {// 設定按鈕2 @Override public void onClick(DialogInterface dialog, int which) { finishEdit(1); } }); ad.setCanceledOnTouchOutside(false);//當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true ad.setCancelable(false);//當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true ad.show(); } } } public boolean onKeyDown(int keycode, KeyEvent event){ FP.p("keycode:"+keycode); FP.p("event:"+event.getAction()); finishEdit(1); switch(keycode){ // menu key case 82: break; } return super.onKeyDown(keycode, event); } /** * * @param result 0 ok */ void finishEdit(int result){ if(result==0){ Lock_Flow.this.setResult(0); Lock_Flow.this.finish(); overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit); } else if(result==1){ Lock_Flow.this.setResult(1); Lock_Flow.this.finish(); overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit); } } }
第 30 行 flow=0代表已經有鎖, 必須先解鎖,而flow=1,代表沒有鎖,可以直接輸入密碼上鎖
結果為