Android LoginActivity 源代碼分析

本文是基於android4.0下的loginActivity Demo和android下的Webservice實現的。loginActivity是android4.0下的自帶演示例程,他自帶登錄界面、用戶名格式設定、輸入密碼和用戶名格式是否正確、用戶登錄時間進度條等功能,用戶可以在這個例程的基礎上延伸出自己login用戶登錄程序。在這裏我沒有對這個程序做過多的延伸,只是增加Webservice驗證用戶登錄的功能,使其成爲一個完整的網絡用戶登錄驗證的模塊程序。在這我會對這個Demo做全面的解析,使初學者可以理解並能夠使用這個Demo。
    一、準備工作(以下的準備步驟都在本人專欄裏有相應文章,可以參考下面的連接)
        ③下載 android的WebService項目包(初學者可以參考android專欄下的Webservice使用例程)。
    二、創建並理解android自帶loginActivity demo
        1、創建android項目,SDK版本爲API16、android4.1。然後一直next,在create Activity 中選擇loginActivity並將create activity選中。項目創建完成。
        2、loginActivity demo的各塊源碼理解
        ①activity_login.xml界面佈局代碼分析
[html] view plaincopy
  1. <merge xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     tools:context=".LoginActivity" >  
  4.   
  5.     <!-- Login progress -->  
  6.     <!-- merge與FrameLayout佈局相同,都是幀佈局,不同的是,當LayoutInflater遇到這個標籤時,它會跳過它,並將<merge />內的元素添加到<merge />的父元素裏。 -->  
  7.    
  8.     <!-- 這個線性佈局是驗證等待對話框的根元素,這個線性佈局包含一個環形進度條,和一個字符標籤 -->  
  9.     <!-- 設置子元素在這個佈局中心排布 -->  
  10.     <!-- 設置該佈局在父佈局及界面中心水平放置 -->  
  11.     <!-- 設置子佈局縱向佈局 -->  
  12.     <!-- 設置這個佈局界面隱藏不可見 -->  
  13.     <LinearLayout              
  14.         android:id="@+id/login_status"    
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_gravity="center"       
  18.         android:gravity="center_horizontal"   
  19.         android:orientation="vertical"        
  20.         android:visibility="gone" >            
  21.   
  22.         <ProgressBar  
  23.             style="?android:attr/progressBarStyleLarge"  
  24.             android:layout_width="wrap_content"  
  25.             android:layout_height="wrap_content"  
  26.             android:layout_marginBottom="8dp" />   
  27.   
  28.         <TextView  
  29.             android:id="@+id/login_status_message"  
  30.             android:layout_width="wrap_content"  
  31.             android:layout_height="wrap_content"  
  32.             android:layout_marginBottom="16dp"  
  33.             android:fontFamily="sans-serif-light"  
  34.             android:text="@string/login_progress_signing_in"  
  35.             android:textAppearance="?android:attr/textAppearanceMedium" />  
  36.     </LinearLayout>  
  37.   
  38.     <!-- Login form -->  
  39.     <!-- 根目錄爲滾動試圖 -->  
  40.     <ScrollView  
  41.         android:id="@+id/login_form"  
  42.         android:layout_width="match_parent"  
  43.         android:layout_height="match_parent" >  
  44.         <!-- 線性縱向排布 -->  
  45.         <LinearLayout  
  46.             style="@style/LoginFormContainer"  
  47.             android:orientation="vertical" >  
  48.              <!--郵箱輸入框  -->  
  49.             <!--hint:設置編輯框無輸入顯示,設置輸入類型爲Email型,設置爲一行、單行模式  -->  
  50.             <EditText  
  51.                 android:id="@+id/email"  
  52.                 android:layout_width="match_parent"  
  53.                 android:layout_height="wrap_content"  
  54.                 android:hint="@string/prompt_email"  
  55.                 android:inputType="textEmailAddress"  
  56.                 android:maxLines="1"  
  57.                 android:singleLine="true" />  
  58.             <!-- 密碼輸入框 -->  
  59.             <!-- imeActionLabel設置編輯文本“下一步”的顯示內容,imeActionId設置“下一步”的ID, 設置“完成”,設置輸入格式顯示***-->  
  60.             <EditText  
  61.                 android:id="@+id/password"  
  62.                 android:layout_width="match_parent"  
  63.                 android:layout_height="wrap_content"  
  64.                 android:hint="@string/prompt_password"  
  65.                 android:imeActionId="@+id/login"  
  66.                 android:imeActionLabel="@string/action_sign_in_short"  
  67.                 android:imeOptions="actionUnspecified"  
  68.                 android:inputType="textPassword"  
  69.                 android:maxLines="1"  
  70.                 android:singleLine="true" />  
  71.              <!-- 提交按鈕 -->  
  72.             <!--paddingLeft設置左邊距  -->  
  73.             <Button  
  74.                 android:id="@+id/sign_in_button"  
  75.                 android:layout_width="wrap_content"  
  76.                 android:layout_height="wrap_content"  
  77.                 android:layout_gravity="right"  
  78.                 android:layout_marginTop="16dp"  
  79.                 android:paddingLeft="32dp"  
  80.                 android:paddingRight="32dp"  
  81.                 android:text="@string/action_sign_in_register" />  
  82.         </LinearLayout>  
  83.     </ScrollView>  
  84.   
  85. </merge>  

 

