iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android Socket接口实现即时通讯实例代码
  • 322
分享到

Android Socket接口实现即时通讯实例代码

即时通讯socketAndroid 2022-06-06 05:06:14 322人浏览 薄情痞子
摘要

Android Socket接口实现即时通讯            

Android Socket接口实现即时通讯

             最近学习Android 通信的知识,做一个小实例,巩固下学习内容,以下内容是网上找的资料,觉得很不错,知识比较全面,大家看下。

 首先了解一下即时通信的概念。通过消息通道 传输消息对象,一个账号发往另外一账号,只要账号在线,可以即时获取到消息,这就是最简单的即使通讯。消息通道可由tcp/IP UDP实现。通俗讲就是把一个人要发送给另外一个人的消息对象(文字,音视频,文件)通过消息通道(C/S实时通信)进行传输的服务。即时通讯应该包括四种形式,在线直传、在线代理、离线代理、离线扩展。在线直传指不经过服务器,直接实现点对点传输。在线代理指消息经过服务器,在服务器实现中转,最后到达目标账号。离线代理指消息经过服务器中转到达目标账号,对方不在线时消息暂存服务器的数据库,在其上线再传发。离线扩展指将暂存消息以其它形式,例如邮件、短信等转发给目标账号。

       此外,我们还需要认识一下计算机网络相关的概念。经典的计算机网络四层模型中,TCP和UDP是传输层协议,包含着消息通信内容。ip为网络层协议,是一种网络地址。TCP/IP,即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何在它们之间传输的标准。Socket,又称“套接字”, 在应用层和传输层之间的一个抽象层,用于描述 IP 地址和端口,是一个通信连的句柄,应用程序通常通过“套接字”向网络发送请求或者应答网络请求,它就是网络通信过程中端点的抽象表示。它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,应用于即时通讯场景的应用层协议,底层通过Socket实现。它用于即时消息(IM)以及在线现场探测。它在促进服务器之间的准即时操作。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息, 即使其操作系统和浏览器不同。这样实现即时通讯就有两种方案,一是从套接字入手,直接利用socket提供的接口进行数据的传送。二是借助开源工具(服务器openfire),用XMPPConnection创建连接。

     XMPP是实现即时通讯使用较为普遍的做法。XMPP中,各项工作都是通过在一个 XMPP 流上发送和接收 XMPP 节来完成的。核心 XMPP 工具集由三种基本节组成,这三种节分别为<presence>、出席<message>、<iq>。XMPP 流由两份 XML 文档组成,通信的每个方向均有一份文档。这份文档有一个根元素<stream:stream>,这个根元素的子元素由可路由的节以及与流相关的顶级子元素构成。xmpp协议同样包括客户端和服务器。客户端基于 Android 平台进行开发。负责初始化通信过程,进行即时通信时,由客户端负责向服务器发起创建连接请求。系统通过 GPRS 无线网络与Internet 网络建立连接,通过服务器实现与 Android 客户端的即时通信脚。服务器端则采用 Openfire 作为服务器。 允许多个客户端同时登录并且并发的连接到一个服务器上。服务器对每个客户端的连接进行认证,对认证通过的客户端创建会话,客户端与服务器端之间的通信就在该会话的上下文中进行。使用了 asmark 开源框架实现的即时通讯功能.该框架基于开源的 XMPP 即时通信协议,采用 C/S 体系结构,通过 GPRS 无线网络用TCP 协议连接到服务器,以架设开源的 Openfn'e 服务器作为即时通讯平台。xmpp消息通道的创建:

          先配置通道信息进行连接


  ConnectionConfiguration configuration = new ConnectionConfiguration(HOST, PORT),

          设置Debug信息和安全模式


      configuration.setDebuggerEnabled(true);
      configuration.setSecurityMode(SecurityMode.disabled),

          最后才是建立连接


      conn.connect();

         在ContentObserver的实现类中观察消息变化。XMPPConnection.getRoster()获取联系人列表对象。用xmpp协议编写通讯协议的大致思路可以如下。进入登陆界面,通过xmppconnection的login方法实现登陆,登陆成功进入主界面。主界面包含两个Fragment,分别用来显示联系人和聊天记录。创建联系人和短信的数据观察者,在联系人、短信服务中分别设定监听RosterListener()、ChatManagerListener(),接受联系人和短信信息,同时将相关信息添加到内容提供者中。在内容提供者中设定一个内容观察者,当数据发生变化时通知界面更新。

        本文的重点是利用Socket的接口实现即时通讯,因为绝大多数即时通讯的底层都是通过Socket实现的。其基本的业务逻辑可描述如下。用户进入登陆界面后,提交账号密码 经服务端确定,返回相关参数用于确定连接成功。进入聊天界面或好友界面。点击联系人或聊天记录的条目,进入聊天界面。当移动端再次向服务器发送消息时,由服务器转发消息内容给目标账号。同时更新界面显示。这样就完成即时通讯的基本功能。当然,也可以添加一个后台服务,当用户推出程序时,在后台接受消息。不难看出,对于即时通讯来讲,有三个关注点:消息通道、消息内容、消息对象。因此,主要逻辑也是围绕这三个点展开。消息通道实现传输消息对象的发送和接收。为Socket(String host, int port)传入服务其地址和端口号,即可创建连接。消息内容的格式应该与服务器保持一致。接受数据时,获取输入流并用DatainputStream包装,通过输入流读取server发来的数据。发送数据时,获取输出流并用DataOutputStream包装,通过输出流往server发送数据。消息内容中应该包括发送者、接受者信息、数据类型等。消息对象就是消息的发送者和消息的接受者。接下来在代码中进行详细的讲解。

         创建一个消息的基类,实现xml文件和字符串的转换,用到Xsream第三方jar包。这样当创建消息类时,继承该方法,就可以直接在类中实现数据的转换。



