Android通信,大体上的逻辑是跟Java上的通信是差不多的,只是因为Android线程不能直接访问UI界面组件,所以在处理的时候有些麻烦,只要是通过Handle处理。

接下来是一个简单地手机聊天App,主要是手机终端与电脑之间的通信,比如发文字或者是发送图片。

因为涉及到发送不同类型的文件,所以需要制定以下协议:

1、消息类型,使用一个int表示,4个字节:

1、表示文字数据包;

2、表示鱼片数据包。

2、数据包的长度,使用一个int表示,4个字节

3、数据内容,使用字节数组进行传输。

关键性代码:

1、服务机与客户机之间的链接:

服务机:

ServerSocket ss = new ServerSocket(port);

Socket socket = ss.accept();

客户机:

//这个地方不能填电脑的本机地址,一定要是局域网或公网的//IP地址,wifi

socket = new Socket("10.96.23.74", 8888);

2、发送文字的代码:

//发送数据类型, 1-文本, 2-图片

dataOutputStream.writeInt(1);

//发送数据长度

dataOutputStream.writeInt(bytes. length);

//发送数据内容

dataOutputStream.write(bytes);

3、发送图片的代码:

//把一个图片文件读取到一个字节数组中

FileInputStream fis = new FileInputStream("images/jobs.png");

int len = fis.available();

byte[] bytes = new byte[len];

fis.read(bytes);

fis.close();

//发送数据类型, 1-文本, 2-图片

dataOutputStream.writeInt(2);

//数据长度

dataOutputStream.writeInt(bytes. length);

//数据内容

dataOutputStream.write(bytes);

//刷新缓存

dataOutputStream.flush();

4、Handle处理UI界面:

在客户机线程里面,handler.sendMessage(msg);

在MainActivity里面:

//创建Handler对象

Handler handler = new Handler(

//回调接口,当handler接收到消息时调用该接口的handleMessage方法

new Callback() {

//出理线程发送过来的数据

public boolean handleMessage(Message msg) {

if(msg. what == 1){

//把服务器发送过来的内容显示出来

textMsgLog.append(" 服务器: " + msg. obj .toString() +

"\n");

}

if(msg. what == 2){

//服务器发送过来的图片

Bitmap bitmap = (Bitmap)msg. obj ;

ImageSpan imageSpan = new ImageSpan(MainActivity. this,

bitmap);

//创建一个SpannableString对象,以便插//入用ImageSpan对象封装的图像

SpannableString ss = new SpannableString("img");

// 用imageSpan对象替换img

ss.setSpan(imageSpan, 0, 3,

Spannable. SPAN_EXCLUSIVE_EXCLUSIVE);

//把图片显示在界面上

textMsgLog.append(" 服务器: ");

textMsgLog.append(ss);

textMsgLog.append("\n");

}

return true;

}

});

5、在 Android Manifest.xml文件中添加网络权限:

在 uses-sdk 标签后面添加

<uses-permission android:name="android.permission.INTERNET"/>

所以,对于服务机

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

