栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android中使用socket通信实现消息推送的方法详解

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android中使用socket通信实现消息推送的方法详解

原理
最近用socket写了一个消息推送的demo,在这里和大家分享一下。

主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ。

效果图:

原理:手机通过socket发送消息到服务器,服务器每接收到一条消息之后,都会把这条消息放进一个messageList里面,服务器会不停地检测messageList是否含有消息,如果有的话就会根据messageList里面item的数据,推送到相应的另一端手机上面。

下面简单画了一个图来说明这个原理:

演示:手机客户端client1发送消息msg1到手机客户端client2,client2收到消息后回复msg2给client1

1.手机客户端client1发送一条“msg1”的文本消息到服务器;

2.服务器收到来自client1的“msg1”消息后,把它add进messageList里面;

3.服务器检测到messageList里面含有消息(开启服务器时就新建里一个检测messageList的线程,线程里面有一个死循环,用于不停检测messageList是否含有消息);

4.服务器读取消息数据,如读取到来自client1发给client2的消息“msg1”,那么服务器就把“msg1”推送到client2上;

5.client2检测到服务器推送的消息,做出相应的操作(如:震动、铃声、显示消息等);

6.client2接收到来自服务器推送的“msg1”消息后,client2也回复一条文本消息“msg2”给client1,此过程和client1发送消息给client2一样。

7.最后,client2就可以显示来自client1发送的消息“msg1”,而client1则可以显示来自client2的回复消息“msg2”。

实现过程
根据消息推送的原理图,我们的实现过程主要分为Server端和Client端,Server端采用Java的编程,而Client端则用Android编程。

所以在这里也分别创建了两个工程SocketServer和SocketClient

我们先来看一下SocketMessage.java类:

public class SocketMessage { 
 
  public int to;//socketID,指发送给谁 
  public int from;//socketID,指谁发送过来的 
  public String msg;//消息内容 
  public String time;//接收时间 
  public SocketThread thread;//socketThread下面有介绍 
} 

该类是一个消息类,用于表示消息是由谁发给谁的、消息内容是什么、接收时间是多少,只有几个属性,比较简单。

而MyServer.java类就相对比较多一些代码:

package com.jimstin.server; 
 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Date; 
 
import org.json.JSONObject; 
 
 
import com.jimstin.msg.SocketMessage; 
 
public class MyServer { 
 
  private boolean isStartServer; 
  private ServerSocket mServer; 
   
  private ArrayList mMsgList = new ArrayList(); 
   