public class ProtacolObjc implements Serializable {
  public String toXml() {
    XStream stream = new XStream();
    //将根节点转换为类名
    stream.alias(this.getClass().getSimpleName(), this.getClass());
    return stream.toXML(this);
  }
  public Object fromXml(String xml) {
    XStream x = new XStream();
    x.alias(this.getClass().getSimpleName(), this.getClass());
    return x.fromXML(xml);
  }
  //创建Gson数据和字符串之间转换的方法,适应多种数据
  public String toGson() {
    Gson gson = new Gson();
    return toGson();
  }
  public Object fromGson(String result) {
    Gson gson = new Gson();
    return gson.fromJSON(result, this.getClass());
  }
}

         创建线程工具,指定方法运行在子线程和主线程中。由于网络操作需要在子线程中,界面更新需要在主线程中,创建线程工具可以方便选择线程。


import android.os.Handler;

public class ThreadUtils {
  private static Handler handler = new Handler();
  public static void runUIThread(Runnable r){
    handler.post(r);
  }
  public static void runINThread(Runnable r){
    new Thread(r).start();
  }
}

          创建消息的工具类,包括消息内容、消息类型、消息本省等。由于服务器返回的内容中包含消息的包名信息所以消息本身的包名应该于服务其保持一直。



public class QQMessage extends ProtacolObjc {
  public String type = QQmessageType.MSG_TYPE_CHAT_P2P;// 类型的数据 chat login
  public long from = 0;// 发送者 account
  public String fromNick = "";// 昵称
  public int fromAvatar = 1;// 头像
  public long to = 0; // 接收者 account
  public String content = ""; // 消息的内容 约不?
  public String sendTime = getTime(); // 发送时间
  public String getTime() {
    Date date = new Date(System.currentTimeMillis());
    java.text.SimpleDateFORMat format = new java.text.SimpleDateFormat("mm-DD HH:mm:ss");
    return format.format(date);
  }
  public String getTime(Long time) {
    Date date = new Date(time);
    java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("mm-DD HH:mm:ss");
    return format.format(date);
  }
}

public class QQmessageType {
  public static final String MSG_TYPE_REGISTER = "register";// 注册
  public static final String MSG_TYPE_LOGIN = "login";// 登录
  public static final String MSG_TYPE_LOGIN_OUT = "loginout";// 登出
  public static final String MSG_TYPE_CHAT_P2P = "chatp2p";// 聊天
  public static final String MSG_TYPE_CHAT_ROOM = "chatroom";// 群聊
  public static final String MSG_TYPE_OFFLINE = "offline";// 下线
  public static final String MSG_TYPE_SUCCESS = "success";//成功
  public static final String MSG_TYPE_BUDDY_LIST = "buddylist";// 好友
  public static final String MSG_TYPE_FAILURE = "failure";// 失败
}
import com.example.huang.imsocket.bean.ProtacolObjc;