②loginActivity.java源碼分析
[html] view plaincopy
  1. protected void onCreate(Bundle savedInstanceState) {  
  2.         super.onCreate(savedInstanceState);  
  3.         setContentView(R.layout.activity_login);  
  4.         // Set up the login form.  
  5.         //獲取引入的郵箱並顯示  
  6.         mEmail = getIntent().getStringExtra(EXTRA_EMAIL);  
  7.         mEmailView = (EditText) findViewById(R.id.email);  
  8.         mEmailView.setText(mEmail);  
  9.         //在密碼編輯界面判斷軟鍵盤的選擇,做對應操作  
  10.         mPasswordView = (EditText) findViewById(R.id.password);  
  11.         mPasswordView  
  12.                 .setOnEditorActionListener(new TextView.OnEditorActionListener() {  
  13.                     @Override  
  14.                     public boolean onEditorAction(TextView textView, int id,  
  15.                             KeyEvent keyEvent) {  
  16.                         if (id == R.id.login || id == EditorInfo.IME_NULL) {//判斷軟件盤選擇的內容  
  17.                             attemptLogin();  
  18.                             return true;  
  19.                         }  
  20.                         return false;  
  21.                     }  
  22.                 });  
  23.         mLoginFormView = findViewById(R.id.login_form);  
  24.         mLoginStatusView = findViewById(R.id.login_status);  
  25.         mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message);  
  26.         //提交按鍵響應處理  
  27.         findViewById(R.id.sign_in_button).setOnClickListener(  
  28.                 new View.OnClickListener() {  
  29.                     @Override  
  30.                     public void onClick(View view) {  
  31.                         attemptLogin();  
  32.                     }  
  33.                 });  
  34.     }  
                -----以上代碼是對界面相關設置
[java] view plaincopy
  1. public void attemptLogin() {  
  2.     if (mAuthTask != null) {  
  3.         return;  
  4.     }  
  5.     //設置輸入框的錯誤提示爲空  
  6.     mEmailView.setError(null);  
  7.     mPasswordView.setError(null);  
  8.     //獲取輸入框的郵箱和密碼  
  9.     mEmail = mEmailView.getText().toString();  
  10.     mPassword = mPasswordView.getText().toString();  
  11.     boolean cancel = false;  
  12.     View focusView = null;  
  13.     // 設置密碼輸入框的格式(不能爲空,不能小於4位)如果格式錯誤重新獲得焦點,並提示錯誤內容  
  14.     if (TextUtils.isEmpty(mPassword)) {  
  15.         mPasswordView.setError(getString(R.string.error_field_required));  
  16.         focusView = mPasswordView;  
  17.         cancel = true;  
  18.     } else if (mPassword.length() < 4) {  
  19.         mPasswordView.setError(getString(R.string.error_invalid_password));  
  20.         focusView = mPasswordView;  
  21.         cancel = true;  
  22.     }  
  23.     // 設置郵箱格式  
  24.     if (TextUtils.isEmpty(mEmail)) {  
  25.         mEmailView.setError(getString(R.string.error_field_required));  
  26.         focusView = mEmailView;  
  27.         cancel = true;  
  28.     } else if (!mEmail.contains("@")) {  
  29.         mEmailView.setError(getString(R.string.error_invalid_email));  
  30.         focusView = mEmailView;  
  31.         cancel = true;  
  32.     }  
  33.     if (cancel) {  
  34.         //如果格式錯誤,輸入框重新獲得輸入焦點  
  35.         focusView.requestFocus();  
  36.     } else {  
  37.         //如果輸入的格式正確,顯示驗證等待對話框,並啓動驗證線程  
  38.         mLoginStatusMessageView.setText(R.string.login_progress_signing_in);  
  39.         showProgress(true);  
  40.         mAuthTask = new UserLoginTask();  
  41.         mAuthTask.execute((Void) null);  
  42.     }  
  43. }  
                -----attemptLogin函數是登錄驗證的調用函數,按鍵和密碼框的響應時間調用attemptLogin來做用戶驗證,他主要的功能是驗證用戶輸入密碼和郵箱的格式的正確與否,如果格式錯誤,在輸入框中顯示格式錯誤信息類型,格式正確後,調用showProgress顯示用戶驗證延時等待對話框和啓動mAuthTask異步處理用戶信息驗證。