  private ArrayList mThreadList = new ArrayList(); 
   
   
  private void startSocket() { 
    try { 
      isStartServer = true; 
      int prot = 2000;//端口可以自己设置,但要和Client端的端口保持一致 
      mServer = new ServerSocket(prot);//创建一个ServerSocket 
      System.out.println("启动server,端口:"+prot); 
      Socket socket = null; 
      int socketID = 0;//Android(SocketClient)客户机的唯一标志,每个socketID表示一个Android客户机 
      //开启发送消息线程 
      startSendMessageThread(); 
      //用一个循环来检测是否有新的客户机加入 
      while(isStartServer) { 
 //accept()方法是一个阻塞的方法,调用该方法后, 
 //该线程会一直阻塞,直到有新的客户机加入,代码才会继续往下走 
 socket = mServer.accept(); 
 //有新的客户机加入后,则创建一个新的SocketThread线程对象 
 SocketThread thread = new SocketThread(socket, socketID++); 
 thread.start(); 
 //将该线程添加到线程队列 
 mThreadList.add(thread); 
      } 

    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
   
   
  public void startSendMessageThread() { 
    new Thread(){ 
      @Override 
      public void run() { 
 super.run(); 
 try { 
    
   while(isStartServer) { 
     //判断消息队列中的长度是否大于0,大于0则说明消息队列不为空 
     if(mMsgList.size() > 0) { 
//读取消息队列中的第一个消息 
SocketMessage from = mMsgList.get(0); 
for(SocketThread to : mThreadList) { 
  if(to.socketID == from.to) { 
    BufferedWriter writer = to.writer; 
    JSonObject json = new JSonObject(); 
    json.put("from", from.from); 
    json.put("msg", from.msg); 
    json.put("time", from.time); 
    //writer写进json中的字符串数据,末尾记得加换行符:"n",否则在客户机端无法识别 
    //因为BufferedReader.readLine()方法是根据换行符来读取一行的 
    writer.write(json.toString()+"n"); 
    //调用flush()方法,刷新流缓冲,把消息推送到手机端 
    writer.flush(); 
    System.out.println("推送消息成功:"+from.msg+">> to socketID:"+from.to); 
    break; 
  } 
} 
//每推送一条消息之后,就要在消息队列中移除该消息 
mMsgList.remove(0); 
     } 
     Thread.sleep(200); 
   } 
 } catch (Exception e) { 
   e.printStackTrace(); 
 } 
      } 
    }.start(); 
  } 
   
   
  public class SocketThread extends Thread { 
     
    public int socketID; 
    public Socket socket;//Socket用于获取输入流、输出流 
    public BufferedWriter writer;//BufferedWriter 用于推送消息 
    public BufferedReader reader;//BufferedReader 用于接收消息 
     
    public SocketThread(Socket socket, int count) { 
      socketID = count; 
      this.socket = socket; 
      System.out.println("新增一台客户机,socketID:"+socketID); 
    } 
     
    @Override 
    public void run() { 
      super.run(); 
 
      try { 
 //初始化BufferedReader 
 reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); 
 //初始化BufferedWriter 
 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8")); 
 //如果isStartServer=true,则说明SocketServer已经启动, 
 //现在需要用一个循环来不断接收来自客户机的消息,并作其他处理 
 while(isStartServer) { 
   //先判断reader是否已经准备好 
   if(reader.ready()) { 
      
     String data = reader.readLine(); 
     //讲data作为json对象的内容,创建一个json对象 
     JSonObject json = new JSonObject(data); 
     //创建一个SocketMessage对象,用于接收json中的数据 
     SocketMessage msg = new SocketMessage(); 
     msg.to = json.getInt("to"); 
     msg.msg = json.getString("msg"); 
     msg.from = socketID; 
     msg.time = getTime(System.currentTimeMillis()); 
     //接收到一条消息后,将该消息添加到消息队列mMsgList 
     mMsgList.add(msg); 
     System.out.println("收到一条消息:"+json.getString("msg")+" >>>> to socketID:"+json.getInt("to")); 
   } 
   //睡眠100ms,每100ms检测一次是否有接收到消息 
   Thread.sleep(100); 
 } 
  
      } catch (Exception e) { 
 e.printStackTrace(); 
      }  

    } 
  } 
   
  private String getTime(long millTime) { 
    Date d = new Date(millTime); 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    return sdf.format(d); 
  } 
  public static void main(String[] args) { 
    MyServer server = new MyServer(); 
    server.startSocket(); 
  } 
 
} 

2.SocketClient工程

该工程是一个Android的工程,只有一个MainActivity.java和activity_main.xml文件,

先看一下activity_main.xml布局文件:

 
   
   
     
     
   
  

效果图:

MainActivity.java类:

package com.jimstin.socketclient; 
 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
import org.json.JSONObject; 
 
import com.tencent.stat.MtaSDkException; 
import com.tencent.stat.StatConfig; 
import com.tencent.stat.StatService; 
 
import android.R.integer; 
import android.os.AsyncTask; 
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.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.app.Activity; 
 
public class MainActivity extends Activity implements onClickListener { 
 
  private EditText mIPEdt, mPortEdt, mSocketIDEdt, mMessageEdt; 
  private static TextView mConsoleTxt; 
   
  private static StringBuffer mConsoleStr = new StringBuffer(); 
  private Socket mSocket; 
  private boolean isStartRecieveMsg; 
   
  private SocketHandler mHandler; 
  protected BufferedReader mReader;//BufferedWriter 用于推送消息 
  protected BufferedWriter mWriter;//BufferedReader 用于接收消息 
   
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    initView(); 
  } 
 