public class QQBuddy extends ProtacolObjc {
  public long account;
  public String nick;
  public int avatar;
}

public class QQBuddyList extends ProtacolObjc {
  public ArrayList<QQBuddy> buddyList = new ArrayList<>();
}

           关于socket的创建连接和发送消息、接受消息。


import android.util.Log;
import com.example.huang.imsocket.bean.QQMessage;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class QQConnection extends Thread {
  private static final String TAG = "QQConnection";
  private Socket client;
  private DataOutputStream write;
  private DataInputStream read;
  public static final String HOST = "192.168.23.48";
  public static final int POST = 5225;
  private boolean flag = true;
  private List<OnQQmwssagereceiveLisener> mOnQQmwssagereceiveLisener = new ArrayList<>();
  public void addOnQQmwssagereceiveLisener(OnQQmwssagereceiveLisener lisener) {
    mOnQQmwssagereceiveLisener.add(lisener);
  }
  public void removeOnQQmwssagereceiveLisener(OnQQmwssagereceiveLisener lisener) {
    mOnQQmwssagereceiveLisener.remove(lisener);
  }
  public interface OnQQmwssagereceiveLisener {
    public void onReiceive(QQMessage qq);
  }
  @Override
  public void run() {
    super.run();
    while (flag) {
      try {
        String utf = read.readUTF();
        QQMessage message = new QQMessage();
        QQMessage msg = (QQMessage) message.fromXml(utf);
        if (msg != null) {
          for (OnQQmwssagereceiveLisener lisner : mOnQQmwssagereceiveLisener)
            lisner.onReiceive(msg);
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  public void connect() {
      try {
        if (client == null) {
          client = new Socket(HOST, POST);
          write = new DataOutputStream(client.getOutputStream());
          read = new DataInputStream(client.getInputStream());
          flag = true;
          this.start();
          Log.e(TAG, "connect: "+(write==null)+"---"+ (read == null));
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
  }
  public void disconnect() {
    if (client != null) {
      flag = false;
      this.stop();
      try {
        read.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
      try {
        write.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
      try {
        client.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  public void send(String xml) throws IOException {
    write.writeUTF(xml);
    write.flush();
  }
  public void send(QQMessage qq) throws IOException {
    write.writeUTF(qq.toXml());
    write.flush();
  }
}

         闪屏界面的布局


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="Http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/activity_splash"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@mipmap/splash_bg">
  <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:src="@mipmap/conversation_bg_loGo" />
</RelativeLayout>

                闪屏界面,保持4秒钟进入登陆界面。一般来见,闪屏界面可以加载数据、获取版本号、更新版本等操作。这里没有做的那么复杂。


import com.example.huang.imsocket.R;
public class SplashActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getSupportActionBar().hide();  //隐藏标栏
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //全屏显示
    setContentView(R.layout.activity_splash);
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        startActivity(new Intent(SplashActivity.this, LoginActivity.class));
        finish();
      }
    }, 4000);
  }
}

        登陆界面的布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#aabbdd"
  android:gravity="center"
  android:orientation="vertical">
  <TableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@mipmap/conversation_bg_logo" />
    <TableRow
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginLeft="20dp"
      android:layout_marginRight="20dp"
      android:layout_marginTop="8dp"
      android:gravity="center_horizontal">
      <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:text="账号:"
        android:textColor="#000" />
      <EditText
        android:id="@+id/et_accoun"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:gravity="center"
        android:hint="输入账号" />
    </TableRow>
    <TableRow
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginLeft="20dp"
      android:layout_marginRight="20dp"
      android:layout_marginTop="4dp"
      android:gravity="center_horizontal">
      <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:text="密码:"
        android:textColor="#000" />
      <EditText
        android:id="@+id/et_pwd"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:gravity="center"
        android:hint="输入密码" />
    </TableRow>
    <Button
      android:id="@+id/btn_login"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginLeft="80dp"
      android:layout_marginRight="80dp"
      android:layout_marginTop="8dp"
      android:onClick="sendmessage"
      android:text="登录" />
  </TableLayout>
</LinearLayout>

     登陆界面,创建和服务器的连接,向服务器发送登陆信息,接受服务器返回的信息。


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.example.huang.imsocket.R;
import com.example.huang.imsocket.bean.Myapp;
import com.example.huang.imsocket.bean.QQBuddyList;
import com.example.huang.imsocket.bean.QQMessage;
import com.example.huang.imsocket.bean.QQmessageType;
import com.example.huang.imsocket.core.QQConnection;
import com.example.huang.imsocket.service.IMService;
import com.example.huang.imsocket.util.ThreadUtils;
import java.io.IOException;

public class LoginActivity extends Activity {
  private static final String TAG = "LoginActivity";
  private EditText et_accoun;
  private EditText et_pwd;
  private String accoun;
  private QQConnection conn;
  private QQConnection.OnQQmwssagereceiveLisener lisener = new QQConnection.OnQQmwssagereceiveLisener() {
    @Override
    public void onReiceive(final QQMessage qq) {
      final QQBuddyList list = new QQBuddyList();
      final QQBuddyList list2 = (QQBuddyList) list.fromXml(qq.content);
      if (QQmessageType.MSG_TYPE_BUDDY_LIST.equals(qq.type)) {
        ThreadUtils.runUIThread(new Runnable() {
          @Override
          public void run() {
            Toast.makeText(getBaseContext(), "成功", Toast.LENGTH_SHORT).show();
            Myapp.me = conn;
            Myapp.username = accoun;
            Myapp.account = accoun + "@qq.com";
            Intent intent = new Intent(LoginActivity.this, contactActivity.class);
            intent.putExtra("list", list2);
            startActivity(intent);
            Intent data = new Intent(LoginActivity.this, IMService.class);
            startService(data);
            finish();
          }
        });
      } else {
        ThreadUtils.runUIThread(new Runnable() {
          @Override
          public void run() {
            Toast.makeText(getBaseContext(), "登陆失败", Toast.LENGTH_SHORT).show();
          }
        });
      }
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    et_accoun = (EditText) findViewById(R.id.et_accoun);
    et_pwd = (EditText) findViewById(R.id.et_pwd);
    ThreadUtils.runINThread(new Runnable() {
      @Override
      public void run() {
        try {
          conn = new QQConnection();
          conn.addOnQQmwssagereceiveLisener(lisener);
          conn.connect();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }
  public void sendmessage(View view) {
    accoun = et_accoun.getText().toString().trim();
    final String passWord = et_pwd.getText().toString().trim();
    Log.i(TAG, "sendmessage: " + accoun + "#" + password);
    ThreadUtils.runINThread(new Runnable() {
      @Override
      public void run() {
        QQMessage message = new QQMessage();
        message.type = QQmessageType.MSG_TYPE_LOGIN;
        message.content = accoun + "#" + password;
        String xml = message.toXml();
        if (conn != null) {
          try {
            conn.send(xml);
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    });
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    conn.removeOnQQmwssagereceiveLisener(lisener);
  }
}

         好友列表界面


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#aabbcc"
  android:orientation="vertical">
  <TextView
    android:id="@+id/tv_title"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center"
    android:text="联系人列表"
    android:textColor="#6d00"
    android:textSize="23Dp" />
  <ListView
    android:id="@+id/lv_contact"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></ListView>
</LinearLayout>

         好友列表及时收到从哪个服务其发挥的好友更新信息,点击条目跳到聊天界面。


import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.huang.imsocket.R;
import com.example.huang.imsocket.bean.Myapp;
import com.example.huang.imsocket.bean.QQBuddyList;
import com.example.huang.imsocket.bean.QQMessage;
import com.example.huang.imsocket.bean.QQmessageType;
import com.example.huang.imsocket.core.QQConnection;
import com.example.huang.imsocket.util.ThreadUtils;
import java.util.ArrayList;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.itcast.server.bean.QQBuddy;

public class contactActivity extends Activity {
  private static final String TAG = "contactActivity";
  @Bind(R.id.tv_title)
  TextView tv_title;
  @Bind(R.id.lv_contact)
  ListView lv_contact;
  private QQBuddyList list;
  private ArrayList<QQBuddy> BuddyList = new ArrayList<>();
  private ArrayAdapter adapter = null;
  private QQConnection.OnQQmwssagereceiveLisener listener = new QQConnection.OnQQmwssagereceiveLisener() {
    @Override
    public void onReiceive(QQMessage qq) {
      if (QQmessageType.MSG_TYPE_BUDDY_LIST.equals(qq.type)) {
        QQBuddyList qqlist = new QQBuddyList();
        QQBuddyList qqm = (QQBuddyList) qqlist.fromXml(qq.content);
        BuddyList.clear();
        BuddyList.addAll(qqm.buddyList);
        ThreadUtils.runUIThread(new Runnable() {
          @Override
          public void run() {
            saveAndNotify();
          }
        });
      }
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_contact);
    ButterKnife.bind(this);
    Myapp.me.addOnQQmwssagereceiveLisener(listener);
    Intent intent = getIntent();
    list = (QQBuddyList) intent.getSerializableExtra("list");
    BuddyList.clear();
    BuddyList.addAll(list.buddyList);
    saveAndNotify();
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    Myapp.me.removeOnQQmwssagereceiveLisener(listener);
  }
  private void saveAndNotify() {
    if (BuddyList.size() < 1) {
      return;
    }
    if (adapter == null) {
      adapter = new ArrayAdapter<QQBuddy>(getBaseContext(), 0, BuddyList) {
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
          viewHolder holder;
          if (convertView == null) {
            convertView = View.inflate(getContext(), R.layout.item_contacts, null);
            holder = new viewHolder(convertView);
            convertView.setTag(holder);
          } else {
            holder = (viewHolder) convertView.getTag();
          }
          QQBuddy qqBuddy = BuddyList.get(position);
          holder.tv_nick.setText(qqBuddy.nick);
          holder.tv_account.setText(qqBuddy.account + "@qq.com");
          if (Myapp.username.equals(qqBuddy.account + "")) {
            holder.tv_nick.setText("[自己]");
            holder.tv_nick.setTextColor(Color.GRAY);
          } else {
            holder.tv_nick.setTextColor(Color.RED);
          }
          return convertView;
        }
      };
      lv_contact.setAdapter(adapter);
      lv_contact.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          QQBuddy qqbuddy = BuddyList.get(position);
          if (Myapp.username.equals(qqbuddy.account + "")) {
            Toast.makeText(getBaseContext(), "不能和自己聊天", Toast.LENGTH_SHORT).show();
          } else {
            Intent intent = new Intent(contactActivity.this, ChatActivity.class);
            intent.putExtra("account", qqbuddy.account + "");
            intent.putExtra("nick", qqbuddy.nick + "");
            startActivity(intent);
          }
        }
      });
    } else {
      adapter.notifyDataSetChanged();
    }
  }
  static class viewHolder {
    @Bind(R.id.iv_contact)
    ImageView iv_contact;
    @Bind(R.id.tv_nick)
    TextView tv_nick;
    @Bind(R.id.tv_account)
    TextView tv_account;
    public viewHolder(View view) {
      ButterKnife.bind(this, view);
    }
  }
}

        聊天界面


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">
  <TextView
    android:id="@+id/tv_name"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:background="#aa119988"
    android:gravity="center"
    android:text="和谁谁聊天中........."
    android:textSize="19dp" />
  <ListView
    android:id="@+id/lv_chat"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <EditText
      android:id="@+id/et_sms"
      android:layout_width="0dp"
      android:layout_height="40dp"
      android:layout_weight="1"
      android:hint="输入聊天" />
    <Button
      android:id="@+id/btn_send"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="发送" />
  </LinearLayout>
</LinearLayout>

         聊天界面中消息接收和消息发送都需要及时更新列表。


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.huang.imsocket.R;
import com.example.huang.imsocket.bean.Myapp;
import com.example.huang.imsocket.bean.QQMessage;
import com.example.huang.imsocket.bean.QQmessageType;
import com.example.huang.imsocket.core.QQConnection;
import com.example.huang.imsocket.util.ThreadUtils;
import java.io.IOException;
import java.util.ArrayList;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class ChatActivity extends Activity {
  private static final String TAG = "ChatActivity";
  @Bind(R.id.tv_name)
  TextView tv_name;
  @Bind(R.id.lv_chat)
  ListView lv_chat;
  @Bind(R.id.et_sms)
  EditText et_sms;
  private ArrayAdapter<QQMessage> adapter = null;
  private ArrayList<QQMessage> list = new ArrayList<>();
  private String account;
  @OnClick(R.id.btn_send)
  public void send(View view) {
    String sendsms = et_sms.getText().toString().trim();
    if (TextUtils.isEmpty(sendsms)) {
      Toast.makeText(this, "消息不能为空", Toast.LENGTH_SHORT).show();
      return;
    }
    et_sms.setText("");
    final QQMessage qq = new QQMessage();
    qq.type = QQmessageType.MSG_TYPE_CHAT_P2P;
    qq.content = sendsms;
    qq.from = Long.parseLong(Myapp.username);
    qq.to = Long.parseLong(account);
    list.add(qq);
    setAdapteORNotify();
    ThreadUtils.runINThread(new Runnable() {
      @Override
      public void run() {
        try {
          Myapp.me.send(qq);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    });
  }
  private QQConnection.OnQQmwssagereceiveLisener listener = new QQConnection.OnQQmwssagereceiveLisener() {
    @Override
    public void onReiceive(final QQMessage qq) {
      if (QQmessageType.MSG_TYPE_CHAT_P2P.equals(qq.type)) {
        ThreadUtils.runUIThread(new Runnable() {
          @Override
          public void run() {
            list.add(qq);
            setAdapteORNotify();
          }
        });
      }
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chat);
    ButterKnife.bind(this);
    Myapp.me.addOnQQmwssagereceiveLisener(listener);
    Intent intent = getIntent();
    account = intent.getStringExtra("account");
    String nick = intent.getStringExtra("nick");
    tv_name.setText("和" + nick + "聊天中......");
    setAdapteORNotify();
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    Myapp.me.removeOnQQmwssagereceiveLisener(listener);
  }
  private void setAdapteORNotify() {
    if (list.size() < 1) {
      return;
    }
    if (adapter == null) {
      adapter = new ArrayAdapter<QQMessage>(this, 0, list) {
        @Override
        public int getViewTypeCount() {
          return 2;
        }
        @Override
        public int getItemViewType(int position) {
          QQMessage msg = list.get(position);
          long fromId = Long.parseLong(Myapp.username);
          if (fromId == msg.from) {
            return 0;
          }
          return 1;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
          int type = getItemViewType(position);
          if (type == 0) {
            viewHolder holder1 = null;
            if (convertView == null) {
              holder1 = new viewHolder();
              convertView = View.inflate(getBaseContext(), R.layout.item_sms_send, null);
              holder1.tv_send_time = (TextView) convertView.findViewById(R.id.tv_send_time);
              holder1.tv_send = (TextView) convertView.findViewById(R.id.tv_send);
              convertView.setTag(holder1);
            } else {
              holder1 = (viewHolder) convertView.getTag();
            }
            QQMessage qqMessage = list.get(position);
            holder1.tv_send_time.setText(qqMessage.sendTime);
            holder1.tv_send.setText(qqMessage.content);
            return convertView;
          } else if (type == 1) {
            viewHolder holder2 = null;
            if (convertView == null) {
              holder2 = new viewHolder();
              convertView = View.inflate(getBaseContext(), R.layout.item_sms_receive, null);
              holder2.tv_receive_time = (TextView) convertView.findViewById(R.id.tv_receive_time);
              holder2.tv_receive = (TextView) convertView.findViewById(R.id.tv_receive);
              convertView.setTag(holder2);
            } else {
              holder2 = (viewHolder) convertView.getTag();
            }
            QQMessage qqMessage = list.get(position);
            holder2.tv_receive_time.setText(qqMessage.sendTime);
            holder2.tv_receive.setText(qqMessage.content);
            return convertView;
          }
          return convertView;
        }
      };
      lv_chat.setAdapter(adapter);
    } else {
      adapter.notifyDataSetChanged();
    }
    if (lv_chat.getCount() > 0) {
      lv_chat.setSelection(lv_chat.getCount() - 1);
    }
  }
  class viewHolder {
    TextView tv_send_time;
    TextView tv_send;
    TextView tv_receive_time;
    TextView tv_receive;
  }
}

          最后可以添加一个服务当程序退出时,接受消息。


import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
import com.example.huang.imsocket.bean.Myapp;
import com.example.huang.imsocket.bean.QQMessage;
import com.example.huang.imsocket.core.QQConnection;
import com.example.huang.imsocket.util.ThreadUtils;

public class IMService extends Service {
  private QQConnection.OnQQmwssagereceiveLisener lisener = new QQConnection.OnQQmwssagereceiveLisener() {
    @Override
    public void onReiceive(final QQMessage qq) {
      ThreadUtils.runUIThread(new Runnable() {
        @Override
        public void run() {
          Toast.makeText(getBaseContext(), "收到好友消息: " + qq.content, Toast.LENGTH_SHORT).show();
        }
      });
    }
  };
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }
  @Override
  public void onCreate() {
    super.onCreate();
    Toast.makeText(getBaseContext(), "服务开启", Toast.LENGTH_SHORT).show();
    Myapp.me.addOnQQmwssagereceiveLisener(lisener);
  }
  @Override
  public void onDestroy() {
    Myapp.me.removeOnQQmwssagereceiveLisener(lisener);
    super.onDestroy();
  }
}

      Activity和Service节点配置,以及相应的权限。


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.huang.imsocket">
  <uses-permission android:name="android.permission.INTERNET" />
  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name="com.example.huang.imsocket.activity.SplashActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity
      android:name="com.example.huang.imsocket.activity.LoginActivity"
      android:theme="@android:style/Theme.NoTitleBar"></activity>
    <activity
      android:name="com.example.huang.imsocket.activity.ChatActivity"
      android:theme="@android:style/Theme.NoTitleBar"></activity>
    <activity
      android:name="com.example.huang.imsocket.activity.contactActivity"
      android:theme="@android:style/Theme.NoTitleBar"></activity>
    <service android:name=".service.IMService" />
  </application>
</manifest>

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

您可能感兴趣的文章:详解Android 基于TCP和UDP协议的Socket通信Android使用websocket实现多人游戏详解OkSocket与Android的简单使用Android开发之Socket通信传输简单示例android基于socket的局域网内服务器与客户端加密通信android socket聊天室功能实现SpringBoot WEBSocket实现发送广播、点对点消息和Android接收Android中Socket大文件断点上传示例android Socket实现简单聊天功能以及文件传输详解Android使用Socket对大文件进行加密传输详解Android 通过Socket 和服务器通讯(附demo)Android完整Socket解决方案


--结束END--

本文标题: Android Socket接口实现即时通讯实例代码

本文链接: https://www.lsjlt.com/news/22893.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android Socket接口实现即时通讯实例代码
    Android Socket接口实现即时通讯            ...
    99+
    2022-06-06
    即时通讯 socket Android
  • SpringBoot实现WebSocket即时通讯的示例代码
    目录1、引入依赖2、WebSocketConfig 开启WebSocket3、WebSocketServer4、测试连接发送和接收消息5、在线测试地址6、测试截图1、引入依赖 <...
    99+
    2022-11-13
  • php 怎么实现即时通讯实例
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。php 怎么实现即时通讯实例?仿百度商桥IM即时通讯(Laravel)基于workerman和websocket开发实时聊天系统仿百度商桥IM通讯实现原理及方法:1、...
    99+
    2022-10-27
  • php如何实现即时通讯实例
    本篇内容介绍了“php如何实现即时通讯实例”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!php实现即时通讯实例的方法:1、搭建websock...
    99+
    2023-07-04
  • C++实现即时通信的示例代码(直接运行)
    目录题目软件:VS服务器端客户端题目 由于本学期上了网络编程课程,老师要求写使用Socke实现网络编程。于是参考 C++多线程实现即时通信软件 写出了简单版本的没有界面的即时通信软件...
    99+
    2022-11-13
  • android语音即时通讯之录音、播放功能实现代码
    在android中,实现录音与语音播放的功能算是比较简单的,但是作为参考,还是很有必要将语音相关的知识做一个简要的记录。首先,在android中,支持录音支持两种方式。主要包括:字节流模式和文件流模式。用文件流模式进行录音操作比较简单,而且...
    99+
    2023-05-30
    android 语音 通讯
  • 300行代码实现go语言即时通讯聊天室
    学了2年Java,因为工作原因需要转Golang,3天时间学习了下go的基本语法,做这样一个聊天室小项目来巩固串联一下语法。 实现的功能:公聊,私聊,修改用户名 只用到了四个类: m...
    99+
    2022-11-13
  • Android如何实现socket通信统一接口
    小编给大家分享一下Android如何实现socket通信统一接口,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Android实现socket通信统一接口,统一接口之后可以在不需要大量修改应用层代码的情况下,使用与当前功能类...
    99+
    2023-06-25
  • Android实现socket通信统一接口的方法
    目录UDP通信与TCP通信的实现UDP通信TCP客户端通信使用统一接口定义接口实现接口实现应用层总结Android实现socket通信统一接口,统一接口之后可以在不需要大量修改应用层...
    99+
    2022-11-12
  • Nodejs+Socket.io实现通讯实例代码
    目录结构 D:. │ package.json │ server.js │ └─public index.html socket.io.js 需要的条件 socket.io.js ...
    99+
    2022-06-04
    实例 通讯 代码
  • Android Flutter基于WebSocket怎么实现即时通讯功能
    这篇文章主要介绍“Android Flutter基于WebSocket怎么实现即时通讯功能”,在日常操作中,相信很多人在Android Flutter基于WebSocket怎么实现即时通讯功能问题上存在疑惑,小编查阅了各...
    99+
    2023-06-29
  • Android连接服务器端的Socket的实例代码
    废话不多说了,直接给大家贴代码了,具体代码如下所述:package com.example.esp8266;import java.io.IOException;import java.io.InputStream;import java....
    99+
    2023-05-31
    android 服务器端 socket
  • PHP使用Socket和EPOLL实现在线即时通讯系统消息的发送和接收
    随着互联网的不断发展,即时通讯(IM)系统已成为人们生活、工作中不可或缺的工具。而其中,如何保证消息的快速传输和实时性就成为了系统设计中至关重要的一环。本文将介绍如何使用PHP的Socket和EPOLL实现在线即时通讯系统消息的发送和接收。...
    99+
    2023-05-24
    PHP socket EPOLL
  • python实现socket简单通信的示例代码
    首先先来简单介绍下socket: (具体更详细介绍的可以在网上找找,都讲得非常详细),这里主要是我自己的一些理解。 socket是在应用层与传输层之间的一个抽象层,它的本质是编程接...
    99+
    2022-11-12
  • Java多线程编程实现socket通信示例代码
    流传于网络上有关Java多线程通信的编程实例有很多,这一篇还算比较不错,代码可用。下面看看具体内容。TCP是Tranfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的...
    99+
    2023-05-30
    java socket通信 ava
  • PHP实现在线即时通讯系统消息的发送和接收
    随着人们生活方式的改变和网络技术的不断发展,即时通讯已经成为现代人必不可少的沟通方式之一。在这种趋势下,各种在线即时通讯系统应运而生。既然在不同地方的人可以在同一时间内交换消息,那么在线即时通讯系统是如何实现消息的传递的呢?本文将介绍通过 ...
    99+
    2023-05-24
    PHP 消息发送 在线通讯
  • C语言实现通讯录的示例代码
    目录一、Contact.h文件二、Contact.c文件三、test.c文件一、Contact.h文件 包含函数的声明 #pragma once #define _CRT_SECUR...
    99+
    2022-11-13
    C语言实现通讯录 C语言 通讯录
  • Android TimeLine 时间节点轴的实现实例代码
    整理文档,搜刮出一个Android TimeLine 时间节点轴的实现实例代码,稍微整理精简一下做下分享。效果图具体实现 (RecyclerView)Adapterpackage com.haoren.timeline;import and...
    99+
    2023-05-31
    timeline android tim
  • java利用socket通信实现Modbus-RTU通信协议的示例代码
    Modbus Modbus是一种串行通信协议。Modbus 一个工业上常用的通讯协议、一种通讯约定。Modbus协议包括RTU、ASCII、TCP。其中MODBUS-RTU最常用,...
    99+
    2022-11-12
  • Android中通过反射实现圆角ImageView代码实例
    private void init(){ paint = new Paint(Paint.ANTI_ALIAS_FLAG); roundRect = ...
    99+
    2022-06-06
    反射 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作