[java] view plaincopy
  1. @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)//指出應用程序的API版本  
  2. private void showProgress(final boolean show) {  
  3.     //獲取運行平臺的版本與應用的版本對比實現功能的兼容性  
  4.     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {  
  5.         int shortAnimTime = getResources().getInteger(  
  6.                 android.R.integer.config_shortAnimTime);//獲取系統定義的時間  
  7.   
  8.         mLoginStatusView.setVisibility(View.VISIBLE);//設置驗證對話框爲可顯  
  9.         mLoginStatusView.animate().setDuration(shortAnimTime)//設置動畫顯示時間  
  10.                 .alpha(show ? 1 : 0)//設置動畫漸變效果  
  11.                 .setListener(new AnimatorListenerAdapter() {  
  12.                     @Override  
  13.                     public void onAnimationEnd(Animator animation) {  
  14.                         mLoginStatusView.setVisibility(show ? View.VISIBLE  
  15.                                 : View.GONE);//跟據參數控制該控件顯示或隱藏  
  16.                     }  
  17.                 });  
  18.         mLoginFormView.setVisibility(View.VISIBLE);//設置輸入界面可顯  
  19.         mLoginFormView.animate().setDuration(shortAnimTime)  
  20.                 .alpha(show ? 0 : 1)  
  21.                 .setListener(new AnimatorListenerAdapter() {  
  22.                     @Override  
  23.                     public void onAnimationEnd(Animator animation) {  
  24.                         mLoginFormView.setVisibility(show ? View.GONE  
  25.                                 : View.VISIBLE);  
  26.                     }  
  27.                 });  
  28.     } else {  
  29.         mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);//跟據參數控制該控件顯示或隱藏  
  30.         mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);  
  31.     }  
  32. }  
                -----showProgress函數主要是用戶登錄驗證時界面的顯示工作,界面顯示一個等待對話框。在這個函數裏主要做了應用程序的API與系統平臺的API對比並處理,關於系統信息的調用學習請參考(Build相關屬性和調用系統信息的方法)。
[java] view plaincopy
  1. public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {  
  2.         @Override  
  3.         protected Boolean doInBackground(Void... params) {//後臺運行線程  
  4.             try {  
  5.                 //模擬用戶驗證耗時  
  6.                 Thread.sleep(2000);  
  7.             } catch (InterruptedException e) {  
  8.                 return false;  
  9.             }  
  10.   
  11.             for (String credential : DUMMY_CREDENTIALS) {//遍歷數組驗證自定義用戶及密碼  
  12.                 String[] pieces = credential.split(":");//分割字符串,將密碼個郵箱分離開  
  13.                 if (pieces[0].equals(mEmail)) {  
  14.                     return pieces[1].equals(mPassword);  
  15.                 }  
  16.             }  
  17.             return true;  
  18.         }  
  19.   
  20.         @Override  
  21.         protected void onPostExecute(final Boolean success) {//線程結束後的ui處理  
  22.             mAuthTask = null;  
  23.             showProgress(false);//隱藏驗證延時對話框  
  24.   
  25.             if (success) {  
  26.                 finish();  
  27.             } else {//密碼錯誤,輸入框獲得焦點,並提示錯誤  
  28.                 mPasswordView  
  29.                         .setError(getString(R.string.error_incorrect_password));  
  30.                 mPasswordView.requestFocus();  
  31.             }  
  32.         }  
  33.         //取消驗證  
  34.         @Override  
  35.         protected void onCancelled() {  
  36.             mAuthTask = null;  
  37.             showProgress(false);  
  38.         }  
  39.     }  
  40. }  
                -----UserLoginTask異步方法,該方法主要負責用戶後臺驗證程序,在這裏主要做了用戶登錄信息和預定義信息驗證,並做驗證後的操作。關於異步的學習可以參考AsyncTask(異步)和Thread(線程)的使用與對比.

 注意事項:這個demo爲模塊界面,其本身不是系統的默認啓動界面,要想程序正常工作,

