http://blog.csdn.net/zhyl8157121/article/details/8169172 http://blog.csdn.net/zhyl8157121/article/details/8169172 其实之前发过一篇这样的博文http://blog.csdn.net/zhyl8157121/article/details/7709552,但那个只是简单记录了一些自己的想法,并没有
http://blog.csdn.net/zhyl8157121/article/details/8169172
http://blog.csdn.net/zhyl8157121/article/details/8169172
其实之前发过一篇这样的博文http://blog.csdn.net/zhyl8157121/article/details/7709552,但那个只是简单记录了一些自己的想法,并没有想作为教程来看,后来由于一些朋友想要源代码,就附上了下载地址,但并没有做什么讲解,从现在开始,准备做一份详细的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 { /// /// 一个操作数据库的类,所有对sqlserver的操作都写在这个类中,使用的时候实例化一个然后直接调用就可以 /// 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; } } /// /// 获取所有货物的信息 /// /// 所有货物信息 public liststring> selectallcargoinfor() { liststring> list = new liststring>(); 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; } /// /// 增加一条货物信息 /// /// 货物名称 /// 货物数量 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; } } /// /// 删除一条货物信息 /// /// 货物编号 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 { /// /// service1 的摘要说明 /// [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> list = new arraylist>(); 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
(改类已经过时,更多请参照
http://blog.csdn.net/zhyl8157121/article/details/8709048)
[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 getwebservre(string methodname, arraylist parameters, arraylist parvalues) { arraylist values = new arraylist(); //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 = + + ; string tps, vps, ts; string mreakstring = ; mreakstring = + methodname + xmlns=\http://tempuri.org/\>; for (int i = 0; i tps = parameters.get(i).tostring(); //设置该方法的参数为.net webservice中的参数名称 vps = parvalues.get(i).tostring(); ts = + tps + > + vps + + tps + >; mreakstring = mreakstring + ts; } mreakstring = mreakstring + + methodname + >; /* + +string11661 +string111 + */ string soap2 = ; string requestdata = soap + mreakstring + soap2; //system.out.println(requestdata); try { &nb