首先说一下背景,由于目前个人自学Android Studio,参考度娘实现连接DB的方式,总结出目前主流的两种方式:
1)使用jtds直接访问DB数据库(参考:https://blog.csdn.net/feidie436/article/details/77532194/)方式
2)另外一种就是比较主流的以webservice方式进行远程访问数据库,使用ksoap2进行数据读取及GSON进行数据解析
但是jtds目前有点弊端,建议局域网,少数人使用。所以这次主要以Android Studio+webservice+ksoap2+GSON的方式读取数据进行总结归纳
开发环境
1、windows 10专业版本X64(破解版,需要安装IIS,度娘上面有很多安装IIS的教程)
2、Visual Studio 2013旗舰版(又是盗版,穷逼一个,需要进行部署webservice)
3、Android Studio(这个是正版,需要ksoap2-android-assembly-3.6.4-jar-with-dependencies.jar(这个需要自己下载,可以进行ksoap2的官网下载,CSDN的资源下载太贵,伤不起,然后放在android项目libs目录下导入Android Studio到)和导入Android Studio自带的com.google.code.gson:gson2.8.5和GsonFormat,度娘上面有很多如何从Android Studio自动添加gson和GsonFormat的方法,这边就不细说了,另外gson的版本可能不一样,但是我现在Android Studio3.3.2的自带是gson2.8.5,这些都不重要,用法都是一样的,另外还需用到AsyncTask异步多线程,Android 不能在主线程直接访问数据库,必须用到异步才能进行)
4、SQL Server 2008 R2版本的(网上找的破解版,挺好用的)
实现逻辑
第一步:安装SQL Server 2008 R2,Visual Studio 2013,Android Studio,
因为是盗版的windows系统,在安装系统环境的时候遇到各种问题,比如windows没有IIS组件,比如在运行Visual Studio 2013的时候报错:内存被占用,最坑的一次是,什么都安装完了,还免费激活400年…结果第3天,系统变未激活,系统还原初始状态,系统Patch参数全部清空,SQL Server 2008 R2及多个软件不能启动…不过还好,最后终于找到一个系统版本,免费激活180天的,一直用到了现在,所以想吐槽一下,那些GHOST系统版本的,能不能不要精简了。
第二步:Visual Studio 2013创建个空网站,新建webserver服务,访问及操作数据库
1)Visual Studio 2013新建一个空白网站
2)新建项目->Web服务(ASMX)
3)配置Web.config
add name=“conn_data” connectionString=“server=.;database=testDB;user id=sa;password=618531;Max Pool Size=50000;Min Pool Size=2;Pooling=true;Connect Timeout=60000;” providerName=“System.Data.SqlClient”
4)编写SQLHelper.cs文件用来进行数据库操作
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace DBUtility
{
///
/// 数据库访问类,
///
public class SQLHelper
{
#region 全局变量定义
private static SQLHelper sqldb;
///
/// 定义数据库链接字符串
///
private string sqlConnStr = “”;
private SqlConnection con;
#endregion
#region
///
/// 根据默认连接字符串实例化
///
public SQLHelper()
{
sqlConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["conn_data"].ToString();
}
///
/// 根据指定数据库链接字符串实例化
///
/// 指定数据库链接字符串值
public SQLHelper(string connectionName)
{
sqlConnStr = System.Configuration.ConfigurationManager.ConnectionStrings[connectionName].ToString();
}
#endregion
#region
///
/// 创建SqlHelper的对象(默认数据库链接connName=conn_data)
///
/// sqlhelper实例
public static SQLHelper CreateSQLHelper()
{
if (sqldb == null)
{
sqldb = new SQLHelper();
return sqldb;
}
else
{
return sqldb;
}
}
///
/// 创建SqlHelper的对象(指定数据库链接connName=自定义的非'conn_data')
///
/// 数据库链接字符串在config中的键值名称
/// sqlhelper实例
public static SQLHelper CreateSQLHelper(string connectionName)
{
//如需要用到,可能会修改对象名,否则无法真正重载此函数(sqldb不为空)
if (sqldb == null)
{
sqldb = new SQLHelper(connectionName);
return sqldb;
}
else
{
return sqldb;
}
}
#endregion
#region
///
/// 连接数据库对象及数据库链接操作
///
public SqlConnection CreateConnecton()
{
string connstr = sqlConnStr;// System.Configuration.ConfigurationManager.ConnectionStrings["conn_data"].ToString();
try
{
con = new SqlConnection(connstr);
}
catch (SqlException ex)
{
throw ex;
}
return con;
}
///
/// 打开数据库链接
///
private void ConnOpen()
{
if (con.State != ConnectionState.Open)
{
con.Open();
}
}
///
/// 关闭数据库链接 同时释放sqlconnection资源
///
private void ConnClose()
{
if (con.State == ConnectionState.Open)
{
con.Close();
con.Dispose();
}
else
{
con.Dispose();
}
}
#endregion
#region
#region
///
/// 执行不带参数的sql语句,更新数据库返回受影响的行数
///
/// T-SQL语句
///
public int TSQLExecuteNonQuery(string cmdText)
{
return TSQLExecuteNonQuery(cmdText, null);
}
///
/// 执行带参数的sql语句,更新数据库返回受影响的行数
///
/// T-SQL语句
/// 一组用于执行命令的参数
///
public int TSQLExecuteNonQuery(string cmdText, params SqlParameter[] commandParameters)
{
int val = 0;
try
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
//conn = CreateConnecton();
PrepareCommand(cmd, null, CommandType.Text, cmdText, commandParameters,conn);
val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return val;
}
}
catch(SqlException ex)
{
//ConnClose();
throw ex;
}
return val;
}
#endregion
#region
///
/// 执行不带参数的存储过程,更新数据库并返回受影响的行数
///
/// 存储过程名称
/// 返回受影响的行数
public int PROCExecuteNonQuery(string procName)
{
return PROCExecuteNonQuery(procName,null,null);
}
///
/// 执行带参数的存储过程,更新数据库并返回受影响的行数
///
/// 存储过程名称
/// 一组用于执行命令的参数
/// 返回受影响的行数
public int PROCExecuteNonQuery(string procName, params SqlParameter[] commandParameters)
{
return PROCExecuteNonQuery(procName, 0, commandParameters);
}
///
/// 执行带参数的存储过程,更新数据库并返回受影响的行数
///
/// 存储过程名称
/// 设置执行存储过程的时间 单位(秒)
/// 一组用于执行命令的参数
/// 返回受影响的行数
public int PROCExecuteNonQuery(string procName,int times, params SqlParameter[] commandParameters)
{
int val = 0;
try
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn = CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.StoredProcedure, procName, commandParameters,times,conn);
val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return val;
}
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
return val;
}
#endregion
#endregion
#region
#region
///
/// 执行不带参数的SQL语句,返回结果为DataTable
///
/// T-SQL 命令
/// 一个包含返回结果集的DataTable
public DataTable TSQLExecuteDataTable(string cmdText)
{
return TSQLExecuteDataTable(cmdText, null);
}
///
/// 执行带参数的SQL语句,返回结果为DataTable
///
/// T-SQL 命令
/// 一组用于执行命令的参数
/// 一个包含返回结果集的DataTable
public DataTable TSQLExecuteDataTable(string cmdText, params SqlParameter[] commandParameters)
{
DataTable dtbl = new DataTable();
try
{
//conn = CreateConnecton();
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.Text, cmdText, commandParameters,conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dtbl);
da.Dispose();
//ConnClose();
}
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
return dtbl;
}
///
/// 执行不带参数的SQL语句,返回结果为DataSet
///
/// T-SQL 命令
/// 一个包含返回结果集的DataSet
public DataSet TSQLExecuteDataSet(string cmdText)
{
return TSQLExecuteDataSet(cmdText, null);
}
///
/// 执行带参数的SQL语句,返回结果为DataSet
///
/// T-SQL 命令
/// 一组用于执行命令的参数
/// 一个包含返回结果集的DataSet
public DataSet TSQLExecuteDataSet(string cmdText, params SqlParameter[] commandParameters)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable("0");
try
{
//conn = CreateConnecton();
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.Text, cmdText, commandParameters,conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
da.Dispose();
//ConnClose();
}
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
ds.Tables.Add(dt);
return ds;
}
///
/// 执行不带参数的SQL语句,返回结果为DataReader
///
/// T-SQL语句
/// 返回类型为datareader的结果集
public SqlDataReader TSQLExecuteReader(string cmdText)
{
SqlDataReader sdr = TSQLExecuteReader(cmdText, null);
return sdr;
}
///
/// 执行带参数的SQL语句,返回结果为DataReader
///
/// T-SQL语句
/// 一组用于执行命令的参数
/// 返回类型为datareader的结果集
public SqlDataReader TSQLExecuteReader(string cmdText, params SqlParameter[] commandParameters)
{
try
{
SqlCommand cmd = new SqlCommand();
SqlConnection conn = CreateConnecton();
//{
//conn = CreateConnecton();
PrepareCommand(cmd, null, CommandType.Text, cmdText, commandParameters,conn);
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
//rdr.Dispose();
//ConnClose();
return rdr;
//}
}
catch (Exception ex)
{
//ConnClose();
throw ex;
}
}
///
/// 执行不带参数的sql语句,返回首行首列值,忽略其他行
///
/// T-SQL命令
///
public object TSQLExecuteScalar(string cmdText)
{
return TSQLExecuteScalar(cmdText, null);
}
///
/// 执行带参数的sql语句,返回首行首列值,忽略其他行
///
/// T-SQL命令
/// 一组用于执行命令的参数
///
public object TSQLExecuteScalar(string cmdText, params SqlParameter[] commandParameters)
{
object obj = null;
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
try
{
//conn = CreateConnecton();
PrepareCommand(cmd, null, CommandType.Text, cmdText, commandParameters,conn);
obj = cmd.ExecuteScalar();
cmd.Parameters.Clear();
//ConnClose();
}
catch (SqlException ex)
{
throw ex;
}
}
return obj;
}
#endregion
#region
///
/// 执行不带参数的存储过程,返回结果为DataTable
///
/// 存储过程名称
/// 一个包含返回结果集的DataTable
public DataTable PROCExecuteDataTable(string procName)
{
return TSQLExecuteDataTable(procName, null,null);
}
///
/// 执行带参数的存储过程,返回结果为DataTable
///
/// 存储过程名称
/// 一组用于执行命令的参数
/// 一个包含返回结果集的DataTable
public DataTable PROCExecuteDataTable(string procName, params SqlParameter[] commandParameters)
{
return PROCExecuteDataTable(procName, 0, commandParameters);
}
///
/// 执行带参数的存储过程,返回结果为DataTable
///
/// 存储过程名称
/// 设置执行存储过程的时间 单位(秒)
/// 一组用于执行命令的参数
/// 一个包含返回结果集的DataTable
public DataTable PROCExecuteDataTable(string procName,int times, params SqlParameter[] commandParameters)
{
DataTable dtbl = new DataTable();
try
{
//conn = CreateConnecton();
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.StoredProcedure, procName, commandParameters,times,conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dtbl);
da.Dispose();
//ConnClose();
}
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
return dtbl;
}
///
/// 执行带有返回值的存储过程
///
/// 存储过程名
/// 输入参数
/// 存储过程Output参数名称
///
public string RunProcReturn(string procName, SqlParameter[] param,string outparam)
{
string retstr = "";
try
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn = CreateConnecton())
{
cmd.Connection = conn;
conn.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = procName;
if (param != null)
{
foreach (SqlParameter sp in param)
{
cmd.Parameters.Add(sp);
}
}
SqlParameter sp1 = cmd.Parameters.Add(outparam,SqlDbType.VarChar,500);
sp1.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
retstr = Convert.ToString(sp1.Value);
}
}
catch (Exception ex)
{
throw ex;
}
return retstr;
}
///
/// 执行不带参数的存储过程,返回结果为DataSet
///
/// 存储过程名称
/// 一个包含返回结果集的DataSet
public DataSet PROCExecuteDataSet(string procName)
{
return PROCExecuteDataSet(procName, 0,null);
}
///
/// 执行带参数的存储过程,返回结果为DataSet
///
/// 存储过程名称
/// 一组用于执行命令的参数
/// 一个包含返回结果集的DataSet
public DataSet PROCExecuteDataSet(string procName, params SqlParameter[] commandParameters)
{
return PROCExecuteDataSet(procName, 0, commandParameters);
}
///
/// 执行带参数的存储过程,返回结果为DataSet
///
/// 存储过程名称
/// 设置执行存储过程的时间 单位(秒)
/// 一组用于执行命令的参数
/// 一个包含返回结果集的DataSet
public DataSet PROCExecuteDataSet(string procName,int times, params SqlParameter[] commandParameters)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable("0");
try
{
//conn = CreateConnecton();
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.Text, procName, commandParameters,times,conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
da.Dispose();
//ConnClose();
}
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
ds.Tables.Add(dt);
return ds;
}
///
/// 执行不带参数的存储过程,返回结果为DataReader
///
///
///
public SqlDataReader PROCExecuteReader(string procName)
{
return PROCExecuteReader(procName, 0 ,null);
}
///
/// 执行带参数的存储过程,返回结果为DataReader
///
/// 存储过程名称
/// 一组用于执行命令的参数
///
public SqlDataReader PROCExecuteReader(string procName, params SqlParameter[] commandParameters)
{
return PROCExecuteReader(procName, 0, commandParameters);
}
///
/// 执行带参数的存储过程,返回结果为DataReader
///
/// 存储过程名称
/// 设置存储过程执行的时间 单位(秒)
/// 一组用于执行命令的参数
///
public SqlDataReader PROCExecuteReader(string procName,int times, params SqlParameter[] commandParameters)
{
try
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.StoredProcedure, procName, commandParameters,times,conn);
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
rdr.Dispose();
//ConnClose();
return rdr;
}
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
}
///
/// 执行不带参数的存储过程,返回结果为object
///
/// 存储过程名称
///
public object PROCExecuteScalar(string procName)
{
return PROCExecuteScalar(procName, 0,null);
}
///
/// 执行带参数的存储过程,返回结果为object
///
/// 存储过程名称
/// 一组用于执行sql命令的参数
///
public object PROCExecuteScalar(string procName, params SqlParameter[] commandParameters)
{
return PROCExecuteScalar(procName, 0,commandParameters);
}
///
/// 执行带参数的存储过程,返回结果为object
///
/// 存储过程名称
/// 设置存储过程执行的时间 单位(秒)
/// 一组用于执行sql命令的参数
///
public object PROCExecuteScalar(string procName,int times, params SqlParameter[] commandParameters)
{
object obj = null;
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
try
{
PrepareCommand(cmd, null, CommandType.StoredProcedure, procName, commandParameters,conn);
obj = cmd.ExecuteScalar();
cmd.Parameters.Clear();
//ConnClose();
}
catch (SqlException ex)
{
//ConnClose();
throw ex;
}
}
return obj;
}
#endregion
#endregion
#region
#region
//public int ExcuteSQL(string cmdText, SqlCommand cmd)
//{
// int val = 0;
// //conn = CreateConnecton();
// //PrepareCommand(cmd, null, CommandType.Text, cmdText, null);
// cmd.CommandText = cmdText;
// val = cmd.ExecuteNonQuery();
// cmd.Parameters.Clear();
// return val;
//}
//public DataTable MyTest(string cmdText, SqlCommand cmd)
//{
// DataTable dt = new DataTable();
// //PrepareCommand(cmd, null, CommandType.Text, cmdText, null);
// cmd.CommandText = cmdText;
// SqlDataAdapter da = new SqlDataAdapter(cmd);
// da.Fill(dt);
// da.Dispose();
// //ConnClose();
// return dt;
//}
#endregion
#region
///
/// 执行多条sql语句的事物处理
///
/// sql语句列表
///
public int ExecuteTranSqlList(List sqlList)
{
SqlConnection conn = CreateConnecton();
ConnOpen();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
SqlTransaction tran = conn.BeginTransaction();
cmd.Transaction = tran;
try
{
int count = 0;
for (int i = 0; i < sqlList.Count; i++)
{
string strsql = sqlList[i];
if (strsql.Trim().Length > 1)
{
cmd.CommandText = strsql;
count += cmd.ExecuteNonQuery();
}
}
tran.Commit();
return count;
}
catch (SqlException ex)
{
tran.Rollback();
ConnClose();
return 0;
}
}
///
/// 执行多条sql语句的事物处理,params参数为第一条sql语句使用
///
///
///
///
public int ExecuteTranSqlList(List sqlList, string strLast, params SqlParameter[] commandParameters)
{
SqlConnection conn = CreateConnecton();
ConnOpen();
SqlTransaction tran = conn.BeginTransaction();
try
{
SqlCommand cmd = new SqlCommand("", conn, tran);
cmd.CommandType = CommandType.Text;
int count = 0;
for (int i = 0; i < sqlList.Count; i++)
{
string strSql = sqlList[i];
if (strSql.Trim().Length > 1)
{
if (i == 0)
{
cmd.CommandText = strSql;
if (commandParameters != null)
{
foreach (SqlParameter parm in commandParameters)
cmd.Parameters.Add(parm);
}
count = int.Parse(cmd.ExecuteScalar().ToString());
cmd.Parameters.Clear();
}
else
{
if (strLast == "")
{
cmd.CommandText = strSql;
cmd.ExecuteNonQuery();
}
else
{
cmd.CommandText = strSql + count + strLast;
cmd.ExecuteNonQuery();
}
}
}
}
tran.Commit();
return count;
}
catch (SqlException ex)
{
tran.Rollback();
ConnClose();
return 0;
}
}
#endregion
#region
///
/// 判断表中是否存在某个字段
///
/// 字段名
/// 表名
/// true则表示存在,false表示不存在
public bool DiscoverValidOFColumn(string columnName, string tableName)
{
object res = null;
string sql = "select count(1) from syscolumns where [id]=object_id('" + tableName + "') and [name] ='" + columnName + "'";
try
{
res = TSQLExecuteScalar(sql);
}
catch (SqlException ex)
{
throw ex;
}
if (res == null)
{
return false;
}
return Convert.ToInt32(res) > 0;
}
///
/// 检查数据表是否存在
///
/// 表名
///
public bool TableIsExist(string tableName)
{
bool blRet = false;
DataTable dtRet = TSQLExecuteDataTable("Select * From sysobjects Where name='" + tableName + "'");
if (dtRet != null && dtRet.Rows.Count >= 1) { blRet = true; }
return blRet;
}
#endregion
#region
///
/// 有数据返回true
///
/// sql
/// 大于0返回true
public bool Exists(string cmdText)
{
return Exists(cmdText, null);
}
///
/// 获取指表的第一行中指定列的值
///
/// 指定列名
/// 指定表名
/// sql条件语句(不包含‘where’关键字)例如‘1=1’
///
public object GetFirstRowAndColumn(string columnName, string tableName, string conditionsValue)
{
string cmdText = "select " + columnName + " from " + tableName + " where " + conditionsValue;
object obj = null;
DataTable dt = new DataTable();
try
{
//conn = CreateConnecton();
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn=CreateConnecton())
{
PrepareCommand(cmd, null, CommandType.Text, cmdText, null,conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
da.Dispose();
obj = dt.Rows[0][0];
ConnClose();
}
}
catch (SqlException ex)
{
ConnClose();
throw ex;
}
return obj;
}
#endregion
///
/// 有数据返回true
///
/// sql
/// 参数
/// 大于0返回true
public bool Exists(string cmdText, params SqlParameter[] commandParameters)
{
SqlConnection conn = CreateConnecton();
ConnOpen();
bool val;
try
{
int colvalue = int.Parse(TSQLExecuteScalar(cmdText, commandParameters).ToString());
if (colvalue > 0)
val = true;
else
val = false;
}
catch
{
val = false;
}
finally
{
ConnClose();
}
return val;
}
#endregion
#region 封装 参数
///
/// Prepare a command for execution
///
/// SqlCommand object
/// SqlConnection object
/// SqlTransaction object
/// Cmd type e.g. stored procedure or text
/// Command text, e.g. Select * from Products
/// SqlParameters to use in the command
private void PrepareCommand(SqlCommand cmd, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms,SqlConnection conn)
{
//ConnOpen();
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
cmd.CommandText = cmdText;
if (trans != null)
cmd.Transaction = trans;
cmd.CommandType = cmdType;
if (cmdParms != null)
{
foreach (SqlParameter parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
///
/// 新增超时判断的重载
///
/// SqlCommand object
/// SqlConnection object
/// SqlTransaction object
/// Cmd type e.g. stored procedure or text
/// Command text, e.g. Select * from Products
/// SqlParameters to use in the command
/// 设置连接执行的响应时间 单位为秒
private void PrepareCommand(SqlCommand cmd, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms,int times,SqlConnection conn)
{
//ConnOpen();
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
cmd.CommandText = cmdText;
if (trans != null)
cmd.Transaction = trans;
if (times != 0)
cmd.CommandTimeout = times;
cmd.CommandType = cmdType;
if (cmdParms != null)
{
foreach (SqlParameter parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
#endregion
}
}
5)编写AndroidWebServer.asmx逻辑读取或操作数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
using System.Data.SqlClient;
using DBUtility;
///
/// AndroidWebServer 的摘要说明
///
[WebService(Namespace = “http://tempuri.org/”)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class AndroidWebServer : System.Web.Services.WebService {
public AndroidWebServer () {
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
[WebMethod(Description = "查询测试")]
public DataSet GetSelectDS(string sql)
{
SQLHelper db = new SQLHelper();
DataSet ds = db.TSQLExecuteDataSet(sql);
return ds;
}
[WebMethod(Description = "数据库的增、删、改更新操作")]
public int SetExecuteNonQuery(string sql)
{
SQLHelper db = new SQLHelper();
int ExecuteCounts = db.TSQLExecuteNonQuery(sql);
return ExecuteCounts;
}
}
6)运行调试
(注意:Andorid获取的数据最好是DataSet格式,不然可能导致失败,该webservers比较简单,主要用在测试,到时andorid可以直接写Select或insert,update,delete等SQL语句进行获取或操作数据,当然也可以用存储过程写在webserver里面进行逻辑操作,关于这个已经全部包含在SQLHelper.cs里面,直接调用就可以了)
第三步:进行Android Studio进行webservers访问及数据转换处理
1)在ksoap2官网下载最新的ksoap2.jar(ksoap2主要是用来链接webservers及基础的webservers XML数据处理),官网直接问度娘把,我已经忘记地址了,至于版本直接在官网下载最新的就可以了,我当时下载的版本是ksoap2-android-assembly-3.6.4-jar-with-dependencies,下载好的内容直接复制到Android Studio自己项目的Libs里面,复制完后右键点击新黏贴的jar,在弹出菜单中点击Add As Library,如何还是不会的童靴门可以参照度娘:AndroidStudio怎样导入jar包
2)在Android Studio导入自带的com.google.code.gson:gson2.8.5和GsonFormat,也可以参照度娘:在Android Studio中如何添加GSON 并使用GsonFormat快速实现实体类
3)创建测试java实体类,先创建一个空白的Java Class类,然后使用最上方code-Generate-GsonFormat或者Alt+Insert然后选择GsonFormat,把已经格式化好的json复制进来,点击OK就哦了。
我写的是{“id”: “1”, “username”: 6000820,“pwd”: “6000820测试”}
但是还需要在自己生成的实体类里面重写toString()函数,主要是后面用来让:java对象转换为JSON字符串,这部分要自己写
@Override
public String toString() {
return “TestDT [id=” + id + “, username=” + username + “, pwd=” + pwd + “]”; //让java对象转换为JSON字符串
}
4)在android studio里面新建一个空白的Activity窗体用来把数据显示在界面上面,我这边打算做一个简单的返回,点击确认按钮,把数据显示在EditText里面
5)界面画好后,需要创建一个空白的Java Class类,用来继承AsyncTask,AsyncTask是android studio封装好的(Thread+Handler)的线程通信方式,但是AsyncTask目前并不是那么的完美,如果在用于大量并发处理的时候需要各位小心,因为AsyncTask默认线程是SERIAL_EXECUTOR,即按照先后顺序依次调用(假设有两个网路请求,第一个是文件上传,第二个是接口调用,那么接口调用会等待文件下载完毕后执行,而不是立即执行,另外由于顺序模式存在排队的情况,Android提供了executeOnExecutor方法,允许开发者指定任务线程池),不过AsyncTask自带的THREAD_POOL_EXECUTOR也存在瓶颈,该线程池最大线程数是电脑CPU的两倍+1,最大线程SIZE=CPU_COUNT2+1,如果用户手机是双核CPU,那么最大线程数是22+1=5个,因此CPU个数越多,APP运行越流畅是有依据的,不晓得我去年双11花了4000大洋买的HTCU12+烈焰红唇版是多少核的CPU,反正用起来用种丝滑般的感觉,不过想吐槽的是,我怎么双11买了几天后,HTC的手机就下架了,怎么就绝版了呢… 好的直接贴代码,不聊了
package com.example.myapplication;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Message;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;
import com.example.myapplication.DBTable.TestDT;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONObject;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
class DBHelper extends AsyncTask
private String result;
private EditText text;
private List TestDT = new ArrayList();//创建TestDT的实体类
DBHelper(EditText text) //构造函数非常重要,主要用于回调处理的结果内容给予主线程(另外还有一种方式用回调函数可以使用,这边的参数EditText,在主线程的EditText空间,用来显示数据,当然也可以用其他的类型,不是必须要用EditText,可以自己定义)
{
this.text = text;
}
@Override
//该方法是执行AsyncTask的时候,实现逻辑的方法
protected String doInBackground(String[] params) {
try {
result = getRemoteInfo(params[0]);
} catch (Exception e) {
e.printStackTrace();
}
//将结果返回给onPostExecute方法
return result;
}
@Override
//此方法可以在主线程改变UI,主要是进行返回结果到主线程
protected void onPostExecute(String msg) {
super.onPostExecute(msg);
if (msg != null) {
text.setText(msg);
} else {
text.setText("查询不到数据~~~");
}
}
/**
* 测试Webserver访问数据库查询及编辑DB
*
* @param sSQL SQL查询语句
*/
public String getRemoteInfo(String sSQL) throws Exception {
String WSDL_URI = "http://192.168.0.101/AndroidWebServer.asmx";//wsdl 的uri (这个是自己PC IIS发布的webserver网站地址)
String namespace = "http://tempuri.org/";//namespace
String methodName = "GetSelectDS";//要调用的方法名称(这个是IIS发布的webserver网站,需要调用的方法,我们前面的例子有GetSelectDS和SetExecuteNonQuery方法)
SoapObject request = new SoapObject(namespace, methodName);
// 设置需调用WebService接口需要传入的两个参数mobileCode、userId
request.addProperty("sql", sSQL);
//创建SoapSerializationEnvelope 对象,同时指定soap版本号(之前在wsdl中看到的)
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapSerializationEnvelope.VER12);
envelope.bodyOut = request;//由于是发送请求,所以是设置bodyOut
envelope.dotNet = true;//由于是.net开发的webservice,所以这里要设置为true
HttpTransportSE httpTransportSE = new HttpTransportSE(WSDL_URI);
httpTransportSE.call(null, envelope);//调用0
Gson gson = new Gson(); //创建Gson对象
// 获取返回的数据
// SoapObject object = (SoapObject) envelope.bodyIn;
// Object object = (Object) envelope.getResponse();
SoapObject object = (SoapObject) envelope.getResponse();
if (envelope.getResponse() != null) {
SoapObject soapObject = (SoapObject) envelope.bodyIn;
SoapObject soap1 = (SoapObject) soapObject.getProperty("GetSelectDSResult");//此时的获取到的信息是 (获取webserver的调用的方法名称)
SoapObject soapChilds = (SoapObject) soap1.getProperty(1);//因为0位置对我们来说没有数据,所以我们去1位置的信息
SoapObject soap2 = (SoapObject) soapChilds.getProperty(0);//去掉了前面的部分anyType
if (TestDT.size() > 0) {//对实体类进行clear作业
TestDT.clear();
}
for (int i = 0; i < soap2.getPropertyCount(); i++) {
SoapObject soap3 = (SoapObject) soap2.getProperty(i);//取出每个视频信息
TestDT film = new TestDT();
film.setId(soap3.getProperty("id").toString());
film.setUsername(soap3.getProperty("username").toString());
film.setPwd(soap3.getProperty("pwd").toString());
TestDT.add(film);//封装后存入集合中
}
}
String objectStr = TestDT.toString();//让java对象转换为LIST字符串
String gsStr = gson.toJson(TestDT);//让java对象转换为Json字符串
result = gsStr;
Log.d("debug", result);
return result;
}
}
6)在前面空白的Activity窗体中,在后台编写调用DBHelper(AsyncTask)的逻辑,实现数据的显示
package com.example.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MyLogin extends AppCompatActivity implements View.OnClickListener {
Button bt;
Button bt2;
EditText edt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_login);
bt = findViewById(R.id.MyLoginBT1);
bt.setOnClickListener(this);
bt2 = findViewById(R.id.MyLoginBT2);
bt2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
EditText ET1 = (EditText) findViewById(R.id.MyLogintv1);
if (v.getId() == R.id.MyLoginBT1) {
ET1.setText("第一次文本框");
sendRequestForListData();
}
if (v.getId() == R.id.MyLoginBT2) {
ET1.setText("第二次文本框");
}
}
private void sendRequestForListData()
{
try {
String sStr="";
edt = (EditText) findViewById(R.id.MyLogintv1);
//启动后台异步线程进行连接webService操作,并且根据返回结果在主线程中改变UI
DBHelper socketConn = new DBHelper(edt);
//启动后台任务
socketConn.execute(" Select * From TestDT ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
7)最后需要在Android Studio打开手机网络访问权限,在AndoridMainifest.xml配置信息中添加
8)启动夜神模拟器,进行最后调试(我没有用Android Studio自带的模拟器,主要是自带的太卡,太不方便,启动也麻烦),夜神模拟器真的很方便,怎么使用可以参照度娘(启动夜神nox_adb.exe connect 127.0.0.1:62001的时候,可以自己写个脚本放在桌面上,把夜神模拟器的安装地址写在系统Patch环境变量中,就可以一键启动模拟器)