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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 plain copy
  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 键。有如下值可 置: normal actionUnspecified actionNone actionGo actionSearch actionSend actionNext actionDone flagNoExtractUi     flagNoAccessoryAction flagNoEnterAction 。可用 ’|’ 设置多个。
    设置  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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值