Android通過ksoap2調用.net(c#)的webservice


近段時間終於全面向Android平台進軍,但是在進入的時候,的確遇到很多問題,即使在調用WebService也遇到了不少的問題,在一番系統的學習過後,終於明白了個大概,現將學習的心得寫下,與所有跟我一樣剛入門的菜菜分享。

本人開發環境為Android Studio,如用Eclipse的童鞋請參照參照。

■下載 ksoap2-android 包

http://code.google.com/p/ksoap2-android/wiki/HowToUse?tm=2下載最新版的“ksoap2-android”,我現時使用的版本為:“ksoap2-android-assembly-3.0.0-RC.4-jar-with-dependencies.jar”

■引用包

下載後,將類庫復制到“libs” 文件下。如果Eclipse的童鞋到這里引用就完事了,但於Android Studio的就還沒有完,因為Android Studio使用的是gradle,故還需要對引用進行聲明。找到build.gradle文件(於項目的底部),打開於dependencies節點里,添加代碼:

dependencies {
    compile 'com.android.support:support-v4:13.0.+'
    
   //添加以下代碼以聲明類庫的引用
    compile files('libs/ksoap2-android-assembly-3.0.0-RC.4-jar-with-dependencies.jar')
}

下面開始我以一個登錄的例子來講解整個webserive的調用過程
layout_login中有兩個EditText控件,一個按鈕,登錄界面最基本的配置。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center|center_horizontal|center_vertical"
              android:orientation="vertical"
              android:background="#6AA7D2">

    <LinearLayout
            android:id="@+id/Layout_Input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="15dp"
            android:layout_marginBottom="0dp"
            android:orientation="vertical">

        <EditText
                android:id="@+id/Txt_Name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="text"
                android:hint="用戶名" />

        <EditText
                android:id="@+id/Txt_Password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textPassword"
                android:hint="密碼" />
    </LinearLayout>

    <LinearLayout
            android:id="@+id/Layout_Button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp">

        <Button
                android:id="@+id/Btn_Login"
                android:layout_weight="1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="登錄"
                android:onClick="Btn_Login_OnClick" />

    </LinearLayout>

</LinearLayout>

當點擊登錄Button時,執行以下事件 

public void Btn_Login_OnClick(View view) {
        loginName = ControlHelper.GetText(this, R.id.Txt_Name);
        loginPassword = ControlHelper.GetText(this, R.id.Txt_Password);

        if (loginName.equals("")) {
            MessageHelper.AlertDialog(this, "操作提示","用戶名不能為空."));
            findViewById(R.id.Txt_Name).requestFocus();
            return;
        }
view.setEnabled(
false); progressDialog = ProgressDialog.show(this,"Loading...","Please wait...",true,false); Thread thread = new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(1000); Login(loginName, loginPassword); } }); thread.start(); }

說明:由於Android4.0以後主線程為了線程安全,訪問網絡不能由主線程進,只能由子線程訪問,另外像.net的winform一樣,子線程不能控制UI,所有的UI都必需由主線程控制,所以所有的什麽提示框,等候框都必需由主線程去操作。所以上面的代碼中,Login的方法是在新開的子線程中完成的。

而Runnable就是一個Thread要實現的接口,此接口中有一個run()方法,當線程執行start()方法時,就會自動調用Thread的Runnable接口中的run()方法。所以我們要子線程執行的所有代碼都在run()里完成。

順帶一提的就是,子線程讀取UI上控件的值是沒有限制的,所以如果想在子程線中讀取UI,直接讀取就可以了。

但於子線程又是怎樣跟主線程溝通的呢?這就要提到另外兩個東東就是Handler跟Message了。

下面先看一看Login方法里面的代碼

private void Login(String name,String psw)
    {
        Message msg = new Message();

        try
        {
       //聲明Service的空間命名,.net默認為 http://tempuri.org/
       //第二個參數是要調用的方法 SoapObject so
= new SoapObject(this.getString(R.string.webservice_namespace), "Login");

        //設置調用Service需要傳入的兩個參數,聞說參數名可以不正確,但順序必需要正確 so.addProperty(
"accountName", name); so.addProperty("password", psw);
       // 設置調用WebService方法的SOAP請求信息,並指定SOAP的版本 SoapSerializationEnvelope envelope
= new SoapSerializationEnvelope(SoapEnvelope.VER12); envelope.bodyOut = so;

       // 設置是否調用的是dotNet開發的WebService envelope.dotNet
= true;

       // 設置Service所使用的URL String url
= this.getString(R.string.webservice_domain) + this.getString(R.string.webservice_url_logic); HttpTransportSE ht = new HttpTransportSE(url); ht.call(null, envelope); if (envelope.getResponse()!=null) {
          //接收返回的對象 SoapObject responseSO
= (SoapObject)envelope.getResponse(); Boolean succeed = Boolean.parseBoolean(responseSO.getProperty("Succeed").toString()); if(!succeed) { msg.obj = responseSO.getProperty("Message").toString(); msg.what = 0; } else { msg.obj = responseSO.getProperty("ReturnObject"); msg.what = 1; } } } catch (Exception ex) { msg.obj = ex.getMessage(); msg.what = -1; } finally { handler.sendMessage(msg); } }

我先講講我們的ksoap2是如何使用,再去講解Message與Handler。

上面的注釋都寫得很清楚了,在這里我提一提,在獲取接收的對象時,有兩種方法:

1. envelope.bodyIn

2.envelope.getResponse();

我選用的是第二種方法,因為我發現可以很好轉換回一個SoapObject,可能bodyIn都可以,但我沒有深入的研究,沒有發言權,有興趣又好學的同學們可以研究一下,記得研究完跟我說一聲。

別外值得一提如果你的Service返回的是一個對象,在ksoap2里,你的對象依然是一個SoapObject,你必須要寫代碼自已轉換,後面我還會有文章另外介紹。

下面再講如何,通知主線程,我所獲取得的返回結果了,大家看到,於Login方法中一開始就定義了一個Message的對象,其實這個對象就是用於線程之間通訊所使用的,姑且先這樣理解。

他有一個obj的屬性與一個what的屬性,obj用於存放通訊的數據,what是用於存放一個標志,為什麽需要這個標志呢?因為你Message可能有好多種狀態情況,what就是為了區分這些狀態而存在,如果你還是有不明白的,可能看了以下的代碼,或許會對你的了解有所幫助。

Handler接收Message

private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            findViewById(R.id.Btn_Login).setEnabled(true);
            progressDialog.dismiss();
            switch (msg.what)
            {
                case -1:
                    //exception
                    MessageHelper.AlertDialog(Activity_Main.this, "異常提示", msg.obj.toString());
                    break;
                case 0:
                    //fail
                    MessageHelper.AlertDialog(Activity_Main.this, "錯誤提示", msg.obj.toString());
                    break;
                case 1:
                    //login success
                    MessageHelper.AlertDialog(Activity_Main.this, "操作提示", "登錄成功。");

            break;

default: break; } } };

最後是需要在activity中定義一個Handler對象,並實現handleMessage的方法就可以。這樣整個調用Webservice的過程就完成了。

但是這里面還差一點小小的動作,就是由於你的程序未聲明網絡訪問的權限,所以無法接入網絡,並且有異常被拋出,聲明方法是,只需要在AndroidManifest.xml中聲明就可以了。

<uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="16" />

<!--添加以下節點聲明網絡使用-->
<uses-permission android:name="android.permission.INTERNET" />

 

OK,你的調用webservice的程序就可以正常運行了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM