- <merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:context=".LoginActivity" >
- <!-- Login progress -->
- <!-- merge與FrameLayout佈局相同,都是幀佈局,不同的是,當LayoutInflater遇到這個標籤時,它會跳過它,並將<merge />內的元素添加到<merge />的父元素裏。 -->
- <!-- 這個線性佈局是驗證等待對話框的根元素,這個線性佈局包含一個環形進度條,和一個字符標籤 -->
- <!-- 設置子元素在這個佈局中心排布 -->
- <!-- 設置該佈局在父佈局及界面中心水平放置 -->
- <!-- 設置子佈局縱向佈局 -->
- <!-- 設置這個佈局界面隱藏不可見 -->
- <LinearLayout
- android:id="@+id/login_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center_horizontal"
- android:orientation="vertical"
- android:visibility="gone" >
- <ProgressBar
- style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dp" />
- <TextView
- android:id="@+id/login_status_message"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:fontFamily="sans-serif-light"
- android:text="@string/login_progress_signing_in"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- </LinearLayout>
- <!-- Login form -->
- <!-- 根目錄爲滾動試圖 -->
- <ScrollView
- android:id="@+id/login_form"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <!-- 線性縱向排布 -->
- <LinearLayout
- style="@style/LoginFormContainer"
- android:orientation="vertical" >
- <!--郵箱輸入框 -->
- <!--hint:設置編輯框無輸入顯示,設置輸入類型爲Email型,設置爲一行、單行模式 -->
- <EditText
- android:id="@+id/email"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/prompt_email"
- android:inputType="textEmailAddress"
- android:maxLines="1"
- android:singleLine="true" />
- <!-- 密碼輸入框 -->
- <!-- imeActionLabel設置編輯文本“下一步”的顯示內容,imeActionId設置“下一步”的ID, 設置“完成”,設置輸入格式顯示***-->
- <EditText
- android:id="@+id/password"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/prompt_password"
- android:imeActionId="@+id/login"
- android:imeActionLabel="@string/action_sign_in_short"
- android:imeOptions="actionUnspecified"
- android:inputType="textPassword"
- android:maxLines="1"
- android:singleLine="true" />
- <!-- 提交按鈕 -->
- <!--paddingLeft設置左邊距 -->
- <Button
- android:id="@+id/sign_in_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:layout_marginTop="16dp"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:text="@string/action_sign_in_register" />
- </LinearLayout>
- </ScrollView>
- </merge>
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_login);
- // Set up the login form.
- //獲取引入的郵箱並顯示
- mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
- mEmailView = (EditText) findViewById(R.id.email);
- mEmailView.setText(mEmail);
- //在密碼編輯界面判斷軟鍵盤的選擇,做對應操作
- mPasswordView = (EditText) findViewById(R.id.password);
- mPasswordView
- .setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView textView, int id,
- KeyEvent keyEvent) {
- if (id == R.id.login || id == EditorInfo.IME_NULL) {//判斷軟件盤選擇的內容
- attemptLogin();
- return true;
- }
- return false;
- }
- });
- mLoginFormView = findViewById(R.id.login_form);
- mLoginStatusView = findViewById(R.id.login_status);
- mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message);
- //提交按鍵響應處理
- findViewById(R.id.sign_in_button).setOnClickListener(
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- attemptLogin();
- }
- });
- }
- public void attemptLogin() {
- if (mAuthTask != null) {
- return;
- }
- //設置輸入框的錯誤提示爲空
- mEmailView.setError(null);
- mPasswordView.setError(null);
- //獲取輸入框的郵箱和密碼
- mEmail = mEmailView.getText().toString();
- mPassword = mPasswordView.getText().toString();
- boolean cancel = false;
- View focusView = null;
- // 設置密碼輸入框的格式(不能爲空,不能小於4位)如果格式錯誤重新獲得焦點,並提示錯誤內容
- if (TextUtils.isEmpty(mPassword)) {
- mPasswordView.setError(getString(R.string.error_field_required));
- focusView = mPasswordView;
- cancel = true;
- } else if (mPassword.length() < 4) {
- mPasswordView.setError(getString(R.string.error_invalid_password));
- focusView = mPasswordView;
- cancel = true;
- }
- // 設置郵箱格式
- if (TextUtils.isEmpty(mEmail)) {
- mEmailView.setError(getString(R.string.error_field_required));
- focusView = mEmailView;
- cancel = true;
- } else if (!mEmail.contains("@")) {
- mEmailView.setError(getString(R.string.error_invalid_email));
- focusView = mEmailView;
- cancel = true;
- }
- if (cancel) {
- //如果格式錯誤,輸入框重新獲得輸入焦點
- focusView.requestFocus();
- } else {
- //如果輸入的格式正確,顯示驗證等待對話框,並啓動驗證線程
- mLoginStatusMessageView.setText(R.string.login_progress_signing_in);
- showProgress(true);
- mAuthTask = new UserLoginTask();
- mAuthTask.execute((Void) null);
- }
- }
- @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)//指出應用程序的API版本
- private void showProgress(final boolean show) {
- //獲取運行平臺的版本與應用的版本對比實現功能的兼容性
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
- int shortAnimTime = getResources().getInteger(
- android.R.integer.config_shortAnimTime);//獲取系統定義的時間
- mLoginStatusView.setVisibility(View.VISIBLE);//設置驗證對話框爲可顯
- mLoginStatusView.animate().setDuration(shortAnimTime)//設置動畫顯示時間
- .alpha(show ? 1 : 0)//設置動畫漸變效果
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLoginStatusView.setVisibility(show ? View.VISIBLE
- : View.GONE);//跟據參數控制該控件顯示或隱藏
- }
- });
- mLoginFormView.setVisibility(View.VISIBLE);//設置輸入界面可顯
- mLoginFormView.animate().setDuration(shortAnimTime)
- .alpha(show ? 0 : 1)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLoginFormView.setVisibility(show ? View.GONE
- : View.VISIBLE);
- }
- });
- } else {
- mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);//跟據參數控制該控件顯示或隱藏
- mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
- }
- }
- public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
- @Override
- protected Boolean doInBackground(Void... params) {//後臺運行線程
- try {
- //模擬用戶驗證耗時
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- return false;
- }
- for (String credential : DUMMY_CREDENTIALS) {//遍歷數組驗證自定義用戶及密碼
- String[] pieces = credential.split(":");//分割字符串,將密碼個郵箱分離開
- if (pieces[0].equals(mEmail)) {
- return pieces[1].equals(mPassword);
- }
- }
- return true;
- }
- @Override
- protected void onPostExecute(final Boolean success) {//線程結束後的ui處理
- mAuthTask = null;
- showProgress(false);//隱藏驗證延時對話框
- if (success) {
- finish();
- } else {//密碼錯誤,輸入框獲得焦點,並提示錯誤
- mPasswordView
- .setError(getString(R.string.error_incorrect_password));
- mPasswordView.requestFocus();
- }
- }
- //取消驗證
- @Override
- protected void onCancelled() {
- mAuthTask = null;
- showProgress(false);
- }
- }
- }
注意事項:這個demo爲模塊界面,其本身不是系統的默認啓動界面,要想程序正常工作,
要在AndroidManifest.xml中添加如下代碼
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- /*******************************************/
- final static String SERVICE_NS = "http://tempuri.org/"; //Webservice所在命名空間
- final static String SERVICE_URL = "http://192.168.1.213:9006/WS_Base.asmx";//Webservice服務地址
- final static String methodName = "AuthenticateLogin";//要使用的接口函數
- private HttpTransportSE ht; //該對象用於調用WebService操作
- private SoapSerializationEnvelope envelope;//上一個類信息的載體
- private SoapObject soapObject; //將參數傳遞給WebService
- /**********************************************/
- public class UserLoginTask extends AsyncTask<String, Void, Boolean> {
- @Override
- protected Boolean doInBackground(String... params) {
- // TODO: attempt authentication against a network service.
- //set webservices attribute
- /***********************************************/
- //創建HttpTransportSE對象,該對象用於調用WebService操作
- ht = new HttpTransportSE(SERVICE_URL);
- ht.debug = true;
- //創建SoapSerializationEnvelope對象,它是HttpTransportSE調用WebService時消息
- //的載體;客戶端需要傳入的參數,需要通過SoapSerializationEnvelope對象的bodyOut屬性
- //傳給服務器;服務器響應生成的SOAP消息也通過該對象的bodyIn屬性來獲取。
- envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);//指明SOPA規範
- //創建SoapObject對象,創建對象時需要傳入調用Web Service的命名空間、方法名。
- soapObject = new SoapObject(SERVICE_NS, methodName);
- /************************************************************/
- //SoapObject 對象的addProperty(String name,Object value)方法將參數傳遞給服務端
- //該方法的name參數指定參數名;value參數指定參數值。
- //如果方法存在多個參數,多次調用addProperty即可。
- soapObject.addProperty("userName",params[0]);
- soapObject.addProperty("password",params[1]);
- envelope.bodyOut = soapObject;
- //設置WebService的開發類型
- envelope.dotNet = true;
- try
- {
- //調用遠程WebService,call()方法的參數意義 第一個參數:命名空間+方法名,
- //第二個參數:SoapSerializationEnvelope對象
- ht.call(SERVICE_NS+methodName, envelope);
- if(envelope.getResponse()!=null)
- {
- //SoapSerializationEnvelope對象的bodyIn屬性返回一個SoapObject對象,
- //該對象就代表了WebService的返回消息。
- //WebService在服務器端返回值是String類型的數值的時候使用Object代替SoapObject
- SoapObject result = (SoapObject)envelope.bodyIn;
- Object detail1 = (Object) result.getProperty(0);
- return detail1.toString().equals("true");
- }
- return false;
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- catch (XmlPullParserException e) {
- // TODO: handle exception
- e.printStackTrace();
- }
- return false;
- }
- @Override
- protected void onPostExecute(final Boolean success) {
- mAuthTask = null;
- showProgress(false);
- if (success) {
- finish();
- } else {
- mPasswordView
- .setError(getString(R.string.error_incorrect_password));
- mPasswordView.requestFocus();//設置密碼框獲得焦點
- }
- }
- @Override
- protected void onCancelled() {
- mAuthTask = null;
- showProgress(false);
- }
- }
總結:“關於android loginDemo +WebService用戶登錄驗證”實驗中遇到的問題及知識點總結
1.View.VISIBLE,常量值爲0,意思是可見的2.View.INVISIBLE,常量值是4,意思是不可見的3.View.GONE,常量值是8,意思是不可見的,並且不佔用佈局空間