目錄:
一. android使用ksoap2調用webservice
二. 異步調用
三. Android使用ksoap2調用C#中的webservice實現圖像上傳參考方法
四. 圖像傳輸中Base64編碼問題
一. android使用ksoap2調用webservice
這個話題很多文章中做過討論,這裏需要說明的一點,You can't do Network operations on the main thread. Checkout :http://developer.android.com/reference/android/os/AsyncTask.htmlfor painless background threading :) (參考:http://stackoverflow.com/questions/11969071/android-os-networkonmainthreadexception-for-webservice-ksoap),即調用webservice的操作必須是異步執行的(在2.2及之前版本可能不需要)。
android使用ksoap2調用webservice的基本代碼如下:
package com.example.webserviceexample;
import java.io.IOException;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
final static String NAMESPACE = "http://tempuri.org/";
final static String METHOD_NAME = "CelsiusToFahrenheit";
final static String SOAP_ACTION = "http://tempuri.org/CelsiusToFahrenheit";
final static String URL = "http://www.w3schools.com/webservices/tempconvert.asmx";
TextView sonuc;
EditText deger;
Button hesapla;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
deger = (EditText) findViewById(R.id.deger);
sonuc = (TextView) findViewById(R.id.flag);
hesapla = (Button) findViewById(R.id.hesapla);
hesapla.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//request info
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
Request.addProperty("Celcius",deger.getText().toString());
//envelope
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
soapEnvelope.dotNet = true; //.NET = true, php = false
//putting request to the envelope
soapEnvelope.setOutputSoapObject(Request);
//transferring data
HttpTransportSE aht = new HttpTransportSE(URL); //prepare
//start
try {
aht.call(SOAP_ACTION, soapEnvelope);
}
catch (IOException e) {
e.printStackTrace();
}
catch (XmlPullParserException e)
{
e.printStackTrace();
}
//waiting and getting response.
String result;
try {
// we are creating SoapPrimitive Object as waiting for simple variable.
result = "Fahrenheit:" + soapEnvelope.getResponse();
//writing the result to the textView
sonuc.setText(result);
}
catch (SoapFault e) {
e.printStackTrace();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
二. 異步調用
上述代碼中,沒有異步調用,是不能正常執行的,會有如下警告:
08-15 11:45:26.294: E/AndroidRuntime(641): FATAL EXCEPTION: main 08-15 11:45:26.294: E/AndroidRuntime(641): android.os.NetworkOnMainThreadException
正確的步驟中,需要把操作webservice的代碼放入異步執行中,下面是異步執行的一個完整示例(同時可參考:http://stackoverflow.com/questions/8322057/android-os-networkonmainthreadexception-exception-while-trying-to-call-a-webserv):
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
private String TAG ="Vik";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AsyncCallWS task = new AsyncCallWS();
task.execute();
}
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInVoid... params) {
Log.i(TAG, "doInBackground");
calculate();
return null;
}
@Override
protected void onPostExecute(Void result) {
Log.i(TAG, "onPostExecute");
}
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
@Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
}
public void calculate()
{
String SOAP_ACTION = "http://tempuri.org/CelsiusToFahrenheit";
String METHOD_NAME = "CelsiusToFahrenheit";
String NAMESPACE = "http://tempuri.org/";
String URL = "http://www.w3schools.com/webservices/tempconvert.asmx";
try {
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
Request.addProperty("Celsius", "32");
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
soapEnvelope.dotNet = true;
soapEnvelope.setOutputSoapObject(Request);
HttpTransportSE transport= new HttpTransportSE(URL);
transport.call(SOAP_ACTION, soapEnvelope);
SoapPrimitive resultString = (SoapPrimitive)soapEnvelope.getResponse();
Log.i(TAG, "Result Celsius: " + resultString);
}
catch(Exception ex) {
Log.e(TAG, "Error: " + ex.getMessage());
}
SOAP_ACTION = "http://tempuri.org/FahrenheitToCelsius";
METHOD_NAME = "FahrenheitToCelsius";
try {
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
Request.addProperty("Fahrenheit", "100");
SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
soapEnvelope.dotNet = true;
soapEnvelope.setOutputSoapObject(Request);
HttpTransportSE transport= new HttpTransportSE(URL);
transport.call(SOAP_ACTION, soapEnvelope);
SoapPrimitive resultString = (SoapPrimitive)soapEnvelope.getResponse();
Log.i(TAG, "Result Fahrenheit: " + resultString);
}
catch(Exception ex) {
Log.e(TAG, "Error: " + ex.getMessage());
}
}
}
三. Android使用ksoap2調用C#中的webservice實現圖像上傳參考方法
博客園“與時俱進”同時有相關的一篇博文(http://www.cnblogs.com/top5/archive/2012/02/16/2354517.html)可作爲參考,全文如下:
最近boss要求做android客戶端的圖片上傳和下載,就是調用服務器的webservice接口,實現從android上傳圖片到服務器,然後從服務器下載圖片到android客戶端。
需求下來了,開始動腦筋了唄。
通常,我們調用webservice,就是服務器和客戶端(瀏覽器,android手機端等)之間的通信,其通信一般是傳 xml或json格式的字符串。對,就只能是字符串。
我的思路是這樣的,從android端用io流讀取到要上傳的圖片,用Base64編碼成字節流的字符串,通過調用webservice把該字符串作爲參數傳到服務器端,服務端解碼該字符串,最後保存到相應的路徑下。整個上傳過程的關鍵就是 以 字節流的字符串 進行數據傳遞。下載過程,與上傳過程相反,把服務器端和客戶端的代碼相應的調換。
不羅嗦那麼多,上代碼。流程是:把android的sdcard上某張圖片 上傳到 服務器下images 文件夾下。
注:這只是個demo,沒有UI界面,文件路徑和文件名都已經寫死,運行時,相應改一下就行。
1 .讀取android sdcard上的圖片。
public void testUpload(){
try{
String srcUrl = "/sdcard/"; //路徑
String fileName = "aa.jpg"; //文件名
FileInputStream fis = new FileInputStream(srcUrl + fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count = 0;
while((count = fis.read(buffer)) >= 0){
baos.write(buffer, 0, count);
}
String uploadBuffer = new String(Base64.encode(baos.toByteArray())); //進行Base64編碼
String methodName = "uploadImage";
connectWebService(methodName,fileName, uploadBuffer); //調用webservice
Log.i("connectWebService", "start");
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
connectWebService()方法:
//使用 ksoap2 調用webservice
private boolean connectWebService(String methodName,String fileName, String imageBuffer) {
String namespace = "http://134.192.44.105:8080/SSH2/service/IService"; // 命名空間,即服務器端得接口,注:後綴沒加 .wsdl,
//服務器端我是用x-fire實現webservice接口的
String url = "http://134.192.44.105:8080/SSH2/service/IService"; //對應的url
//以下就是 調用過程了,不明白的話 請看相關webservice文檔
SoapObject soapObject = new SoapObject(namespace, methodName);
soapObject.addProperty("filename", fileName); //參數1 圖片名
soapObject.addProperty("image", imageBuffer); //參數2 圖片字符串
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER10);
envelope.dotNet = false;
envelope.setOutputSoapObject(soapObject);
HttpTransportSE httpTranstation = new HttpTransportSE(url);
try {
httpTranstation.call(namespace, envelope);
Object result = envelope.getResponse();
Log.i("connectWebService", result.toString());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
2. 服務器端的webservice代碼 :
public String uploadImage(String filename, String image) {
FileOutputStream fos = null;
try{
String toDir = "C:\\Program Files\\Tomcat 6.0\\webapps\\SSH2\\images"; //存儲路徑
byte[] buffer = new BASE64Decoder().decodeBuffer(image); //對android傳過來的圖片字符串進行解碼
File destDir = new File(toDir);
if(!destDir.exists()) destDir.mkdir();
fos = new FileOutputStream(new File(destDir,filename)); //保存圖片
fos.write(buffer);
fos.flush();
fos.close();
return "上傳圖片成功!" + "圖片路徑爲:" + toDir;
}catch (Exception e){
e.printStackTrace();
}
return "上傳圖片失敗!";
}
對android 端進行 單元測試調用testUpload()方法,如果你看到綠條的話,說明調用成功!在服務器下,就可以看到你上傳的圖片了。。。。
當然,這個demo很簡陋,沒有漂亮UI什麼的,但是這是 android端調用webservice進行上傳圖片的過程。從服務器下載到android端,道理亦然。歡迎大家交流學習。。。。
ljd_198641給出了Android使用ksoap2調用C#中的webservice函數方法(參考:http://blog.csdn.net/ljd_1986413/article/details/6928051),全文如下:
一:webService簡介
那麼什麼是webService呢?,它是一種基於SAOP協議的遠程調用標準,通過webservice可以將不同操作系統平臺,不同語言,不同技術整合到一起。
二:在AdroidManifest.xml中加入權限
<!-- 訪問網絡的權限 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
三:導入ksoap2包
首先下載KSOAP包:ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar包 複製到工程下的lib文件件裏面
然後在android項目:右鍵->build path(構建路徑)->configure build path(添加外部歸檔)--選擇ksoap2
四:編寫android可客戶端代碼
導入包庫:
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
函數方法:
try {
final String SERVER_URL = "http://124.205.154.198:8081/Service.asmx";
String nameSpace = "http://tempuri.org/";//命名空間
String methodName = "Sum";//方法名
String soapAction = "http://tempuri.org/Sum";//HelloWorld 命名空間/方法名
//創建SoapObject實例
SoapObject request = new SoapObject(nameSpace, methodName);
request.addProperty("a", "g"); //這個是傳遞參數的 當然了不要參數就不必寫這個了啊
//request.addProperty("passonString", "Rajapandian"); //這個是傳遞參數的
//生成調用web service方法的soap請求消息
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true; //設置.net web service
envelope.setOutputSoapObject(request);//發送請求
HttpTransportSE androidHttpTransport = new HttpTransportSE(SERVER_URL);
androidHttpTransport.call(soapAction, envelope);
Object result = (Object) envelope.getResponse();
//textView.setText(e.getMessage());
textView.setText(result.toString());
//textView.setText("7");
new AlertDialog.Builder(this).setTitle("Hint").setMessage(result.toString()).setPositiveButton("OK", null).show();
}
catch (Exception e)
{
System.out.println(e.getMessage());
textView.setText(e.getMessage());
new AlertDialog.Builder(this).setTitle("Hint").setMessage(e.getMessage()).setPositiveButton("OK", null).show();
}
五:webService方法
[WebMethod]
public string Sum(string a)
{
string c =a+"hello android";
return c;
}
四. 圖像傳輸中Base64編碼問題
在android java與c#進行圖像傳輸時涉及到 Base64編解碼,涉及到的知識點如下(參考:http://www.cnblogs.com/chenqingwei/archive/2010/06/28/1766689.html):
一. Base64的編碼規則
Base64編碼的思想是是採用64個基本的ASCII碼字符對數據進行重新編 碼。它將需要編碼的數據拆分成字節數組。以3個字節爲一組。按順序排列24 位數據,再把這24位數據分成4組,即每組6位。再在每組的的最高位前補兩個0湊足一個字節。這樣就把一個3字節爲一組的數據重新編碼成了4個字節。當所 要編碼的數據的字節數不是3的整倍數,也就是說在分組時最後一組不夠3個字節。這時在最後一組填充1到2個0字節。並在最後編碼完成後在結尾添加1到2個 “=”。
例:將對ABC進行BASE64編碼:
1、首先取ABC對應的ASCII碼值。A(65)B(66)C(67);
2、再取二進制值A(01000001)B(01000010)C(01000011);
3、然後把這三個字節的二進制碼接起來(010000010100001001000011);
4、 再以6位爲單位分成4個數據塊,並在最高位填充兩個0後形成4個字節的編碼後的值,(00010000)(00010100)(00001001)(00000011),其中藍色部分爲真實數據;
5、再把這四個字節數據轉化成10進制數得(16)(20)(9)(3);
6、最後根據BASE64給出的64個基本字符表,查出對應的ASCII碼字符(Q)(U)(J)(D),這裏的值實際就是數據在字符表中的索引。
注:BASE64字符 表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
二.解碼 規則
解碼過程就是把4個字節再還原成3個字節再根據不同的數據形式把字節數組重新整理 成數據。
三. C#中的實現
編碼:
byte[] bytes = Encoding.Default.GetBytes("要轉換的字符");
string str = Convert.ToBase64String(bytes);
解 碼:
byte[] outputb = Convert.FromBase64String(str);
string orgStr = Encoding.Default.GetString(outputb);
C#圖片的Base64編碼和解碼
圖片的Base64編碼:
System.IO.MemoryStream m =new System.IO.MemoryStream();
System.Drawing.Bitmap bp =new System.Drawing.Bitmap(@“c:\demo.GIF”);
bp.Save(m, System.Drawing.Imaging.ImageFormat.Gif);
byte[]b= m.GetBuffer();
string base64string=Convert.ToBase64String(b);
Base64字符串解碼:
byte[] bt = Convert.FromBase64String(base64string);
System.IO.MemoryStream stream =new System.IO.MemoryStream(bt);
Bitmap bitmap =new Bitmap(stream);
pictureBox1.Image = bitmap;
本文出自 “獨釣寒江雪” 博客,請務必保留此出處http://zhaojie.blog.51cto.com/1768828/1209816