public class Server {

public void setUp(int port){

try {

//监听port端口

ServerSocket ss = new ServerSocket(port);

//循环接收客户端的访问

while(true){

Socket socket = ss.accept();

//把客户端的连接放到线程里处理

SocketThread st = new SocketThread(socket);

st.start();

}

} catch (IOException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

//服务器监听8888端口

new Server().setUp(8888);

}

}

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.Socket;

public class SocketThread extends Thread {

private Socket socket;

private DataOutputStream dataOutputStream;

public SocketThread(Socket socket) {

this. socket = socket;

}

public void run(){

try {

//得到网络连接的输入输出流对象

InputStream inputStream = socket.getInputStream();

//用数据输入流对原输入流进行封装,用于读取不同类型的数据

DataInputStream dis = new DataInputStream(inputStream);

//用数据输出流对原输出流进行封装,用于发送不同类型的数据

dataOutputStream = new DataOutputStream(socket.getOutputStream());

while(true){

//读取一个int,注意:这里是readInt方法

int msgType = dis.readInt();

//文字消息

if(msgType == 1){

//读取数据包长度

int len = dis.readInt();

//读取数据内容

byte[] bytes = new byte[len];

dis.readFully(bytes);

//转成字符串

String content = new String(bytes, "GB2312");

System. out.println(" 客户端说: "+content);

//客户端发送过来的字符串为image的话就发送一张图片过去

if(content.equals("image")){

sendImage();

} else {

//向客户端回应信息

String replyString = " 服务器收到了("+content+")";

bytes = replyString.getBytes("GB2312");

//发送数据类型, 1-文本, 2-图片

dataOutputStream.writeInt(1);

//发送数据长度

dataOutputStream.writeInt(bytes. length);

//发送数据内容

dataOutputStream.write(bytes);

//刷新缓存

dataOutputStream.flush();

}

}

//图片数据包

if(msgType == 2){

//读取数据包长度

int len = dis.readInt();

//读取数据内容

byte[] bytes = new byte[len];

dis.readFully(bytes);

//在这里可以把客户端发送的图片保存到文件,也可以做个界面显示出来,具体代码就不写了

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

//向客户端发送一张图片

public void sendImage() throws IOException{

//把一个图片文件读取到一个字节数组中

//src/wo.jpg,以文件夹ChatAppServer为起始目录

FileInputStream fis = new FileInputStream("images/wo.jpg");

int len = fis.available();

byte[] bytes = new byte[len];

fis.read(bytes);

fis.close();

//发送数据类型, 1-文本, 2-图片

dataOutputStream.writeInt(2);

//数据长度

dataOutputStream.writeInt(bytes. length);

//数据内容

dataOutputStream.write(bytes);

//刷新缓存

dataOutputStream.flush();

}

}

对于客户机

首先是Android页面:

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/textMsgLog"

android:text="" />

<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal">

<EditText

android:id="@+id/editInput"

android:layout_width="220dp"

android:layout_height="wrap_content" />

<Button

android:id="@+id/btnSend"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="send"

android:text="发送" />

</LinearLayout>

</LinearLayout>

主页面:

package com.cyw.chatapp;

import android.app.Activity;

import android.graphics.Bitmap;

import android.os.Bundle;

import android.os.Handler;

import android.os.Handler.Callback;

import android.os.Message;

import android.text.Spannable;

import android.text.SpannableString;

import android.text.style.ImageSpan;

import android.view.View;

import android.widget.EditText;

import android.widget.TextView;

import android.widget.Toast;

public class MainActivity extends Activity {

private TextView textMsgLog;

private ClientThread clientThread;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout. activity_main);

//聊天记录组件

textMsgLog = (TextView)findViewById(R.id. textMsgLog);

//创建Handler对象

Handler handler = new Handler(

//回调接口,当handler接收到消息时调用该接口的handleMessage方法

new Callback() {

//出理线程发送过来的数据

public boolean handleMessage(Message msg) {

if(msg. what == 1){

//把服务器发送过来的内容显示出来

textMsgLog.append(" 服务器: " + msg. obj .toString() +

"\n");

}

if(msg. what == 2){

//服务器发送过来的图片

Bitmap bitmap = (Bitmap)msg. obj ;

ImageSpan imageSpan = new ImageSpan(MainActivity. this,

bitmap);

//创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像

SpannableString ss = new SpannableString("img");

// 用imageSpan对象替换img

ss.setSpan(imageSpan, 0, 3,

Spannable. SPAN_EXCLUSIVE_EXCLUSIVE);

//把图片显示在界面上

textMsgLog.append(" 服务器: ");

textMsgLog.append(ss);

textMsgLog.append("\n");

}

return true;

}

});

//通信线程,通过handler对象与UI主现象发送数据

clientThread = new ClientThread(handler);

clientThread.start();

}

//向服务器发送文本内容

public void send(View v){

EditText editInput = (EditText)findViewById(R.id. editInput);

String msg = editInput.getText().toString();

boolean result = clientThread.sendText(msg);

if(result){

textMsgLog.append(" 我: "+msg+"\n");

editInput.setText("");

} else {

Toast. makeText(this, " 发送失败", Toast. LENGTH_LONG).show();

}

}

}

客户端处理线程:

package com.cyw.chatapp;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.net.Socket;

import java.net.UnknownHostException;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.Handler;

import android.os.Message;

public class ClientThread extends Thread {

//与UI主线程通信的中间代理

private Handler handler;

private DataOutputStream dataOutputStream;

private DataInputStream dataInputStream;

private Socket socket;

public ClientThread(Handler handler){

this. handler = handler;

}

//一定记得要在线程里访问网络

public void run(){

try {

//因为连接网络比较耗时间,会阻塞UI主线程

//所以连接到服务器的操作一定要放在线程的run里面

connect();

while(true){

//读取一个int,注意:这里是readInt方法

int msgType = dataInputStream.readInt();

//文字消息

if(msgType == 1){

//读取数据包长度

int len = dataInputStream.readInt();

//读取数据内容

byte[] bytes = new byte[len];

dataInputStream.readFully(bytes);

//转成字符串

String content = new String(bytes, "GB2312");

Message msg = new Message();

//消息类型

msg. what = 1;

//消息内容

msg. obj = content;

//发送给UI主线程

handler.sendMessage(msg);

}

//图片数据包

if(msgType == 2){

//读取数据包长度

int len = dataInputStream.readInt();

//读取数据内容

byte[] bytes = new byte[len];

dataInputStream.readFully(bytes);

//把字节数组还原成一个图片

Bitmap bitmap = BitmapFactory. decodeByteArray(bytes,

0, len);

Message msg = new Message();

//消息类型

msg. what = 2;

//消息内容

msg. obj = bitmap;

//发送给UI主线程

handler.sendMessage(msg);

}

}

} catch (IOException e) {

e.printStackTrace();

} finally {

close();

}

}

//链接主机

private void connect() throws UnknownHostException, IOException {

//这个地方不能填电脑的本机地址,一定要是局域网或公网的IP地址,wifi

//IPv4 地址: 10.96.23.74  IPv6 地址: 2001:250:4400:d000::3:97b8

socket = new Socket("10.96.23.74", 8888);

//得到输入输出流对象

dataInputStream = new DataInputStream(socket.getInputStream());

dataOutputStream = new DataOutputStream(socket.getOutputStream());

}

//关闭网络连接

private void close(){

if(dataInputStream != null){

try {

dataInputStream.close();

} catch (IOException e) {

}

}

if(dataOutputStream != null){

try {

dataOutputStream.close();

} catch (IOException e) {

}

}

if(socket != null){

try {

socket.close();

} catch (IOException e) {

}

}

}

//向服务器发送数据

public boolean sendText(String content){

try {

//把字符串转成字节数组

byte[] bytes = content.getBytes("GB2312");

//消息类型

dataOutputStream.writeInt(1);

//数据长度

dataOutputStream.writeInt(bytes. length);

//发送数据

dataOutputStream.write(bytes);

dataOutputStream.flush();

return true;

} catch (IOException e) {

e.printStackTrace();

}

return false;

}

}

<!--EndFragment-->

Andoird通信之简单聊天ChatApp的更多相关文章

  1. JAVA基础知识之网络编程——-基于TCP通信的简单聊天室

    下面将基于TCP协议用JAVA写一个非常简单的聊天室程序, 聊天室具有以下功能, 在服务器端,可以接受客户端注册(用户名),可以显示注册成功的账户 在客户端,可以注册一个账号,并用这个账号发送信息 发 ...

  2. Android笔记——Socket通信实现简单聊天室

    两部分,客户端和服务端 ---------------------------------------------------------------- 客户端  1.为防止ANR异常,互联网连接可用 ...

  3. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  4. 利用socket.io+nodejs打造简单聊天室

    代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...

  5. AngularJS作出简单聊天机器人

    简单聊天机器人 很初级的对话框形式.以前做对话框使用js,今天尝试使用AngularJS做出来 这里直接使用自己写的JSON数据. <!DOCTYPE html> <html lan ...

  6. iOS中XMPP简单聊天实现 好友和聊天

    版权声明本文由陈怀哲首发自简书:http://www.jianshu.com/users/9f2e536b78fd/latest_articles;微信公众号:陈怀哲(chenhuaizhe2016) ...

  7. Python Socket 简单聊天室2

    上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  8. Asp.Net SignalR - 简单聊天室实现

    简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 ...

  9. SpringBoot 搭建简单聊天室

    SpringBoot 搭建简单聊天室(queue 点对点) 1.引用 SpringBoot 搭建 WebSocket 链接 https://www.cnblogs.com/yi1036943655/p ...

随机推荐

  1. Eclipse 文件太长,导致着色异常问题

    1. 把C/C++ ->Editor->Scalability, 对应红框中的数字调大.

  2. thrift系列 - 快速入门

    1.简介           Thrift是当前流行的RPC框架之一,它有强大的代码生成引擎,可以跨语言,轻松解决程序间的通信问题. 本文旨在帮助大家快速入门,若想深入原理,请参见thrift官网:h ...

  3. (转)Xen Server删除Local Storage

    1. First, you have to determine the Storage-Repository-UUID: xe sr-list -> write down / take note ...

  4. [Angular CLI] Build application without remove dist folder for Docker Volume

    When we develop the Angular app inside Docker container, we can simulate Production envioment by bui ...

  5. Android 开源项目 eoe 社区 Android 客户端

    本文内容 环境 开源项目 eoe 社区 Android 客户端 本文介绍 eoe 社区 Android 客户端.它是一个开源项目,功能相对简单,采用侧边菜单栏.可以学习一下.点击此处查看 GitHub ...

  6. VS2015 之 常用快捷键

    调试执行 F5,终止调试执行 Shift+F5 启动执行 Ctrl+F5 查找下一个 F3,查找上一个 Shift+F3 附加到进程 Ctrl+Alt+P,逐过程 F10,逐语句执行 F11 切换断点 ...

  7. WinForm 之 程序启动不显示主窗体

    在 WinForm 程序启动时,不显示主窗体的实现方法主要有以下5种,第五种最简单,而且效果也不错,第四种方法也值得推荐. 实例代码如下: //隐藏窗体的方法1/5:不指定任何窗体为主窗体 //注意: ...

  8. Cocon90.Db调用方法

    Cocon90.DB 使用说明 开源库:https://github.com/Cocon90/Cocon90.Db Sqlite位置:https://www.nuget.org/packages/Co ...

  9. Vue.js 2.0 独立构建和运行时构建的区别

    Vue.js 2.0 独立构建和运行时构建的区别 在使用 Vue.js 2.0 时,有独立构建(standalone)和运行时构建(runtime-only)两种版本可供选择.而在 Vue.js 1. ...

  10. 简单的tcp聊天

    package com.pers.tcptest; import java.io.IOException; import java.io.InputStream; import java.io.Out ...