上鎖功能相當簡單,基本上只需要 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,代表沒有鎖,可以直接輸入密碼上鎖
結果為