要在AndroidManifest.xml中添加如下代碼

[html] view plaincopy
  1. <intent-filter>  
  2.   
  3.             <action android:name="android.intent.action.MAIN" />  
  4.   
  5.             <category android:name="android.intent.category.LAUNCHER" />  
  6.   
  7.         </intent-filter>  
三、添加WebService用戶登錄驗證代碼

  1、添加用戶上網權限
                在AndroidManifest.xml中添加用戶權限,添加如下代碼使用戶有上網的權限。
<uses-permission android:name="android.permission.INTERNET"/>
         2、定義Webservice的命名空間和服務地址以及Webservice方法,定義android下webservice的相關對象。
            Webservice的服務地址和命名空間及內部方法的獲得,請參考(Android 使用.net開發的webservice做用戶登錄驗證)中的WebService解析。關於android下webservice的使用請參考()webservice的入門學習。
            定義Webservice相關函數代碼
[html] view plaincopy
  1. /*******************************************/  
  2. final static String SERVICE_NS = "http://tempuri.org/"; //Webservice所在命名空間  
  3. final static String SERVICE_URL = "http://192.168.1.213:9006/WS_Base.asmx";//Webservice服務地址  
  4. final static String methodName = "AuthenticateLogin";//要使用的接口函數  
  5.   
  6. private HttpTransportSE ht; //該對象用於調用WebService操作  
  7. private SoapSerializationEnvelope envelope;//上一個類信息的載體  
  8. private SoapObject soapObject; //將參數傳遞給WebService  
  9. /**********************************************/  
        3、刪除attemptLogin方法中的關於用戶郵件驗證的部分,(程序中有一些要刪除的部分,根據理解)。
        4、在attemptLogin方法中更改異步方法mAuthTask參數的傳遞類型。
         mAuthTask = new UserLoginTask();
            mAuthTask.execute(mEmail,mPassword);
        5、重新修改異步方法實現用戶登錄驗證(關於異步的學習可以參考AsyncTask(異步)和Thread(線程)的使用與對比.)
            
