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(); } }
其实现在看看这个功能的实现,是非常简单的但是在我编写他们的时候由于马虎大意反了很多的错误,这里也感谢强哥和胡哥对我指导和鼓励。