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. Mongo如何在多个字段中查询某个关键字?

    If a text index has multiple fields in Mongo, how can I do a search in only one field since the weig ...

  2. [Algorithm] How many times is a sorted array rotated?

    Given a sorted array, for example: // [2,5,6,8,11,12,15,18] Then we rotated it 1 time, it becomes: / ...

  3. 恶性循环中的永生bug,可以说是相当写实了

    恶性循环中的永生bug,可以说是相当写实了

  4. maven 下载源码downloadsources

    mvn eclipse:eclipse -Ddownloadsources=true  -Ddownloadjavadocs=true

  5. PHP http_build_query()方法

    http_build_query (PHP 5) http_build_query -- 生成 url-encoded 之后的请求字符串描述 string http_build_query ( arr ...

  6. SQL Server 之 修改时不允许保存更改

    SQL Server错误提示:不允许保存更改. 您所做的更改要求删除并重新创建以下表.您对无法重新创建的表进行了更改或者启用了“阻止保存要求重新创建表的更改”选项. 修改数据库的数据结构,比如把var ...

  7. J4架构应用过程中出现的问题与解决摘录

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6369346.html sendRedirect()的页面不能用EL表达式获取参数:因为是新的request.E ...

  8. oracle列自增实现(1)-Sequence+Trigger实现Oracle列自增

    Sequence+Trigger实现Oracle列自增 序列的语法格式为: CREATE SEQUENCE 序列名 [INCREMENT BY n] [START WITH n] [{MAXVALUE ...

  9. JavaSE入门学习7:Java基础语法之语句(下)

    继续接着Java基础语法来:JavaSE入门学习5:Java基础语法(一)和JavaSE入门学习6:Java基础语法(二). 语句 Java经常使用的3种循环:while.do...while,for ...

  10. 非常漂亮滴皮肤skin++ 终极破解之法

    破解includeparametershook汇编windows *[标题]:Skin++通用界面换肤系统V2.0.1破解探讨 *[作者]:gz1X <gz1x(at)tom(dot)com&g ...