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. Cognos11只需简单几步创建你的Dashboard

    一.环境 操作系统:win10 数据库   :SQLserver 2008 R2 软件版本:IBM Cognos Analytics 11.0.6 浏览器   :IE 11 二.开始创建仪表板 2.1 ...

  2. SharePoint CAML Query小结

    CAML的结构. <View Type="HTML" Name="Summary"> <ViewBody ExpandXML="TR ...

  3. How could I create a custom windows message?

    [问题] Our project is running on Windows CE 6.0 and is written in C++ . We have some problems with the ...

  4. springboot 中使用事务

    直接在service 层的方法上加上@Transactional 注解就ok. 注意事项: 1.Spring 基于注解的声明式事物 @Transactional 默认情况下只会对运行期异常(java. ...

  5. 机器学习之深入理解SVM

    在浏览本篇博客之前,最好先查看一下我写的还有一篇文章机器学习之初识SVM(点击可查阅哦).这样能够更好地为了结以下内容做铺垫! 支持向量机学习方法包括构建由简至繁的模型:线性可分支持向量机.线性支持向 ...

  6. FutureTask使用完整演示样例

    MainActivity例如以下: package cc.cv; import java.util.concurrent.FutureTask; import android.os.Bundle; i ...

  7. 不同版本的tomcat下载路径

    1.由于安全问题,有些tomcat存在漏洞.为了升级要么修复漏洞,要么就直接升级tomcat. 一般升级tomcat比较省事.但是找到相应版本的tomcat比较难,所以还是要自己寻找对应的tomcat ...

  8. Android学习笔记四:activity的四种启动模式

    Activity有四种启动模式:standard,singleTop,singleTask,singleInstance. 1.standard:标准启动模式 默认模式,这个模式下启动的Activit ...

  9. Java通过join方法来暂停当前线程

    目标线程的join方法暂停当前线程,直到目前线程完成(从run()方法返回). Java代码: package Threads; import java.io.IOException; /** * C ...

  10. ps 如何制作动态打字图?

      1.情景展示 有几句话,想以打字的形式出现,而不是干巴巴的几个字,如何实现这个有趣的效果呢? 2.解决方案 第一步:录制屏幕:将想展示的文字逐字打出来-->保存: 第二步:将录制的视频使用p ...