android通过webservice连接SQL Server详细教程(数据库+服务器+客户端)

android通过webservice连接SQL Server详细教程(数据库+服务器+客户端)这篇文章中讲到android如何通过webservice连接SQL Server。由于这篇文章距今也有四年了,一些代码在现在比较新的环境中运行不了。所以我根据评论中的提示和自己遇到的问题重新修改了部分代码,使得整个系统能在SQL Server2016+Win10+VS2015+android4.4上能够运行。具体的步骤就不说了,大致上和原来的教程差不多,只说几个比较容易出问题的地方。
1.原文章中登录SQL Server用的是Windows身份验证方式。如果像我出现登录失败的问题,可以改用SQL Server身份验证方式。在安全性-登录名中添加一个SQL Server身份验证方式登录的用户。



C#的代码里面数据库连接字符串还是粘贴属性里面的连接字符串,把密码改成自己的密码
private String ConServerStr = "Data Source=2013-20160523DL;Initial Catalog=test;User ID=houjingyi;Password=*******";
2.一定要先在webservice里面确认对数据库的操作没有问题,再去调android程序。只看到页面出来了很可能数据库连接有问题,这样即使android程序没问题也调不出来。
3.android4.0以后不允许在主线程中访问网络,因为万一主线程阻塞了,会使得界面没有响应。我们开启线程访问即可。

	public List<HashMap<String, String>> getAllInfo(final Handler myhandler) 
	{
		HashMap<String, String> tempHash = new HashMap<String, String>();
		List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
		tempHash.put("Cno", "Cno");
		tempHash.put("Cname", "Cname");
		tempHash.put("Cnum", "Cnum");
		list.clear();
		arrayList1.clear();
		arrayList2.clear();
		arrayList3.clear();
		list.add(tempHash);

		new Thread()
		{
			public void run()
			{
				arrayList1 = Soap.GetWebServer("selectAllCargoInfor", arrayList1, arrayList2);
				Message msg=new Message();
				msg.what=0x123;
				msg.obj=arrayList1;
				myhandler.sendMessage(msg);
			}
		}.start();
	
		return list;
	}

	public void insertCargoInfo(String Cname, String Cnum) 
	{
		arrayList1.clear();
		arrayList2.clear();
		arrayList1.add("Cname");
		arrayList1.add("Cnum");
		arrayList2.add(Cname);
		arrayList2.add(Cnum);
		
		new Thread()
		{
			public void run()
			{
				try
				{
					Soap.GetWebServer("insertCargoInfo", arrayList1, arrayList2);
				}
				catch(Exception e)
				{
					
				}
			}
		}.start();
	}

	public void deleteCargoInfo(String Cno) 
	{
		arrayList1.clear();
		arrayList2.clear();
		arrayList1.add("Cno");
		arrayList2.add(Cno);
		
		new Thread()
		{
			public void run()
			{
				try
				{
					Soap.GetWebServer("deleteCargoInfo", arrayList1, arrayList2);
				}
				catch(Exception e)
				{
				
				}
			}
		}.start();
	}
	
4.android4.0以后子线程里是不能对主线程的UI进行改变的,因此就引出了Handler。主线程里定义Handler供子线程里使用。
	final Handler myhandler=new Handler()
	{
		public void handleMessage(Message msg)
		{
			if(msg.what==0x123)
			{
				ArrayList<String> drrayList=(ArrayList<String>) msg.obj;
				for(int j=0;!drrayList.isEmpty()&&j+2<drrayList.size();j+=3)
				{
					HashMap<String,String> hashMap=new HashMap<String,String>();
					hashMap.put("Cno", drrayList.get(j));
					hashMap.put("Cname", drrayList.get(j+1));
					hashMap.put("Cnum", drrayList.get(j+2));
					list.add(hashMap);
				}
				adapter=new SimpleAdapter(
						MainActivity.this,list,
						R.layout.adapter_item,
						new String[]{"Cno","Cname","Cnum"},
						new int[]{R.id.txt_Cno,R.id.txt_Cname,R.id.txt_Cnum});
				listView.setAdapter(adapter);
			}
		}
	};
5.HttpConnSoap.java这个类是干什么的。我们看一下这些操作的SOAP1.1请求和响应示例。
selectAllCargoInfo:
请求:
POST /Service1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/selectAllCargoInfor"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <selectAllCargoInfor xmlns="http://tempuri.org/" />
  </soap:Body>
</soap:Envelope>
响应:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <selectAllCargoInforResponse xmlns="http://tempuri.org/">
      <selectAllCargoInforResult>
        <string>string</string>
        <string>string</string>
      </selectAllCargoInforResult>
    </selectAllCargoInforResponse>
  </soap:Body>
</soap:Envelope>
insertCargoInfo:
请求:
POST /Service1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/insertCargoInfo"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <insertCargoInfo xmlns="http://tempuri.org/">
      <Cname>string</Cname>
      <Cnum>int</Cnum>
    </insertCargoInfo>
  </soap:Body>
</soap:Envelope>
响应:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <insertCargoInfoResponse xmlns="http://tempuri.org/">
      <insertCargoInfoResult>boolean</insertCargoInfoResult>
    </insertCargoInfoResponse>
  </soap:Body>
</soap:Envelope>
deleteCargoInfo:
请求:
POST /Service1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/deleteCargoInfo"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <deleteCargoInfo xmlns="http://tempuri.org/">
      <Cno>string</Cno>
    </deleteCargoInfo>
  </soap:Body>
</soap:Envelope>
响应:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <deleteCargoInfoResponse xmlns="http://tempuri.org/">
      <deleteCargoInfoResult>boolean</deleteCargoInfoResult>
    </deleteCargoInfoResponse>
  </soap:Body>