  private void initView() { 
    mIPEdt = (EditText) findViewById(R.id.ip_edt); 
    mPortEdt = (EditText) findViewById(R.id.port_edt); 
    mSocketIDEdt = (EditText) findViewById(R.id.socket_id_edt); 
    mMessageEdt = (EditText) findViewById(R.id.msg_edt); 
    mConsoleTxt = (TextView) findViewById(R.id.console_txt); 
    findViewById(R.id.start_btn).setonClickListener(this); 
    findViewById(R.id.send_btn).setonClickListener(this); 
    findViewById(R.id.clear_btn).setonClickListener(this); 
    mHandler = new SocketHandler(); 
  } 
 
   
  private void initSocket() { 
    //新建一个线程,用于初始化socket和检测是否有接收到新的消息 
    Thread thread = new Thread(new Runnable() { 

      @Override 
      public void run() { 
 String ip = mIPEdt.getText().toString();//IP 
 int port = Integer.parseInt(mPortEdt.getText().toString());//Socket 
  
 try { 
   isStartRecieveMsg = true; 
   mSocket = new Socket(ip, port); 
   mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "utf-8")); 
   mWriter = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "utf-8")); 
   while(isStartRecieveMsg) { 
     if(mReader.ready()) { 
 
String data = mReader.readLine(); 
//handler发送消息,在handleMessage()方法中接收 
mHandler.obtainMessage(0, data).sendToTarget(); 
     } 
     Thread.sleep(200); 
   } 
   mWriter.close(); 
   mReader.close(); 
   mSocket.close(); 
 } catch (Exception e) { 
   e.printStackTrace(); 
 }  
      } 
    }); 
    thread.start(); 
  } 
   
  @Override 
  public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.send_btn: 
      send(); 
      break; 
    case R.id.clear_btn: 
      mConsoleStr.delete(0, mConsoleStr.length()); 
      mConsoleTxt.setText(mConsoleStr.toString()); 
      break; 
    case R.id.start_btn: 
      if(!isStartRecieveMsg) { 
 initSocket(); 
      } 
      break; 
    default: 
      break; 
    } 
  } 
 
   
  private void send() { 
    new AsyncTask() { 
 
      @Override 
      protected String doInBackground(String... params) { 
 sendMsg(); 
 return null; 
      } 
    }.execute(); 
  } 
   
  protected void sendMsg() { 
    try { 
      String socketID = mSocketIDEdt.getText().toString().trim(); 
      String msg = mMessageEdt.getText().toString().trim(); 
      JSonObject json = new JSonObject(); 
      json.put("to", socketID); 
      json.put("msg", msg); 
      mWriter.write(json.toString()+"n"); 
      mWriter.flush(); 
      mConsoleStr.append("我:" +msg+"  "+getTime(System.currentTimeMillis())+"n"); 
      mConsoleTxt.setText(mConsoleStr); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 
  static class SocketHandler extends Handler { 
     
    @Override 
    public void handleMessage(Message msg) { 
      // TODO Auto-generated method stub 
      super.handleMessage(msg); 
      switch (msg.what) { 
      case 0: 
 try { 
   //将handler中发送过来的消息创建json对象 
   JSonObject json = new JSonObject((String)msg.obj); 
   mConsoleStr.append(json.getString("from")+":" +json.getString("msg")+"  "+getTime(System.currentTimeMillis())+"n"); 
   //将json数据显示在TextView中 
   mConsoleTxt.setText(mConsoleStr); 
 } catch (Exception e) { 
   e.printStackTrace(); 
 } 
  
 break; 
 
      default: 
 break; 
      } 
    } 
  } 
   
  @Override 
  public void onBackPressed() { 
    super.onBackPressed(); 
    isStartRecieveMsg = false; 
  } 
   
  private static String getTime(long millTime) { 
    Date d = new Date(millTime); 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    return sdf.format(d); 
  } 
   
} 

以上代码的注释都比较详细,就不再多说了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/162727.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号