Android连接SQLServer详细教程(数据库+服务器+客户端)
2013-05-13 09:41
330 查看
本文为原创,如果转载请注明出处 /article/8101846.html
其实之前发过一篇这样的博文/article/8101803.html,但那个只是简单记录了一些自己的想法,并没有想作为教程来看,后来由于一些朋友想要源代码,就附上了下载地址,但并没有做什么讲解,从现在开始,准备做一份详细的Android如何连接Sqlserver的教程.由于本人才疏学浅,如果有什么不对的地方欢迎大家批评指正.
为了避免再次被说标题党,这里先说明些事情:
第一,android没法直接连接SQLServer,起码我没有发现方法,想想看,sqlserver安装之后有多大,android程序是跑在手机上的,想让程序直接访问sqlserver,那手机要多大的内存?
第二,本文是通过一个“桥梁”——webservice来间接访问SQLServer的,当然还有其他方法,感兴趣的同学可以自行百度。
如果理解了上面两点,好了咱们继续。
教程会拿一个具体的例子来讲,一步一步来,也许细节上还可以继续加工,但大致的流程就是这样的。
本教程有五个部分:
项目说明
开发环境部署
数据库设计
服务器端程序设计
客户端(android端)程序设计
就做一个简单的库存管理功能,包括对仓库内现有货物的查看、货物信息的增加&删除。
操作系统:Windows764bit 旗舰版
当然这个是什么基本无所谓,只是我是在这上面开发的,不过家庭普通版的貌似不能配置IIS,就是咱们后面要使用的一个服务.
android端:eclipse + ADT集成开发环境
相信看到这个教程的基本都知道如何做这些了.如果真的是有哪位同学android开发环境没有配置好而来看这篇教程,请先移步->www.google.com
服务器端:VisualStudio 2010
旗舰版
这个是用来写website/webservice的,开发语言使用C# (即.net)
数据库:SQLServer2008 R2
其实这个是什么版本也无所谓吧,教程使用的都是比较基本的东西,所以版本的差异基本可以忽略。
IIS 7.5:正确配置并开启IIS服务
如果想将website/webservice发布出去就要开启这个服务。但是如果仅仅是在本地进行测试就不需要配置,直接在VS中运行就可以。
其实我在开发的时候也只是配置IIS的时候遇到了一些问题,这里给出IIS的配置方法.
http://wenku.baidu.com/view/95cf9fd9ad51f01dc281f1af.html这篇文库给的还是很详细的,我当初就是照着这个配置的。
表设计
表名称:C
表说明:
下图是设计表的时候的截图。
向表中输入内容
吐槽一下:为什么这里猫、狗、电话都有,甚至还有Surface?!这只能说当时LZ在想这些……
两者的区别:
Web Service 只提供程序和接口,不提供用户界面
Web Site 提供程序和接口,也提供用户界面(网页)
由于咱们只是需要一个中介来访问sqlserver,所以写成webservice足够了。
目标:写一个Website访问Sqlserver,获取数据并转换成xml格式,然后传递给android客户端。
1. 新建一个Webservice工程
2. 视图 -> 其它窗口 -> 服务器资源管理器
3. 右键数据连接 -> 添加连接
4. 选择Microsoft Sqlserver
5. 如下图所示选择(可以点击测试连接来检测连接是否成功,然后点击确定)
6. 数据库的查看和编辑也可以在VS中进行了
7. 先查看一下数据库属性并记录下连接属性
8. 新建一个类DBOperation,代码如下:
[csharp]
view plaincopyprint?
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;
namespace StockManageWebservice
{
/// <summary>
/// 一个操作数据库的类,所有对SQLServer的操作都写在这个类中,使用的时候实例化一个然后直接调用就可以
/// </summary>
public class DBOperation:IDisposable
{
public static SqlConnection sqlCon; //用于连接数据库
//将下面的引号之间的内容换成上面记录下的属性中的连接字符串
private String ConServerStr = @"Data Source=BOTTLE-PC;Initial Catalog=StockManage;Integrated Security=True";
//默认构造函数
public DBOperation()
{
if (sqlCon == null)
{
sqlCon = new SqlConnection();
sqlCon.ConnectionString = ConServerStr;
sqlCon.Open();
}
}
//关闭/销毁函数,相当于Close()
public void Dispose()
{
if (sqlCon != null)
{
sqlCon.Close();
sqlCon = null;
}
}
/// <summary>
/// 获取所有货物的信息
/// </summary>
/// <returns>所有货物信息</returns>
public List<string> selectAllCargoInfor()
{
List<string> list = new List<string>();
try
{
string sql = "select * from C";
SqlCommand cmd = new SqlCommand(sql,sqlCon);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
//将结果集信息添加到返回向量中
list.Add(reader[0].ToString());
list.Add(reader[1].ToString());
list.Add(reader[2].ToString());
}
reader.Close();
cmd.Dispose();
}
catch(Exception)
{
}
return list;
}
/// <summary>
/// 增加一条货物信息
/// </summary>
/// <param name="Cname">货物名称</param>
/// <param name="Cnum">货物数量</param>
public bool insertCargoInfo(string Cname, int Cnum)
{
try
{
string sql = "insert into C (Cname,Cnum) values ('" + Cname + "'," + Cnum + ")";
SqlCommand cmd = new SqlCommand(sql, sqlCon);
cmd.ExecuteNonQuery();
cmd.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 删除一条货物信息
/// </summary>
/// <param name="Cno">货物编号</param>
public bool deleteCargoInfo(string Cno)
{
try
{
string sql = "delete from C where Cno=" + Cno;
SqlCommand cmd = new SqlCommand(sql, sqlCon);
cmd.ExecuteNonQuery();
cmd.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
}
}
9. 修改Service1.asmx.cs代码如下:
[csharp]
view plaincopyprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace StockManageWebservice
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
DBOperation dbOperation = new DBOperation();
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod(Description = "获取所有货物的信息")]
public string[] selectAllCargoInfor()
{
return dbOperation.selectAllCargoInfor().ToArray();
}
[WebMethod(Description = "增加一条货物信息")]
public bool insertCargoInfo(string Cname, int Cnum)
{
return dbOperation.insertCargoInfo(Cname, Cnum);
}
[WebMethod(Description = "删除一条货物信息")]
public bool deleteCargoInfo(string Cno)
{
return dbOperation.deleteCargoInfo(Cno);
}
}
}
10. 运行程序(F5),会自动打开一个浏览器,可以看到如下画面:
11. 选择相应的功能并传递参数可以实现调试从浏览器中调试程序:
下图选择的是增加一条货物信息
12. 程序执行的结果:
13.另,记住这里的端口名,后面android的程序中添入的端口号就是这个:
1.MainActivity
[java]
view plaincopyprint?
package com.bottle.stockmanage; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.app.Dialog; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; public class MainActivity extends Activity{ private Button btn1; private Button btn2; private Button btn3; private ListView listView; private SimpleAdapter adapter; private DBUtil dbUtil; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.btn_all); btn2 = (Button) findViewById(R.id.btn_add); btn3 = (Button) findViewById(R.id.btn_delete); listView = (ListView) findViewById(R.id.listView); dbUtil = new DBUtil(); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setListView(); } }); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setAddDialog(); } }); btn3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setDeleteDialog(); } }); } /** * 设置弹出删除对话框 */ private void setDeleteDialog() { final Dialog dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.dialog_delete); dialog.setTitle("输入想要删除的货物的编号"); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); final EditText cNoEditText = (EditText) dialog.findViewById(R.id.editText1); Button btnConfirm = (Button) dialog.findViewById(R.id.button1); Button btnCancel = (Button) dialog.findViewById(R.id.button2); btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dbUtil.deleteCargoInfo(cNoEditText.getText().toString()); dialog.dismiss(); hideButton(false); Toast.makeText(MainActivity.this, "成功删除数据", Toast.LENGTH_SHORT).show(); } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); hideButton(false); } }); dialog.show(); } /** * 设置弹出添加对话框 */ private void setAddDialog() { final Dialog dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.dialog_add); dialog.setTitle("输入添加的货物的信息"); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); final EditText cNameEditText = (EditText) dialog.findViewById(R.id.editText1); final EditText cNumEditText = (EditText) dialog.findViewById(R.id.editText2); Button btnConfirm = (Button) dialog.findViewById(R.id.button1); Button btnCancel = (Button) dialog.findViewById(R.id.button2); btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dbUtil.insertCargoInfo(cNameEditText.getText().toString(), cNumEditText.getText().toString()); dialog.dismiss(); hideButton(false); Toast.makeText(MainActivity.this, "成功添加数据", Toast.LENGTH_SHORT).show(); } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); hideButton(false); } }); dialog.show(); } /** * 设置listView */ private void setListView() { listView.setVisibility(View.VISIBLE); List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); list = dbUtil.getAllInfo(); 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); } /** * 设置button的可见性 */ private void hideButton(boolean result) { if (result) { btn1.setVisibility(View.GONE); btn2.setVisibility(View.GONE); btn3.setVisibility(View.GONE); } else { btn1.setVisibility(View.VISIBLE); btn2.setVisibility(View.VISIBLE); btn3.setVisibility(View.VISIBLE); } } /** * 返回按钮的重写 */ @Override public void onBackPressed() { if (listView.getVisibility() == View.VISIBLE) { listView.setVisibility(View.GONE); hideButton(false); }else { MainActivity.this.finish(); } } }
2.HttpConnSoap
[java]
view plaincopyprint?
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;
public class HttpConnSoap {
public ArrayList<String> GetWebServre(String methodName, ArrayList<String> Parameters, ArrayList<String> ParValues) {
ArrayList<String> Values = new ArrayList<String>();
//ServerUrl是指webservice的url
//10.0.2.2是让android模拟器访问本地(PC)服务器,不能写成127.0.0.1
//11125是指端口号,即挂载到IIS上的时候开启的端口
//Service1.asmx是指提供服务的页面
String ServerUrl = "http://10.0.2.2:11125/Service1.asmx";
//String soapAction="http://tempuri.org/LongUserId1";
String soapAction = "http://tempuri.org/" + methodName;
//String data = "";
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 tps, vps, ts;
String mreakString = "";
mreakString = "<" + methodName + " xmlns=\"http://tempuri.org/\">";
for (int i = 0; i < Parameters.size(); i++) {
tps = Parameters.get(i).toString();
//设置该方法的参数为.net webService中的参数名称
vps = ParValues.get(i).toString();
ts = "<" + tps + ">" + vps + "</" + tps + ">";
mreakString = mreakString + ts;
}
mreakString = mreakString + "</" + methodName + ">";
/*
+"<HelloWorld xmlns=\"http://tempuri.org/\">"
+"<x>string11661</x>"
+"<SF1>string111</SF1>"
+ "</HelloWorld>"
*/
String soap2 = "</soap:Envelope>";
String requestData = soap + mreakString + soap2;
//System.out.println(requestData);
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();
//data=parser(inStream);
//System.out.print("11");
Values = inputStreamtovaluelist(inStream, methodName);
//System.out.println(Values.size());
return Values;
} catch (Exception e) {
System.out.print("2221");
return null;
}
}
public ArrayList<String> inputStreamtovaluelist(InputStream in, String MonthsName) 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[] s13 = s1.split("><");
String ifString = MonthsName + "Result";
String TS = "";
String vs = "";
Boolean getValueBoolean = false;
for (int i = 0; i < s13.length; i++) {
TS = s13[i];
System.out.println(TS);
int j, k, l;
j = TS.indexOf(ifString);
k = TS.lastIndexOf(ifString);
if (j >= 0) {
System.out.println(j);
if (getValueBoolean == false) {
getValueBoolean = true;
} else {
}
if ((j >= 0) && (k > j)) {
System.out.println("FFF" + TS.lastIndexOf("/" + ifString));
//System.out.println(TS);
l = ifString.length() + 1;
vs = TS.substring(j + l, k - 2);
//System.out.println("fff"+vs);
Values.add(vs);
System.out.println("退出" + vs);
getValueBoolean = false;
return Values;
}
}
if (TS.lastIndexOf("/" + ifString) >= 0) {
getValueBoolean = false;
return Values;
}
if ((getValueBoolean) && (TS.lastIndexOf("/" + ifString) < 0) && (j < 0)) {
k = TS.length();
//System.out.println(TS);
vs = TS.substring(7, k - 8);
//System.out.println("f"+vs);
Values.add(vs);
}
}
return Values;
}
}
3.DBUtil
[java]
view plaincopyprint?
package com.bottle.stockmanage;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DBUtil {
private ArrayList<String> arrayList = new ArrayList<String>();
private ArrayList<String> brrayList = new ArrayList<String>();
private ArrayList<String> crrayList = new ArrayList<String>();
private HttpConnSoap Soap = new HttpConnSoap();
public static Connection getConnection() {
Connection con = null;
try {
//Class.forName("org.gjt.mm.mysql.Driver");
//con=DriverManager.getConnection("jdbc:mysql://192.168.0.106:3306/test?useUnicode=true&characterEncoding=UTF-8","root","initial");
} catch (Exception e) {
//e.printStackTrace();
}
return con;
}
/**
* 获取所有货物的信息
*
* @return
*/
public List<HashMap<String, String>> getAllInfo() {
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
arrayList.clear();
brrayList.clear();
crrayList.clear();
crrayList = Soap.GetWebServre("selectAllCargoInfor", arrayList, brrayList);
HashMap<String, String> tempHash = new HashMap<String, String>();
tempHash.put("Cno", "Cno");
tempHash.put("Cname", "Cname");
tempHash.put("Cnum", "Cnum");
list.add(tempHash);
for (int j = 0; j < crrayList.size(); j += 3) {
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("Cno", crrayList.get(j));
hashMap.put("Cname", crrayList.get(j + 1));
hashMap.put("Cnum", crrayList.get(j + 2));
list.add(hashMap);
}
return list;
}
/**
* 增加一条货物信息
*
* @return
*/
public void insertCargoInfo(String Cname, String Cnum) {
arrayList.clear();
brrayList.clear();
arrayList.add("Cname");
arrayList.add("Cnum");
brrayList.add(Cname);
brrayList.add(Cnum);
Soap.GetWebServre("insertCargoInfo", arrayList, brrayList);
}
/**
* 删除一条货物信息
*
* @return
*/
public void deleteCargoInfo(String Cno) {
arrayList.clear();
brrayList.clear();
arrayList.add("Cno");
brrayList.add(Cno);
Soap.GetWebServre("deleteCargoInfo", arrayList, brrayList);
}
}
4.activity_main.xml
[html]
view plaincopyprint?
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone" >
</ListView>
<Button
android:id="@+id/btn_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/btn_add"
android:layout_alignLeft="@+id/btn_add"
android:layout_marginBottom="10dip"
android:text="@string/btn1" />
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/btn2" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/btn_add"
android:layout_below="@+id/btn_add"
android:layout_marginTop="10dip"
android:text="@string/btn3" />
</RelativeLayout>
5.adapter_item.xml
[html]
view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:gravity="center" >
<TableRow
android:id="@+id/classroom_detail_item_tableRow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<TextView
android:id="@+id/txt_Cno"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:height="40dp"
android:textSize="14sp" >
</TextView>
<TextView
android:id="@+id/txt_Cname"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:height="40dp"
android:textSize="14sp" >
</TextView>
<TextView
android:id="@+id/txt_Cnum"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:height="40dp"
android:textSize="14sp" >
</TextView>
</TableRow>
</TableLayout>
6.dialog_add.xml
[html]
view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/add_hint1" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/editText2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/add_hint2"
android:inputType="number" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:text="@string/confirm" />
<Button
android:id="@+id/button2"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="40dip"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
7.dialog_delete.xml
[html]
view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/delete_hint" >
<requestFocus />
</EditText>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:text="@string/confirm" />
<Button
android:id="@+id/button2"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="40dip"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
8.strings.xml
[html]
view plaincopyprint?
<resources> <string name="app_name">StockManagement</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">MainActivity</string> <string name="btn1">查看所有货物信息</string> <string name="btn2">增加一条货物信息</string> <string name="btn3">删除一条货物信息</string> <string name="add_hint1">输入添加的货物的名称</string> <string name="add_hint2">输入货物的数量</string> <string name="confirm">确定</string> <string name="cancel">取消</string> <string name="delete_hint">输入删除的货物的编号</string> </resources>
9.Manifest.xml
[html]
view plaincopyprint?
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bottle.stockmanage" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
运行程序的效果如下图所示:
再说一下IIS,如果只是在本地进行测试等操作,是不需要使用到IIS的,但是如果想发布出去,就要配置一下IIS。
好啦,基本就是这样了。程序不是完善的,但大概的思路就是这样,用到的技术也大概就是这几样,但是每一样拿出来都够学一阵的了。
--->2012.12.02 增加内容
附上本文demo的CSDN下载地址
http://download.csdn.net/detail/zhyl8157121/4836107
--->2013.01.08 增加内容
解释一下android端如何和webservice通信的。(如何修改实例程序)
具体的更深层的东西已经在HttpSoap中封装好了,所以大家使用的时候可以直接用这个类就可以了。(我也不懂是怎么实现的……)
android调用的方法就是如DBUtil中那样,比如
其中arrayList中和brrayList中分别存放对应的webservice中“selectAllCargoInfor”方法的参数名和参数的值。
由于webservice中的selectAllCargoInfo方法的参数为空,所以对应的,android端调用的时候,arrayList和brrayList的值就是空的。
所以大家在使用的时候,只需要将webservice中的方法写好,然后写好DBUtil中的调用参数即可。
--->2013.03.23 增加内容
如果获取值为空,可能是返回值是复杂类型造成的,可以参考:/article/8101849.html
其实之前发过一篇这样的博文/article/8101803.html,但那个只是简单记录了一些自己的想法,并没有想作为教程来看,后来由于一些朋友想要源代码,就附上了下载地址,但并没有做什么讲解,从现在开始,准备做一份详细的Android如何连接Sqlserver的教程.由于本人才疏学浅,如果有什么不对的地方欢迎大家批评指正.
为了避免再次被说标题党,这里先说明些事情:
第一,android没法直接连接SQLServer,起码我没有发现方法,想想看,sqlserver安装之后有多大,android程序是跑在手机上的,想让程序直接访问sqlserver,那手机要多大的内存?
第二,本文是通过一个“桥梁”——webservice来间接访问SQLServer的,当然还有其他方法,感兴趣的同学可以自行百度。
如果理解了上面两点,好了咱们继续。
教程会拿一个具体的例子来讲,一步一步来,也许细节上还可以继续加工,但大致的流程就是这样的。
本教程有五个部分:
项目说明
开发环境部署
数据库设计
服务器端程序设计
客户端(android端)程序设计
项目说明
这个项目意在实现一个简单的android连接Sqlserver的功能。就做一个简单的库存管理功能,包括对仓库内现有货物的查看、货物信息的增加&删除。
开发环境的部署
今天主要讲解第一个部分,开发环境的部署.操作系统:Windows764bit 旗舰版
当然这个是什么基本无所谓,只是我是在这上面开发的,不过家庭普通版的貌似不能配置IIS,就是咱们后面要使用的一个服务.
android端:eclipse + ADT集成开发环境
相信看到这个教程的基本都知道如何做这些了.如果真的是有哪位同学android开发环境没有配置好而来看这篇教程,请先移步->www.google.com
服务器端:VisualStudio 2010
旗舰版
这个是用来写website/webservice的,开发语言使用C# (即.net)
数据库:SQLServer2008 R2
其实这个是什么版本也无所谓吧,教程使用的都是比较基本的东西,所以版本的差异基本可以忽略。
IIS 7.5:正确配置并开启IIS服务
如果想将website/webservice发布出去就要开启这个服务。但是如果仅仅是在本地进行测试就不需要配置,直接在VS中运行就可以。
其实我在开发的时候也只是配置IIS的时候遇到了一些问题,这里给出IIS的配置方法.
http://wenku.baidu.com/view/95cf9fd9ad51f01dc281f1af.html这篇文库给的还是很详细的,我当初就是照着这个配置的。
数据库设计
数据库名称:StockManage表设计
表名称:C
表说明:
列名 | 中文名称 | 数据型态 | 必填 | 说明 |
Cno | 货物编号 | Int | V | 主键,自增 |
Cname | 货物名称 | String | ||
Cnum | 货物数量 | Int |
向表中输入内容
吐槽一下:为什么这里猫、狗、电话都有,甚至还有Surface?!这只能说当时LZ在想这些……
服务器端程序设计(Webservice)
其实服务端可以写成webservice也可以写成website,前者只是提供一种服务,而后者是可以提供用户界面等具体的页面,后者也就是咱们平时所说的“网站”。两者的区别:
Web Service 只提供程序和接口,不提供用户界面
Web Site 提供程序和接口,也提供用户界面(网页)
由于咱们只是需要一个中介来访问sqlserver,所以写成webservice足够了。
目标:写一个Website访问Sqlserver,获取数据并转换成xml格式,然后传递给android客户端。
1. 新建一个Webservice工程
2. 视图 -> 其它窗口 -> 服务器资源管理器
3. 右键数据连接 -> 添加连接
4. 选择Microsoft Sqlserver
5. 如下图所示选择(可以点击测试连接来检测连接是否成功,然后点击确定)
6. 数据库的查看和编辑也可以在VS中进行了
7. 先查看一下数据库属性并记录下连接属性
8. 新建一个类DBOperation,代码如下:
[csharp]
view plaincopyprint?
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;
namespace StockManageWebservice
{
/// <summary>
/// 一个操作数据库的类,所有对SQLServer的操作都写在这个类中,使用的时候实例化一个然后直接调用就可以
/// </summary>
public class DBOperation:IDisposable
{
public static SqlConnection sqlCon; //用于连接数据库
//将下面的引号之间的内容换成上面记录下的属性中的连接字符串
private String ConServerStr = @"Data Source=BOTTLE-PC;Initial Catalog=StockManage;Integrated Security=True";
//默认构造函数
public DBOperation()
{
if (sqlCon == null)
{
sqlCon = new SqlConnection();
sqlCon.ConnectionString = ConServerStr;
sqlCon.Open();
}
}
//关闭/销毁函数,相当于Close()
public void Dispose()
{
if (sqlCon != null)
{
sqlCon.Close();
sqlCon = null;
}
}
/// <summary>
/// 获取所有货物的信息
/// </summary>
/// <returns>所有货物信息</returns>
public List<string> selectAllCargoInfor()
{
List<string> list = new List<string>();
try
{
string sql = "select * from C";
SqlCommand cmd = new SqlCommand(sql,sqlCon);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
//将结果集信息添加到返回向量中
list.Add(reader[0].ToString());
list.Add(reader[1].ToString());
list.Add(reader[2].ToString());
}
reader.Close();
cmd.Dispose();
}
catch(Exception)
{
}
return list;
}
/// <summary>
/// 增加一条货物信息
/// </summary>
/// <param name="Cname">货物名称</param>
/// <param name="Cnum">货物数量</param>
public bool insertCargoInfo(string Cname, int Cnum)
{
try
{
string sql = "insert into C (Cname,Cnum) values ('" + Cname + "'," + Cnum + ")";
SqlCommand cmd = new SqlCommand(sql, sqlCon);
cmd.ExecuteNonQuery();
cmd.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 删除一条货物信息
/// </summary>
/// <param name="Cno">货物编号</param>
public bool deleteCargoInfo(string Cno)
{
try
{
string sql = "delete from C where Cno=" + Cno;
SqlCommand cmd = new SqlCommand(sql, sqlCon);
cmd.ExecuteNonQuery();
cmd.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
}
}
using System; using System.Data; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.Data.SqlClient; using System.Text.RegularExpressions; using System.Collections; using System.Collections.Generic; namespace StockManageWebservice { /// <summary> /// 一个操作数据库的类,所有对SQLServer的操作都写在这个类中,使用的时候实例化一个然后直接调用就可以 /// </summary> public class DBOperation:IDisposable { public static SqlConnection sqlCon; //用于连接数据库 //将下面的引号之间的内容换成上面记录下的属性中的连接字符串 private String ConServerStr = @"Data Source=BOTTLE-PC;Initial Catalog=StockManage;Integrated Security=True"; //默认构造函数 public DBOperation() { if (sqlCon == null) { sqlCon = new SqlConnection(); sqlCon.ConnectionString = ConServerStr; sqlCon.Open(); } } //关闭/销毁函数,相当于Close() public void Dispose() { if (sqlCon != null) { sqlCon.Close(); sqlCon = null; } } /// <summary> /// 获取所有货物的信息 /// </summary> /// <returns>所有货物信息</returns> public List<string> selectAllCargoInfor() { List<string> list = new List<string>(); try { string sql = "select * from C"; SqlCommand cmd = new SqlCommand(sql,sqlCon); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { //将结果集信息添加到返回向量中 list.Add(reader[0].ToString()); list.Add(reader[1].ToString()); list.Add(reader[2].ToString()); } reader.Close(); cmd.Dispose(); } catch(Exception) { } return list; } /// <summary> /// 增加一条货物信息 /// </summary> /// <param name="Cname">货物名称</param> /// <param name="Cnum">货物数量</param> public bool insertCargoInfo(string Cname, int Cnum) { try { string sql = "insert into C (Cname,Cnum) values ('" + Cname + "'," + Cnum + ")"; SqlCommand cmd = new SqlCommand(sql, sqlCon); cmd.ExecuteNonQuery(); cmd.Dispose(); return true; } catch (Exception) { return false; } } /// <summary> /// 删除一条货物信息 /// </summary> /// <param name="Cno">货物编号</param> public bool deleteCargoInfo(string Cno) { try { string sql = "delete from C where Cno=" + Cno; SqlCommand cmd = new SqlCommand(sql, sqlCon); cmd.ExecuteNonQuery(); cmd.Dispose(); return true; } catch (Exception) { return false; } } } }
9. 修改Service1.asmx.cs代码如下:
[csharp]
view plaincopyprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace StockManageWebservice
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
DBOperation dbOperation = new DBOperation();
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod(Description = "获取所有货物的信息")]
public string[] selectAllCargoInfor()
{
return dbOperation.selectAllCargoInfor().ToArray();
}
[WebMethod(Description = "增加一条货物信息")]
public bool insertCargoInfo(string Cname, int Cnum)
{
return dbOperation.insertCargoInfo(Cname, Cnum);
}
[WebMethod(Description = "删除一条货物信息")]
public bool deleteCargoInfo(string Cno)
{
return dbOperation.deleteCargoInfo(Cno);
}
}
}
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; namespace StockManageWebservice { /// <summary> /// Service1 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 // [System.Web.Script.Services.ScriptService] public class Service1 : System.Web.Services.WebService { DBOperation dbOperation = new DBOperation(); [WebMethod] public string HelloWorld() { return "Hello World"; } [WebMethod(Description = "获取所有货物的信息")] public string[] selectAllCargoInfor() { return dbOperation.selectAllCargoInfor().ToArray(); } [WebMethod(Description = "增加一条货物信息")] public bool insertCargoInfo(string Cname, int Cnum) { return dbOperation.insertCargoInfo(Cname, Cnum); } [WebMethod(Description = "删除一条货物信息")] public bool deleteCargoInfo(string Cno) { return dbOperation.deleteCargoInfo(Cno); } } }
10. 运行程序(F5),会自动打开一个浏览器,可以看到如下画面:
11. 选择相应的功能并传递参数可以实现调试从浏览器中调试程序:
下图选择的是增加一条货物信息
12. 程序执行的结果:
13.另,记住这里的端口名,后面android的程序中添入的端口号就是这个:
客户端(android端)程序设计
程序代码:1.MainActivity
[java]
view plaincopyprint?
package com.bottle.stockmanage; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.app.Dialog; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; public class MainActivity extends Activity{ private Button btn1; private Button btn2; private Button btn3; private ListView listView; private SimpleAdapter adapter; private DBUtil dbUtil; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.btn_all); btn2 = (Button) findViewById(R.id.btn_add); btn3 = (Button) findViewById(R.id.btn_delete); listView = (ListView) findViewById(R.id.listView); dbUtil = new DBUtil(); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setListView(); } }); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setAddDialog(); } }); btn3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setDeleteDialog(); } }); } /** * 设置弹出删除对话框 */ private void setDeleteDialog() { final Dialog dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.dialog_delete); dialog.setTitle("输入想要删除的货物的编号"); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); final EditText cNoEditText = (EditText) dialog.findViewById(R.id.editText1); Button btnConfirm = (Button) dialog.findViewById(R.id.button1); Button btnCancel = (Button) dialog.findViewById(R.id.button2); btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dbUtil.deleteCargoInfo(cNoEditText.getText().toString()); dialog.dismiss(); hideButton(false); Toast.makeText(MainActivity.this, "成功删除数据", Toast.LENGTH_SHORT).show(); } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); hideButton(false); } }); dialog.show(); } /** * 设置弹出添加对话框 */ private void setAddDialog() { final Dialog dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.dialog_add); dialog.setTitle("输入添加的货物的信息"); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); final EditText cNameEditText = (EditText) dialog.findViewById(R.id.editText1); final EditText cNumEditText = (EditText) dialog.findViewById(R.id.editText2); Button btnConfirm = (Button) dialog.findViewById(R.id.button1); Button btnCancel = (Button) dialog.findViewById(R.id.button2); btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dbUtil.insertCargoInfo(cNameEditText.getText().toString(), cNumEditText.getText().toString()); dialog.dismiss(); hideButton(false); Toast.makeText(MainActivity.this, "成功添加数据", Toast.LENGTH_SHORT).show(); } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); hideButton(false); } }); dialog.show(); } /** * 设置listView */ private void setListView() { listView.setVisibility(View.VISIBLE); List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); list = dbUtil.getAllInfo(); 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); } /** * 设置button的可见性 */ private void hideButton(boolean result) { if (result) { btn1.setVisibility(View.GONE); btn2.setVisibility(View.GONE); btn3.setVisibility(View.GONE); } else { btn1.setVisibility(View.VISIBLE); btn2.setVisibility(View.VISIBLE); btn3.setVisibility(View.VISIBLE); } } /** * 返回按钮的重写 */ @Override public void onBackPressed() { if (listView.getVisibility() == View.VISIBLE) { listView.setVisibility(View.GONE); hideButton(false); }else { MainActivity.this.finish(); } } }
package com.bottle.stockmanage; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.app.Dialog; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; public class MainActivity extends Activity{ private Button btn1; private Button btn2; private Button btn3; private ListView listView; private SimpleAdapter adapter; private DBUtil dbUtil; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.btn_all); btn2 = (Button) findViewById(R.id.btn_add); btn3 = (Button) findViewById(R.id.btn_delete); listView = (ListView) findViewById(R.id.listView); dbUtil = new DBUtil(); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setListView(); } }); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setAddDialog(); } }); btn3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { hideButton(true); setDeleteDialog(); } }); } /** * 设置弹出删除对话框 */ private void setDeleteDialog() { final Dialog dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.dialog_delete); dialog.setTitle("输入想要删除的货物的编号"); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); final EditText cNoEditText = (EditText) dialog.findViewById(R.id.editText1); Button btnConfirm = (Button) dialog.findViewById(R.id.button1); Button btnCancel = (Button) dialog.findViewById(R.id.button2); btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dbUtil.deleteCargoInfo(cNoEditText.getText().toString()); dialog.dismiss(); hideButton(false); Toast.makeText(MainActivity.this, "成功删除数据", Toast.LENGTH_SHORT).show(); } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); hideButton(false); } }); dialog.show(); } /** * 设置弹出添加对话框 */ private void setAddDialog() { final Dialog dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.dialog_add); dialog.setTitle("输入添加的货物的信息"); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); final EditText cNameEditText = (EditText) dialog.findViewById(R.id.editText1); final EditText cNumEditText = (EditText) dialog.findViewById(R.id.editText2); Button btnConfirm = (Button) dialog.findViewById(R.id.button1); Button btnCancel = (Button) dialog.findViewById(R.id.button2); btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dbUtil.insertCargoInfo(cNameEditText.getText().toString(), cNumEditText.getText().toString()); dialog.dismiss(); hideButton(false); Toast.makeText(MainActivity.this, "成功添加数据", Toast.LENGTH_SHORT).show(); } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); hideButton(false); } }); dialog.show(); } /** * 设置listView */ private void setListView() { listView.setVisibility(View.VISIBLE); List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); list = dbUtil.getAllInfo(); 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); } /** * 设置button的可见性 */ private void hideButton(boolean result) { if (result) { btn1.setVisibility(View.GONE); btn2.setVisibility(View.GONE); btn3.setVisibility(View.GONE); } else { btn1.setVisibility(View.VISIBLE); btn2.setVisibility(View.VISIBLE); btn3.setVisibility(View.VISIBLE); } } /** * 返回按钮的重写 */ @Override public void onBackPressed() { if (listView.getVisibility() == View.VISIBLE) { listView.setVisibility(View.GONE); hideButton(false); }else { MainActivity.this.finish(); } } }
2.HttpConnSoap
[java]
view plaincopyprint?
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;
public class HttpConnSoap {
public ArrayList<String> GetWebServre(String methodName, ArrayList<String> Parameters, ArrayList<String> ParValues) {
ArrayList<String> Values = new ArrayList<String>();
//ServerUrl是指webservice的url
//10.0.2.2是让android模拟器访问本地(PC)服务器,不能写成127.0.0.1
//11125是指端口号,即挂载到IIS上的时候开启的端口
//Service1.asmx是指提供服务的页面
String ServerUrl = "http://10.0.2.2:11125/Service1.asmx";
//String soapAction="http://tempuri.org/LongUserId1";
String soapAction = "http://tempuri.org/" + methodName;
//String data = "";
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 tps, vps, ts;
String mreakString = "";
mreakString = "<" + methodName + " xmlns=\"http://tempuri.org/\">";
for (int i = 0; i < Parameters.size(); i++) {
tps = Parameters.get(i).toString();
//设置该方法的参数为.net webService中的参数名称
vps = ParValues.get(i).toString();
ts = "<" + tps + ">" + vps + "</" + tps + ">";
mreakString = mreakString + ts;
}
mreakString = mreakString + "</" + methodName + ">";
/*
+"<HelloWorld xmlns=\"http://tempuri.org/\">"
+"<x>string11661</x>"
+"<SF1>string111</SF1>"
+ "</HelloWorld>"
*/
String soap2 = "</soap:Envelope>";
String requestData = soap + mreakString + soap2;
//System.out.println(requestData);
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();
//data=parser(inStream);
//System.out.print("11");
Values = inputStreamtovaluelist(inStream, methodName);
//System.out.println(Values.size());
return Values;
} catch (Exception e) {
System.out.print("2221");
return null;
}
}
public ArrayList<String> inputStreamtovaluelist(InputStream in, String MonthsName) 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[] s13 = s1.split("><");
String ifString = MonthsName + "Result";
String TS = "";
String vs = "";
Boolean getValueBoolean = false;
for (int i = 0; i < s13.length; i++) {
TS = s13[i];
System.out.println(TS);
int j, k, l;
j = TS.indexOf(ifString);
k = TS.lastIndexOf(ifString);
if (j >= 0) {
System.out.println(j);
if (getValueBoolean == false) {
getValueBoolean = true;
} else {
}
if ((j >= 0) && (k > j)) {
System.out.println("FFF" + TS.lastIndexOf("/" + ifString));
//System.out.println(TS);
l = ifString.length() + 1;
vs = TS.substring(j + l, k - 2);
//System.out.println("fff"+vs);
Values.add(vs);
System.out.println("退出" + vs);
getValueBoolean = false;
return Values;
}
}
if (TS.lastIndexOf("/" + ifString) >= 0) {
getValueBoolean = false;
return Values;
}
if ((getValueBoolean) && (TS.lastIndexOf("/" + ifString) < 0) && (j < 0)) {
k = TS.length();
//System.out.println(TS);
vs = TS.substring(7, k - 8);
//System.out.println("f"+vs);
Values.add(vs);
}
}
return Values;
}
}
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; public class HttpConnSoap { public ArrayList<String> GetWebServre(String methodName, ArrayList<String> Parameters, ArrayList<String> ParValues) { ArrayList<String> Values = new ArrayList<String>(); //ServerUrl是指webservice的url //10.0.2.2是让android模拟器访问本地(PC)服务器,不能写成127.0.0.1 //11125是指端口号,即挂载到IIS上的时候开启的端口 //Service1.asmx是指提供服务的页面 String ServerUrl = "http://10.0.2.2:11125/Service1.asmx"; //String soapAction="http://tempuri.org/LongUserId1"; String soapAction = "http://tempuri.org/" + methodName; //String data = ""; 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 tps, vps, ts; String mreakString = ""; mreakString = "<" + methodName + " xmlns=\"http://tempuri.org/\">"; for (int i = 0; i < Parameters.size(); i++) { tps = Parameters.get(i).toString(); //设置该方法的参数为.net webService中的参数名称 vps = ParValues.get(i).toString(); ts = "<" + tps + ">" + vps + "</" + tps + ">"; mreakString = mreakString + ts; } mreakString = mreakString + "</" + methodName + ">"; /* +"<HelloWorld xmlns=\"http://tempuri.org/\">" +"<x>string11661</x>" +"<SF1>string111</SF1>" + "</HelloWorld>" */ String soap2 = "</soap:Envelope>"; String requestData = soap + mreakString + soap2; //System.out.println(requestData); 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(); //data=parser(inStream); //System.out.print("11"); Values = inputStreamtovaluelist(inStream, methodName); //System.out.println(Values.size()); return Values; } catch (Exception e) { System.out.print("2221"); return null; } } public ArrayList<String> inputStreamtovaluelist(InputStream in, String MonthsName) 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[] s13 = s1.split("><"); String ifString = MonthsName + "Result"; String TS = ""; String vs = ""; Boolean getValueBoolean = false; for (int i = 0; i < s13.length; i++) { TS = s13[i]; System.out.println(TS); int j, k, l; j = TS.indexOf(ifString); k = TS.lastIndexOf(ifString); if (j >= 0) { System.out.println(j); if (getValueBoolean == false) { getValueBoolean = true; } else { } if ((j >= 0) && (k > j)) { System.out.println("FFF" + TS.lastIndexOf("/" + ifString)); //System.out.println(TS); l = ifString.length() + 1; vs = TS.substring(j + l, k - 2); //System.out.println("fff"+vs); Values.add(vs); System.out.println("退出" + vs); getValueBoolean = false; return Values; } } if (TS.lastIndexOf("/" + ifString) >= 0) { getValueBoolean = false; return Values; } if ((getValueBoolean) && (TS.lastIndexOf("/" + ifString) < 0) && (j < 0)) { k = TS.length(); //System.out.println(TS); vs = TS.substring(7, k - 8); //System.out.println("f"+vs); Values.add(vs); } } return Values; } }
3.DBUtil
[java]
view plaincopyprint?
package com.bottle.stockmanage;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DBUtil {
private ArrayList<String> arrayList = new ArrayList<String>();
private ArrayList<String> brrayList = new ArrayList<String>();
private ArrayList<String> crrayList = new ArrayList<String>();
private HttpConnSoap Soap = new HttpConnSoap();
public static Connection getConnection() {
Connection con = null;
try {
//Class.forName("org.gjt.mm.mysql.Driver");
//con=DriverManager.getConnection("jdbc:mysql://192.168.0.106:3306/test?useUnicode=true&characterEncoding=UTF-8","root","initial");
} catch (Exception e) {
//e.printStackTrace();
}
return con;
}
/**
* 获取所有货物的信息
*
* @return
*/
public List<HashMap<String, String>> getAllInfo() {
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
arrayList.clear();
brrayList.clear();
crrayList.clear();
crrayList = Soap.GetWebServre("selectAllCargoInfor", arrayList, brrayList);
HashMap<String, String> tempHash = new HashMap<String, String>();
tempHash.put("Cno", "Cno");
tempHash.put("Cname", "Cname");
tempHash.put("Cnum", "Cnum");
list.add(tempHash);
for (int j = 0; j < crrayList.size(); j += 3) {
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("Cno", crrayList.get(j));
hashMap.put("Cname", crrayList.get(j + 1));
hashMap.put("Cnum", crrayList.get(j + 2));
list.add(hashMap);
}
return list;
}
/**
* 增加一条货物信息
*
* @return
*/
public void insertCargoInfo(String Cname, String Cnum) {
arrayList.clear();
brrayList.clear();
arrayList.add("Cname");
arrayList.add("Cnum");
brrayList.add(Cname);
brrayList.add(Cnum);
Soap.GetWebServre("insertCargoInfo", arrayList, brrayList);
}
/**
* 删除一条货物信息
*
* @return
*/
public void deleteCargoInfo(String Cno) {
arrayList.clear();
brrayList.clear();
arrayList.add("Cno");
brrayList.add(Cno);
Soap.GetWebServre("deleteCargoInfo", arrayList, brrayList);
}
}
package com.bottle.stockmanage; import java.sql.Connection; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class DBUtil { private ArrayList<String> arrayList = new ArrayList<String>(); private ArrayList<String> brrayList = new ArrayList<String>(); private ArrayList<String> crrayList = new ArrayList<String>(); private HttpConnSoap Soap = new HttpConnSoap(); public static Connection getConnection() { Connection con = null; try { //Class.forName("org.gjt.mm.mysql.Driver"); //con=DriverManager.getConnection("jdbc:mysql://192.168.0.106:3306/test?useUnicode=true&characterEncoding=UTF-8","root","initial"); } catch (Exception e) { //e.printStackTrace(); } return con; } /** * 获取所有货物的信息 * * @return */ public List<HashMap<String, String>> getAllInfo() { List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); arrayList.clear(); brrayList.clear(); crrayList.clear(); crrayList = Soap.GetWebServre("selectAllCargoInfor", arrayList, brrayList); HashMap<String, String> tempHash = new HashMap<String, String>(); tempHash.put("Cno", "Cno"); tempHash.put("Cname", "Cname"); tempHash.put("Cnum", "Cnum"); list.add(tempHash); for (int j = 0; j < crrayList.size(); j += 3) { HashMap<String, String> hashMap = new HashMap<String, String>(); hashMap.put("Cno", crrayList.get(j)); hashMap.put("Cname", crrayList.get(j + 1)); hashMap.put("Cnum", crrayList.get(j + 2)); list.add(hashMap); } return list; } /** * 增加一条货物信息 * * @return */ public void insertCargoInfo(String Cname, String Cnum) { arrayList.clear(); brrayList.clear(); arrayList.add("Cname"); arrayList.add("Cnum"); brrayList.add(Cname); brrayList.add(Cnum); Soap.GetWebServre("insertCargoInfo", arrayList, brrayList); } /** * 删除一条货物信息 * * @return */ public void deleteCargoInfo(String Cno) { arrayList.clear(); brrayList.clear(); arrayList.add("Cno"); brrayList.add(Cno); Soap.GetWebServre("deleteCargoInfo", arrayList, brrayList); } }
4.activity_main.xml
[html]
view plaincopyprint?
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone" >
</ListView>
<Button
android:id="@+id/btn_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/btn_add"
android:layout_alignLeft="@+id/btn_add"
android:layout_marginBottom="10dip"
android:text="@string/btn1" />
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/btn2" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/btn_add"
android:layout_below="@+id/btn_add"
android:layout_marginTop="10dip"
android:text="@string/btn3" />
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/listView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="gone" > </ListView> <Button android:id="@+id/btn_all" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/btn_add" android:layout_alignLeft="@+id/btn_add" android:layout_marginBottom="10dip" android:text="@string/btn1" /> <Button android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/btn2" /> <Button android:id="@+id/btn_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/btn_add" android:layout_below="@+id/btn_add" android:layout_marginTop="10dip" android:text="@string/btn3" /> </RelativeLayout>
5.adapter_item.xml
[html]
view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:gravity="center" >
<TableRow
android:id="@+id/classroom_detail_item_tableRow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<TextView
android:id="@+id/txt_Cno"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:height="40dp"
android:textSize="14sp" >
</TextView>
<TextView
android:id="@+id/txt_Cname"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:height="40dp"
android:textSize="14sp" >
</TextView>
<TextView
android:id="@+id/txt_Cnum"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:height="40dp"
android:textSize="14sp" >
</TextView>
</TableRow>
</TableLayout>
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:gravity="center" > <TableRow android:id="@+id/classroom_detail_item_tableRow" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" > <TextView android:id="@+id/txt_Cno" android:layout_width="80dp" android:layout_height="wrap_content" android:gravity="center" android:height="40dp" android:textSize="14sp" > </TextView> <TextView android:id="@+id/txt_Cname" android:layout_width="80dp" android:layout_height="wrap_content" android:gravity="center" android:height="40dp" android:textSize="14sp" > </TextView> <TextView android:id="@+id/txt_Cnum" android:layout_width="80dp" android:layout_height="wrap_content" android:gravity="center" android:height="40dp" android:textSize="14sp" > </TextView> </TableRow> </TableLayout>
6.dialog_add.xml
[html]
view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/add_hint1" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/editText2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/add_hint2"
android:inputType="number" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:text="@string/confirm" />
<Button
android:id="@+id/button2"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="40dip"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <EditText android:id="@+id/editText1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/add_hint1" > <requestFocus /> </EditText> <EditText android:id="@+id/editText2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/add_hint2" android:inputType="number" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/button1" android:layout_width="100dip" android:layout_height="wrap_content" android:layout_marginLeft="20dip" android:text="@string/confirm" /> <Button android:id="@+id/button2" android:layout_width="100dip" android:layout_height="wrap_content" android:layout_marginLeft="40dip" android:text="@string/cancel" /> </LinearLayout> </LinearLayout>
7.dialog_delete.xml
[html]
view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/delete_hint" >
<requestFocus />
</EditText>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:text="@string/confirm" />
<Button
android:id="@+id/button2"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="40dip"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <EditText android:id="@+id/editText1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/delete_hint" > <requestFocus /> </EditText> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/button1" android:layout_width="100dip" android:layout_height="wrap_content" android:layout_marginLeft="20dip" android:text="@string/confirm" /> <Button android:id="@+id/button2" android:layout_width="100dip" android:layout_height="wrap_content" android:layout_marginLeft="40dip" android:text="@string/cancel" /> </LinearLayout> </LinearLayout>
8.strings.xml
[html]
view plaincopyprint?
<resources> <string name="app_name">StockManagement</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">MainActivity</string> <string name="btn1">查看所有货物信息</string> <string name="btn2">增加一条货物信息</string> <string name="btn3">删除一条货物信息</string> <string name="add_hint1">输入添加的货物的名称</string> <string name="add_hint2">输入货物的数量</string> <string name="confirm">确定</string> <string name="cancel">取消</string> <string name="delete_hint">输入删除的货物的编号</string> </resources>
<resources> <string name="app_name">StockManagement</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">MainActivity</string> <string name="btn1">查看所有货物信息</string> <string name="btn2">增加一条货物信息</string> <string name="btn3">删除一条货物信息</string> <string name="add_hint1">输入添加的货物的名称</string> <string name="add_hint2">输入货物的数量</string> <string name="confirm">确定</string> <string name="cancel">取消</string> <string name="delete_hint">输入删除的货物的编号</string> </resources>
9.Manifest.xml
[html]
view plaincopyprint?
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bottle.stockmanage" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bottle.stockmanage" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
运行程序的效果如下图所示:
再说一下IIS,如果只是在本地进行测试等操作,是不需要使用到IIS的,但是如果想发布出去,就要配置一下IIS。
好啦,基本就是这样了。程序不是完善的,但大概的思路就是这样,用到的技术也大概就是这几样,但是每一样拿出来都够学一阵的了。
--->2012.12.02 增加内容
附上本文demo的CSDN下载地址
http://download.csdn.net/detail/zhyl8157121/4836107
--->2013.01.08 增加内容
解释一下android端如何和webservice通信的。(如何修改实例程序)
具体的更深层的东西已经在HttpSoap中封装好了,所以大家使用的时候可以直接用这个类就可以了。(我也不懂是怎么实现的……)
android调用的方法就是如DBUtil中那样,比如
其中arrayList中和brrayList中分别存放对应的webservice中“selectAllCargoInfor”方法的参数名和参数的值。
由于webservice中的selectAllCargoInfo方法的参数为空,所以对应的,android端调用的时候,arrayList和brrayList的值就是空的。
所以大家在使用的时候,只需要将webservice中的方法写好,然后写好DBUtil中的调用参数即可。
--->2013.03.23 增加内容
如果获取值为空,可能是返回值是复杂类型造成的,可以参考:/article/8101849.html
相关文章推荐
- Android连接SQLServer详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程以及所遇到的问题解答(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android连接SQLServer详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android连接SQLServer详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android连接SQLServer详细教程(数据库+服务器+客户端)
- Android连接SQLServer详细教程(数据库+服务器+客户端),并在微软Azure云上搭建云服务
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- Android连接SQLServer详细教程(数据库+服务器+客户端)