Android使用Java Web服務器作爲中轉實現即時通信
白白浪費掉的今天,是我們嚮往的明天,是我們悔恨的昨天。~~~~~~~~~~與汝共勉
我相信一個人的時間按天計算和按秒計算其效果的差別是巨大的,我們應該相信上帝賦予我們足夠的時間來讓我們變得睿智,成熟。但是我們的時間又是不夠的,因爲我們要做的事好多好多。但是有時候又不知道自己該幹什麼,我能爲別人帶來什麼,或者我又可以收穫什麼。自己或許還並不是一個程序員,但是我並不想把編程只看做Code,我在做的是Program。我希望我可以去做很偉大的事情,但是有時候又很害怕。其實那又有什麼呢,嘗試是一件多麼令人心動的事啊。
我感覺我不能說的太多了,要不然會滔滔不絕偏離主題的。最近一個人沒事在搞一個聊天的模塊,因爲想要這個模塊真正的變得有價值,加上我們這些學習愛好者並沒有服務器的原因,雲服務器並不提供我們編寫Socket程序所需要的端口,於是我的這個模塊就顯得很長有意義了。這個模塊其實很簡單,只不過由於本人能力有限,還是中間出了點差錯,錯誤調試了好久才得以實現,不過還好我這人挺豁達的。不跟程序較勁,所以後來還是慢慢的完成了這個模塊成功交差。
這個實現的思想就是:
發送消息時:客戶端發一個http請求,將用戶名加上接收方的名字和發送的消息放在座位請求參數發送給服務器。這個功能實現起來較爲簡單。
接受消息:這個過程實現起來相對會比較麻煩一點點,但是也沒幾行代碼就可以解決了。
思想就是客戶端每隔一段時間就去訪問一下服務器,想服務器問問有沒有我的消息,有的話就把消息帶回去。
首先貼下java web服務器端的代碼:
public class CoreServlet extends HttpServlet {
Map<String, String> mapMessage = new HashMap<String, String>();
private PrintWriter out;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
request.setCharacterEncoding("UTF-8");
// 取得請求者名稱
String strReqName = request.getParameter("name");
// 取得請求者狀態
String strState = request.getParameter("state");
// 如果狀態是登錄
if (strState.equals("load")) {
String strRep = "load success";
System.out.println(strReqName + "登錄");
// 向客戶端迴應登錄成功
out = response.getWriter();
out.write(strRep);
}
// 如果狀態是發送
else if (strState.equals("sendMsg")) {
// 取得發送至的名字
String strSendToName = request.getParameter("toName");
// 得到信息
String strMsg = request.getParameter("Msg");
// 迴應請求客戶端信息
String strSendMsg = strReqName + " send to "
+ strSendToName + " message: \n" + strMsg;
System.out.println(strSendMsg);
// 將信息和發送至的名字和相對應的信息放在Map表中
mapMessage.put(strSendToName, strSendMsg);
}
// 如果狀態是獲得信息
else if (strState.equals("getMsg")) {
out = response.getWriter();
// 送map中取得信息
String strMessage = mapMessage.get(strReqName);
System.out.println(strReqName + "------>" + strMessage);
// 判斷信息是否存在
if (strMessage != null && !strMessage.equals("")) {
// 存在則將信息發給請求客戶端
out.write(strMessage);
out.flush();
System.out.println("移除消息");
// 將消息從消息隊列中移除,防止消息返回發送
mapMessage.put(strReqName, "");
}
}
}
}
再看我們的客戶端,也就是Android端的程序的代碼:
這是一個登陸界面,用來實現用戶登錄過程。
package com.example.tttt;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText editNameText;
private EditText pwdEditText;
private EditText sendToEditText;
private Button loginButton;
//服務器的ip和端口號
protected String serverIP = "192.168.0.115:8080";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editNameText = (EditText) findViewById(R.id.edit_name);
pwdEditText = (EditText) findViewById(R.id.edit_password);
sendToEditText = (EditText) findViewById(R.id.edit_toname);
loginButton = (Button) findViewById(R.id.button_login);
loginButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
/*
* requestUrl---->請求地址
*
* @name用戶名爲tlh
*
* @ state狀態爲load
*/
String requestUrl = "http://" + serverIP
+ "/AppWebConnect/CoreServlet?name=userName&state=load";
// 得到輸入框中的內容
// 用戶名
String strName = editNameText.getText().toString();
// 密碼
String strPassWord = pwdEditText.getText().toString();
// 信息接收方的名稱
String strSendTo = sendToEditText.getText().toString();
// 檢查內容是否爲空
if (check(strName) && check(strPassWord) && check(strSendTo)) {
// 將用戶名替換成自己的名稱---->strName
requestUrl = requestUrl.replace("userName", strName);
// 向服務器發送請求並得到服務器端的迴應信息
String strMessage = ConnectToServer(requestUrl);
Toast.makeText(MainActivity.this, "--->" + strMessage,
Toast.LENGTH_SHORT).show();
if (check(strMessage)) {
// 跳轉聊天界面
Intent intent = new Intent(MainActivity.this,
ChatActivity.class);
intent.putExtra("name", strName);
intent.putExtra("sendTo", strSendTo);
startActivity(intent);
}
} else {
Toast.makeText(MainActivity.this, "用戶名或密碼不能爲空", 2000)
.show();
}
}
});
}
public String ConnectToServer(String requestUrl) {
String strMessage = "";
try {
HttpClient httpclient = new DefaultHttpClient();
// 創建Get方法實例
HttpGet httpgets = new HttpGet(requestUrl);
HttpResponse response = httpclient.execute(httpgets);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instreams = entity.getContent();
String str = convertStreamToString(instreams);
if (str == null || str.equals("")) {
Log.i("tag", "無應答");
}
System.out.println(str);
strMessage = str;
// Do not need the rest
httpgets.abort();
}
} catch (Exception e) {
Log.i("tag", "" + e);
}
return strMessage;
}
public String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public boolean check(String strCheck) {
if (strCheck == null || strCheck.equals("")) {
return false;
}
return true;
}
}
下面是一個類用來實現聊天功能:
下面的這個類是實現消息的發送和接受的功能的
package com.example.tttt;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class ChatActivity extends Activity {
private TextView textView;
private EditText editText;
private Button button;
// 要發送的信息
String strMessage;
// 用戶名
String strUserName;
// 接受者姓名
String strToName;
// 出於Android線程界面安全,用來處理接受到信息後使textView將消息呈現出來
private Handler handler;
// 接受到的信息
private String strResult;
// 服務器的地址
protected String serverIp = "192.168.0.115:8080";
@SuppressWarnings("static-access")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.talk);
// 對界面進行初始化
initUI();
// 對數據進行初始化
initData();
// 開始監聽其他用戶發來的消息
startMessageReciver();
// 設置按鈕的監聽器
button.setOnClickListener(new OnClickListener() {
String requestUrl;
@SuppressLint("ShowToast")
@Override
public void onClick(View v) {
// 獲得信息
strMessage = editText.getText().toString();
editText.setText("");
// 設置請求地址和參數
requestUrl = "http://" + serverIp
+ "/AppWebConnect/CoreServlet?name=" + strUserName
+ "&state=sendMsg&Msg=" + strMessage + "&toName="
+ strToName + "";
Log.i("tag", "strMessage--->" + requestUrl);
Log.i("tag", "URL--->" + strMessage);
if (strMessage.equals("") || strMessage == null) {
Toast.makeText(getApplicationContext(), "發送內容不能爲空!!", 2000)
.show();
} else {
textView.append("向" + strToName + "發送消息----->" + strMessage
+ "\n");
// 請求服務器
String strResult = ConnectToServer(requestUrl);
Toast.makeText(ChatActivity.this, "------->" + strResult,
2000).show();
}
}
});
}
/**
* 對數據進行初始化,並設置回調
*/
private void initData() {
Intent intent = getIntent();
strUserName = intent.getStringExtra("name");
strToName = intent.getStringExtra("sendTo");
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
Log.i("tag", "執行回調方法!!");
textView.append(strResult + "\n");
}
}
};
}
/**
* 對界面進行初始化
*/
private void initUI() {
textView = (TextView) findViewById(R.id.tv_display);
editText = (EditText) findViewById(R.id.edit_message);
button = (Button) findViewById(R.id.btn_send);
}
/**
* 開始監聽服務器發來的消息
*/
private void startMessageReciver() {
new Thread() {
String requestUrl = "http://" + serverIp
+ "/AppWebConnect/CoreServlet?name=" + strUserName
+ "&state=getMsg";
HttpClient httpclient = new DefaultHttpClient();
public void run() {
// 創建Get方法實例
HttpGet httpgets = new HttpGet(requestUrl);
HttpResponse response = null;
// 設置循環,使程序不停的訪問服務器
for (;;) {
try {
response = httpclient.execute(httpgets);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instreams = entity.getContent();
String str = convertStreamToString(instreams);
// 如果接收到服務器發來的消息(即有好友發來消息)
if (str != null && !str.equals("")) {
System.out.println(str);
strResult = str;
Log.i("tag", "" + strResult);
//回調,將好友發來的消息呈現在TextView上
handler.sendEmptyMessage(1);
} else {
Log.i("tag", "無 應 答");
}
}
//設置每兩秒訪問一次
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
};
}.start();
}
/**
* 連接服務器
* @param requestUrl 請求參數
* @return 返回服務器發來的消息
*/
public String ConnectToServer(String requestUrl) {
String strMessage = "";
HttpClient httpClient = new DefaultHttpClient();
try {
// 創建Get方法實例
HttpGet httpgets = new HttpGet(requestUrl);
HttpResponse response = httpClient.execute(httpgets);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instreams = entity.getContent();
String str = convertStreamToString(instreams);
if (str == null || str.equals("")) {
Log.i("tag", "無應答");
} else {
System.out.println(str);
strMessage = str;
Log.i("tag", "*******" + strMessage);
}
httpgets.abort();
}
} catch (Exception e) {
Log.i("tag", "" + e);
}
return strMessage;
}
/**
* 將字節流轉換爲字符串
* @param is 輸入流
* @return 轉換後的字符竄
*/
public String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
其實現在看看這個功能的實現,是非常簡單的但是在我編寫他們的時候由於馬虎大意反了很多的錯誤,這裏也感謝強哥和胡哥對我指導和鼓勵。