[java] view plaincopy
  1. public class UserLoginTask extends AsyncTask<String, Void, Boolean> {  
  2.     @Override  
  3.     protected Boolean doInBackground(String... params) {  
  4.         // TODO: attempt authentication against a network service.  
  5.         //set webservices attribute  
  6.         /***********************************************/  
  7.         //創建HttpTransportSE對象,該對象用於調用WebService操作  
  8.         ht = new HttpTransportSE(SERVICE_URL);  
  9.         ht.debug = true;  
  10.         //創建SoapSerializationEnvelope對象,它是HttpTransportSE調用WebService時消息  
  11.         //的載體;客戶端需要傳入的參數,需要通過SoapSerializationEnvelope對象的bodyOut屬性  
  12.         //傳給服務器;服務器響應生成的SOAP消息也通過該對象的bodyIn屬性來獲取。  
  13.         envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);//指明SOPA規範  
  14.         //創建SoapObject對象,創建對象時需要傳入調用Web Service的命名空間、方法名。  
  15.         soapObject = new SoapObject(SERVICE_NS, methodName);  
  16.           
  17.         /************************************************************/  
  18.         //SoapObject 對象的addProperty(String name,Object value)方法將參數傳遞給服務端  
  19.         //該方法的name參數指定參數名;value參數指定參數值。  
  20.         //如果方法存在多個參數,多次調用addProperty即可。  
  21.         soapObject.addProperty("userName",params[0]);  
  22.         soapObject.addProperty("password",params[1]);  
  23.         envelope.bodyOut = soapObject;  
  24.         //設置WebService的開發類型  
  25.         envelope.dotNet = true;  
  26.         try   
  27.         {  
  28.             //調用遠程WebService,call()方法的參數意義 第一個參數:命名空間+方法名,  
  29.             //第二個參數:SoapSerializationEnvelope對象  
  30.             ht.call(SERVICE_NS+methodName, envelope);  
  31.             if(envelope.getResponse()!=null)  
  32.             {  
  33.                 //SoapSerializationEnvelope對象的bodyIn屬性返回一個SoapObject對象,  
  34.                 //該對象就代表了WebService的返回消息。  
  35.                 //WebService在服務器端返回值是String類型的數值的時候使用Object代替SoapObject  
  36.                 SoapObject result = (SoapObject)envelope.bodyIn;  
  37.                 Object detail1 = (Object) result.getProperty(0);                      
  38.                 return detail1.toString().equals("true");  
  39.             }  
  40.             return false;  
  41.         }  
  42.         catch (IOException e)  
  43.         {  
  44.             e.printStackTrace();  
  45.         }  
  46.         catch (XmlPullParserException e) {  
  47.             // TODO: handle exception  
  48.             e.printStackTrace();  
  49.         }  
  50.         return false;  
  51.     }  
  52.     @Override  
  53.     protected void onPostExecute(final Boolean success) {  
  54.         mAuthTask = null;  
  55.         showProgress(false);  
  56.   
  57.         if (success) {  
  58.             finish();  
  59.         } else {  
  60.             mPasswordView  
  61.                     .setError(getString(R.string.error_incorrect_password));  
  62.             mPasswordView.requestFocus();//設置密碼框獲得焦點  
  63.         }  
  64.     }  
  65.     @Override  
  66.     protected void onCancelled() {  
  67.         mAuthTask = null;  
  68.         showProgress(false);  
  69.     }  
  70. }  

總結:“關於android loginDemo +WebService用戶登錄驗證”實驗中遇到的問題及知識點總結
1、@Override是什麼意思
沒什麼用,這是IDE編輯器爲你自動加上去的一個標誌,告訴你說下面這個方法是從父類/接口 繼承過來的,需要你重寫一次。
2、@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)。
    說明應用的API版本,在代碼中獲得平臺的SDK版本與這個版本對比,在代碼中判斷應用與平臺的兼容性。
    關於獲取及使用用戶信息的Bulid列的介紹及使用說明,參考android專欄
3、EditText:
    ①android:imeOptions 置軟鍵盤的Enter鍵。有如下值可置:normalactionUnspecifiedactionNoneactionGoactionSearchactionSendactionNextactionDoneflagNoExtractUi    flagNoAccessoryActionflagNoEnterAction。可用’|’設置多個。
    設置 android:imeOptions="actionDone" ,軟鍵盤下方變成“完成”,點擊後光標保持在原來的輸入框上,並且軟鍵盤關閉。
       android:imeOptions="actionSend" 軟鍵盤下方變成“發送”,點擊後光標移動下一個。
    ②setError(string);設置編輯框的提示,例如setError(“密碼不能爲空”);
    ③focusView.requestFocus();設置編輯框獲得焦點,實例:
        focusView = mEmailView;
        focusView.requestFocus();
View:
    ①setVisibility設置空間在界面的可見性
1.View.VISIBLE,常量值爲0,意思是可見的
2.View.INVISIBLE,常量值是4,意思是不可見的
3.View.GONE,常量值是8,意思是不可見的,並且不佔用佈局空間
 
XML:
    ①Android:Layout_gravity    設置該組件在其容器中的對其方式。
           Android:Layout_gravity=” center“(在組件中心)。
        android:gravity     設置組件的子組件在組件中的位置,可以同時制定多種對齊方式的組合
            android:gravity="left|center_vertical"代表出現在屏幕左邊,而且垂直居中。
    ②android:inputType 設置文本的輸入類型
        android:inputType =“textPassword”設置輸入類型爲密碼。
    ③<b> 標籤呈現粗體文本效果:
         <string name="action_sign_in_register"><b>Sign in</b> or register</string>
String 類
        ①String.split
            根據給定的正則表達式的匹配來拆分此字符串。
本文轉自:http://blog.csdn.net/meng425841867/article/details/8501848

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章