在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" />