在Android开发过程当中,不必定都用本地文件系统或本地数据库SQLite,好比QQ,用户的账号数据都存储远程服务器上。而访问远程数据库有不少种方式,好比HTTPCLIENT,WEBSERVICE,SOCKET等多种方式,即分别为http通讯,webservice(Web服务通讯),还有socket套接字通讯等等,限于篇幅,本文我只讲解讲一下webservice方式。其余方式,在其余的文档再讲。
相信XFire的优势不用多说,google,百度一下就知道了。我这里主要讲解配置过程。配置一个简单的webservice,相信配置了该webservice。
xfire使用接口和接口实现类来实现远程方法提拱。这样能够将接口公布给客户端,但Android提拱了ksoap框架类,一种全新的实现方式,就不须要使用远程接口。只要配置好相关参数和方法便可。
decodeusername=new String(com.base.encry.decry.app.Base64.decode(username));
decodepassword=new String(com.base.encry.decry.app.Base64.decode(password));
本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文连接:http://www.linuxidc.com/Linux/2011-04/35011.htm
Base64算法相信你们都比较熟悉吧,dt.jar已经提拱了具体的实现细节。你能够查阅相关文档和源码,
这里为了让你们费时费力,我贴上代码。
public class Base64 {
private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/' };
private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
-1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
-1, -1 };
public static void main(String[] args) {
String string="徐忠明";
String encodeStr=encode(string.getBytes());
byte[] bytesStr=null;
try {
bytesStr=decode(encodeStr);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(encodeStr);
System.out.println(new String(bytesStr));
}
// 编码
public static String encode(byte[] data) {
StringBuffer sb = new StringBuffer();
int len = data.length;
int i = 0;
int b1, b2, b3;
while (i < len) {
b1 = data[i++] & 0xff;
if (i == len) {
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
sb.append("==");
break;
}
b2 = data[i++] & 0xff;
if (i == len) {
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
sb.append("=");
break;
}
b3 = data[i++] & 0xff;
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(base64EncodeChars[((b2 & 0x0f) << 2)
| ((b3 & 0xc0) >>> 6)]);
sb.append(base64EncodeChars[b3 & 0x3f]);
}
return sb.toString();
}
// 解码
public static byte[] decode(String str) throws UnsupportedEncodingException {
StringBuffer sb = new StringBuffer();
byte[] data = str.getBytes("US-ASCII");
int len = data.length;
int i = 0;
int b1, b2, b3, b4;
while (i < len) {
/* b1 */
do {
b1 = base64DecodeChars[data[i++]];
} while (i < len && b1 == -1);
if (b1 == -1)
break;
/* b2 */
do {
b2 = base64DecodeChars[data[i++]];
} while (i < len && b2 == -1);
if (b2 == -1)
break;
sb.append((char) ((b1 << 2) | ((b2 & 0x30) >>> 4)));
/* b3 */
do {
b3 = data[i++];
if (b3 == 61)
return sb.toString().getBytes("iso8859-1");
b3 = base64DecodeChars[b3];
} while (i < len && b3 == -1);
if (b3 == -1)
break;
sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
/* b4 */
do {
b4 = data[i++];
if (b4 == 61)
return sb.toString().getBytes("iso8859-1");
b4 = base64DecodeChars[b4];
} while (i < len && b4 == -1);
if (b4 == -1)
break;
sb.append((char) (((b3 & 0x03) << 6) | b4));
}
return sb.toString().getBytes("iso8859-1");
}
}
这段代码能够也能够在Android客户端重用,Android端负责加密码,而XFire服务器端负责解密,这样作是为了安全性着想。
你想一想若是不加密码,直接将账号和密码在网络上传输,裸露在Internet中,那是多么的危险,这是用了通用的Base64加密解密码算法也不必定安全。我只是作一个试笵,你们能够根据自已须要来选用自已的加密码算法。好比md5,SHA等等。
还有就是访问数据库的细节,在这里只用了原始了JDBC,固然能够扩展成Hibernate,iBatis.为求简单原始。帖上以下代码:
package com.db.app;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.constants.util.Constants;
import com.sun.corba.se.impl.orbutil.closure.Constant;
public class ConnDB {
public ConnDB(){
}
public Connection getConnection(){
Connection conn=null;
try{
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
}catch (Exception e) {
// TODO: handle exception
}
return conn;
}
/**
* 功能:用户登录验证
* @param username 用户名
* @param password 密码
* @return
* 首先判断是否存在该用户,若是不存在,则返回false,
* 若是存在该用户,则判断密码是否正确,若是不正确,则返回密码输入错误
*/
public int login(String username,String password){
try{
PreparedStatement ps=getConnection().prepareStatement("select * from t_customer where account=?");
ps.setString(1, username);
ResultSet rs=ps.executeQuery();
if(!rs.next()){
return Constants.INVALID_NAME;//"该用户不存在,请输入你的用户名";
}
ps=getConnection().prepareStatement("select * from t_customer where account=? and password=?");
ps.setString(1, username);
ps.setString(2, password);
rs=ps.executeQuery();
if (!rs.next()) {
return Constants.INVALID_PASSWORD;//"密码输入错误,请核对";
}
else
return Constants.VALID_USERNAME_PASSWORD;//"验证经过";
}catch(Exception evt){
evt.printStackTrace();
return Constants.INVALID_DATABASE;//"数据库出现异常,请重试";
}
}
public static void main(String[] args) {
ConnDB connDB=new ConnDB();
System.out.println(connDB.login("fda", "123"));
System.out.println(connDB.login("001", "123456"));
System.out.println(connDB.login("001", "123"));
}
}
不用多说,地球均可以看懂它们。呵呵。
固然要将这个类中的方法发布出去还要有Services.xml文件,这个文件的存储路径为:WebServices目录下。即项目的根目录下面。
代码以下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xfire.codehaus.org/config/1.0">
<!-- 服务一:简单计算,直接输出 -->
<service>
<name>MyService</name>
<serviceClass>test.IAccount</serviceClass>
<implementationClass>test.AccountImp</implementationClass>
<mce:style><!--
wrapped
--></mce:style><style mce_bogus="1">wrapped</style>
<use>literal</use>
<scope>application</scope>
<namespace>http://Android.googlepages.com/</namespace>
</service>
<!--服务二:访问数据库,功能:由用户账号直接获得其密码,若是账号不对则提示从新输入
<service>
<name>MyDbService</name>
<serviceClass>test.IConnDb</serviceClass>
<implementationClass>test.ConnDbImp</implementationClass>
<mce:style><!--
wrapped
--></mce:style><style mce_bogus="1">wrapped</style>
<use>literal</use>
<scope>application</scope>
<namespace>http://Android.googlepages.com/</namespace>
</service>
-->
</beans>
我为了简单,写只了一个MyService服务。你能够根据自已须要添加其余的服务。
固然运行这个还要有一些JAR包的支持。我附图,以下所示:
接下来咱们看看Android客户端。要使用webservice框架,咱们要在classpath中导入D:/学习专题/Android专题/Android例程专题(自定收集)/Android WebService/android/android webservice/ksoap2_android_src.zip。html
这样才能够运行webservicejava
贴上代码:mysql
- package com.cn.blogs.ksoap.app;
- import java.io.IOException;
- import org.kobjects.base64.Base64;
- import org.ksoap2.SoapEnvelope;
- import org.ksoap2.serialization.SoapObject;
- import org.ksoap2.serialization.SoapPrimitive;
- import org.ksoap2.serialization.SoapSerializationEnvelope;
- import org.ksoap2.transport.AndroidHttpTransport;
- import org.ksoap2.transport.HttpTransportSE;
- import org.xmlpull.v1.XmlPullParserException;
- public class MyWebServiceHelper {
- // WSDL文档中的命名空间
- private static final String targetNameSpace ="http://Android.googlepages.com/";
- // WSDL文档中的URL
- private static final String WSDL ="http://10.10.178.70:8888/WSDLApp/services/MyService";
- // 须要调用的方法名(得到Myervices中的helloWorld方法)
- private static final String getHelloworld = "helloWorld";
- //须要调用的方法名(得到Myervices中的login方法)
- private static final String getLogin="login";
- /********
- * 得到自定义WebService XFire框架信息
- *
- * @return
- */
- public static void main(String[] args) {
- MyWebServiceHelper webServiceHelper=newMyWebServiceHelper();
- // System.out.println(webServiceHelper.getHelloworldStr("\"你好,ksoap webservice 框架\""));
- System.out.println(webServiceHelper.getFlagFromDBCust("001","123"));
- }
- public String getHelloworldStr(String string) {
- String str = "";
- SoapObject soapObject = new SoapObject(targetNameSpace,
- getHelloworld);
- soapObject.addProperty("str", string);
- //调用的方法参数与参数值(根据具体须要可选可不选)
- SoapSerializationEnvelope envelope = newSoapSerializationEnvelope(
- SoapEnvelope.VER11);
- envelope.dotNet = false; //不使用dotnet webservice;
- envelope.setOutputSoapObject(soapObject);//envelope.bodyOut=request;
- AndroidHttpTransport httpTranstation = newAndroidHttpTransport(WSDL);
- //HttpTransportSE httpTranstation=new HttpTransportSE(WSDL);
- try {
- httpTranstation.call(targetNameSpace + getHelloworld, envelope);
- SoapPrimitive result = (SoapPrimitive ) envelope.getResponse();
- // 下面对结果进行解析,结构相似json对象
- // str=(String) result.getProperty(6).toString();
- // int count = result.getPropertyCount();
- // for (int index = 0; index < count; index++) {
- // provinces.add(result.getProperty(index).toString());
- // System.out.println(result.getProperty(index).toString());
- // }
- str=result.toString();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (XmlPullParserException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return str;
- }
- public String getFlagFromDBCust(String username,String password) {
- String str = "";
- SoapObject soapObject = newSoapObject(targetNameSpace,getLogin);
- //给账号和密码加密码
- String encodeUsername=Base64.encode(username.getBytes());
- String encodePassword=Base64.encode(password.getBytes());
- soapObject.addProperty("username", encodeUsername);
- soapObject.addProperty("password",encodePassword);
- //调用的方法参数与参数值(根据具体须要可选可不选)
- SoapSerializationEnvelope envelope = newSoapSerializationEnvelope(SoapEnvelope.VER11);
- envelope.dotNet = false;
- envelope.setOutputSoapObject(soapObject);
- HttpTransportSE httpTranstation=newHttpTransportSE(WSDL);
- //或者AndroidHttpTransport httpTranstation = new AndroidHttpTransport(WSDL);
- try {
- httpTranstation.call(targetNameSpace + getLogin, envelope);
- SoapObject result = (SoapObject ) envelope.bodyIn;//getResponse();
- //
- str=(String) result.getProperty(0).toString();
- // 也能够经过下面方式得到str
- // SoapPrimitive result = (SoapPrimitive ) envelope.getResponse();
- // str=result.toString();
- // 直指value字符串值
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (XmlPullParserException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return str;
- }
- }
能够看到Base64又在这里出现了,主要是为了加密码,而后传送给服务器端linux
注意:private static final String WSDL = "http://10.10.178.70:8888/WSDLApp/services/MyService";android
而不要在后面加上?wsdl,若是加上了就错误了。程序员
里面的代码。你能够下载源码进行解读。
我来提一点两种方式得到:resultweb
HttpTransportSE httpTranstation=new HttpTransportSE(WSDL);
//或者AndroidHttpTransport httpTranstation = new AndroidHttpTransport(WSDL);算法
这两种均可以sql
而后还有数据库
httpTranstation.call(targetNameSpace + getLogin, envelope);
SoapObject result = (SoapObject ) envelope.bodyIn;//getResponse();
//
str=(String) result.getProperty(0).toString();
// 也能够经过下面方式得到str
// SoapPrimitive result = (SoapPrimitive ) envelope.getResponse();
// str=result.toString();
// 直指value字符串值
这两种方式,我在测试的过程当中都经过。提拱多种方式,让程序员灵活使用。
下面我贴上Activity子类MainActivity
- package com.net.connect.app;
- import Android.app.Activity;
- import Android.content.Intent;
- import Android.os.Bundle;
- import Android.view.View;
- import Android.view.View.OnClickListener;
- import Android.view.ViewGroup.LayoutParams;
- import Android.widget.Button;
- import Android.widget.EditText;
- import Android.widget.LinearLayout;
- import Android.widget.TextView;
- import Android.widget.Toast;
- import com.cn.blogs.ksoap.app.MyWebServiceHelper;
- /****
- * http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html
- *
- * @author mingg
- *
- */
- public class LoginActivity extends Activity {
- /** Called when the activity is first created. */
- TextView txtUsername,txtPassword;
- EditText etUsername,etPassword;
- Button loginButton,exitButton;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //setContentView(R.layout.main);
- constructLayout();
- }
- private void constructLayout() {
- LinearLayout.LayoutParams lp = newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- LinearLayout.LayoutParams controlpl = newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
- LinearLayout ll = new LinearLayout(this);
- ll.setOrientation(LinearLayout.VERTICAL);
- txtUsername = new TextView(this);
- txtUsername.setText("账号:\t");
- etUsername = new EditText(this);
- txtPassword = new TextView(this);
- txtPassword.setText("密码:\t");
- etPassword = new EditText(this);
- loginButton=new Button(this);
- loginButton.setText("登录");
- loginButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- String userValue=etUsername.getText().toString();
- String passValue=etPassword.getText().toString();
- if(userValue.length()==0 || passValue.length()==0){
- Toast.makeText(LoginActivity.this, "账号和密码不能为空,请输入", Toast.LENGTH_LONG).show();
- return;
- }
- //调用自已写的webService
- MyWebServiceHelper webServiceHelper=newMyWebServiceHelper();
- intflag=Integer.parseInt(webServiceHelper.getFlagFromDBCust(userValue,passValue));
- String content="";
- switch (flag) {
- case 1 :
- content="该用户不存在,请输入你的用户名";
- Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
- break;
- case 2 :
- content="密码输入错误,请核对";
- Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
- break;
- case 3 :
- content="数据库出现异常,请重试";
- Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
- break;
- case 4 :
- content="验证经过";
- Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
- try {
- Thread.currentThread().sleep(1000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //转到MainActivity
- Intent intent=new Intent();
- intent.setClass(LoginActivity.this, MainActivity.class);
- startActivity(intent);
- break;
- default:
- break;
- }
- }
- });
- exitButton=new Button(this);
- exitButton.setText("退出");
- exitButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- LoginActivity.this.finish();
- //退出
- }
- });
- ll.addView(txtUsername, controlpl);
- ll.addView(etUsername, controlpl);
- ll.addView(txtPassword, controlpl);
- ll.addView(etPassword, controlpl);
- ll.addView(loginButton, controlpl);
- ll.addView(exitButton, controlpl);
- addContentView(ll, lp);
- }
- }
最终运行效果以下所示:
有点小问题,能够在开发中更正。
最终不要忘了加 internet permmition
AndroidManifest.xml中加入<uses-permission android:name="android.permission.INTERNET" />