</soap:Envelope>
其实这个类就是在GetWebServer先拼XML格式的POST请求发给页面,然后在StreamtoValue里面对返回的数据做解析。GetWebServer这个函数比较简单,而在StreamtoValue里面要根据返回类型的不同执行不同的操作。删除和插入操作返回的是布尔类型,而查询操作返回的是String和int。我们也可以看到,删除和插入操作返回的XML格式是一样的。相信大家对比着XML和注释就能明白。
package com.bottle.stockmanage;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import android.app.Activity;
import android.net.ConnectivityManager;
import android.widget.Toast;  
  
public class HttpConnSoap
{  
    public ArrayList<String> GetWebServer(String MethodName, ArrayList<String> Parameters, ArrayList<String> ParValues) 
    {  
        ArrayList<String> Values = new ArrayList<String>();
        //在android模拟器中测试填写10.0.2.2
        //在真机中测试填写电脑的IP地址
        String ServerUrl = "http://10.8.167.229:6666/Service1.asmx";    
        String soapAction = "http://tempuri.org/" + MethodName;    
        String soap = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"  
                + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"  
                + "<soap:Body />";  
        String s1, s2, s3, s4 = ""; 
        s4 = "<" + MethodName + " xmlns=\"http://tempuri.org/\">";  
        for (int i = 0; i < Parameters.size(); i++)
        {  
            s1 = Parameters.get(i).toString();    
            s2 = ParValues.get(i).toString();  
            s3 = "<" + s1 + ">" + s2 + "</" + s1 + ">";  
            s4 = s4 + s3;  
        }  
        s4 = s4 + "</" + MethodName + ">";  
        String s5 = "</soap:Envelope>";  
        String requestData = soap + s4 + s5;  
        try
        {  
            URL url = new URL(ServerUrl);  
            HttpURLConnection con = (HttpURLConnection) url.openConnection();  
            byte[] bytes = requestData.getBytes("utf-8");  
            con.setDoInput(true);  
            con.setDoOutput(true);  
            con.setUseCaches(false);  
            con.setConnectTimeout(6000);  
            con.setRequestMethod("POST");  
            con.setRequestProperty("Content-Type", "text/xml;charset=utf-8");  
            con.setRequestProperty("SOAPAction", soapAction);  
            con.setRequestProperty("Content-Length", "" + bytes.length);  
            OutputStream outStream = con.getOutputStream();  
            outStream.write(bytes);  
            outStream.flush();  
            outStream.close();  
            InputStream inStream = con.getInputStream();  
            Values = StreamtoValue(inStream, MethodName);   
            return Values;  
        } 
        catch (Exception e) 
        {    
            return null;  
        }  
    }  
  
    public ArrayList<String> StreamtoValue(InputStream in, String MethodName) throws IOException
    {  
        StringBuffer out = new StringBuffer();  
        String s1 = "";  
        byte[] b = new byte[4096];  
        ArrayList<String> Values = new ArrayList<String>();  
        Values.clear();  
        for (int n; (n = in.read(b)) != -1;)
        {  
            s1 = new String(b, 0, n);  
            out.append(s1);  
        }  
        System.out.println(out);  
        //分割
        String[] s2 = s1.split("><");  
        String s5 = MethodName + "Result";  
        String s3 = "",s4 = "";  
        Boolean getValueBoolean = false;  
        for (int i = 0; i < s2.length; i++) 
        {  
            s3 = s2[i];  
            System.out.println(s3);  
            int FirstIndexPos, LastIndexPos, LengthofS5;  
            FirstIndexPos = s3.indexOf(s5);  
            LastIndexPos = s3.lastIndexOf(s5);  
            /*
            	删除:deleteCargoInfoResult>boolean</deleteCargoInfoResult
            	插入:insertCargoInfoResult>boolean</insertCargoInfoResult
            	查询:
            	selectAllCargoInforResult
            	string>string</string
            	string>string</string
            	/selectAllCargoInforResult
            */
            if (FirstIndexPos >= 0) 
            {  
                if (getValueBoolean == false) 
                {  
                    getValueBoolean = true;  
                }
                //如果返回的是布尔值,对应删除和增加操作
                if ((FirstIndexPos >= 0) && (LastIndexPos > FirstIndexPos))
                {    
                    LengthofS5 = s5.length() + 1;  
                    s4 = s3.substring(FirstIndexPos + LengthofS5, LastIndexPos - 2);    
                    Values.add(s4);    
                    getValueBoolean = false;  
                    return Values;  
                }  
  
            }  
            //查询操作取值结束
            if (s3.lastIndexOf("/" + s5) >= 0) 
            {  
                getValueBoolean = false;  
                return Values;  
            }
            //如果返回的不是布尔值,对应查询操作
            if ((getValueBoolean) && (s3.lastIndexOf("/" + s5) < 0) && (FirstIndexPos < 0))
            {  
                LastIndexPos = s3.length();  
                s4 = s3.substring(7, LastIndexPos - 8);    
                Values.add(s4);  
            }  
        }  
        return Values;  
    }  
}  

6.如果你的电脑和我一样使用的是局域网,那么手机必须连和电脑在同一个网段的WIFI,不能用4G或者3G连接。如果你用的是公网IP或者以后把程序发布到一个服务器上从而获得一个公网IP,就没有这个限制了。
最后欢迎大家一起交流,学习,也感谢原作者的文章。修改后可运行的代码在:https://github.com/houjingyi233/android-connect-to-SQL-Server-On-PC-by-webservice/

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值