本文将介绍Android客户端与服务器端的通信的简单实现方法。

要两点需要注意的地方:

1.Android 端记得在AndroidManifest.xml里记得获取一下网络权限,否则无法进行网络通信,如果有需要还要获取一下SD卡读写权限。

获取方法是在AndroidManifest.xml里添加获取权限的两句话:

<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
前一句是获取网络权限,后一句是获取SD卡读写权限。


2.在Android 4.0以后,是不允许直接在主线程里直接进行网络连接操作的,因为主线程要把菊花献给UI,所以需要建立一个新的线程来进行网络操作。

当然,如果是在写测试demo,可以强行在主线程中进行网络操作,只要在代码中加入这样一句话即可:

  StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads()                .detectDiskWrites().detectNetwork().penaltyLog().build());

但是我们一般不会这样做,毕竟android4.0以后对主线程的这个设定是有它的道理的,所以我们一般会新建一个线程。

新建线程有一般两个方法:

(1)通过拓展Thread类来拓展多线程

(2)通过Runnable接口来创建多线程


在传输协议方面,这里一般有两种传输协议可选,即我们所熟知的TCP和UDP协议,一个是面向连接的协议,一个是面向无连接的协议。

因为做测试demo的时候要传输的东西很少,只有实现能连上服务器并进行传输就可以了,所以我们先选用UDP来做,一边发出去另一边接收,这边发完那边能收到就算是成功了。



好,开始动手写代码。



首先,我们在eclipse用Java写一个简单的服务器程序,用来接收android端发来的信息。

package com.cky;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class Server2_1 {public static void main(String[] args) throws IOException {/* * 接收客户端发送的数据 *///1.创建服务器端DatagramSocket,指定端口DatagramSocket socket=new DatagramSocket(8800);//2.创建数据报,用于接收客户端发送的数据byte[] data =new byte[1024];//创建字节数组,指定接收的数据包的大小DatagramPacket packet=new DatagramPacket(data, data.length);//3.接收客户端发送的数据System.out.println("****我是服务器,客户端到我碗里来!****");socket.receive(packet);//此方法在接收到数据报之前会一直阻塞//4.读取数据String info=new String(data, 0, packet.getLength());System.out.println("客户端说:"+info);/* * 向客户端响应数据 *///1.定义客户端的地址、端口号、数据InetAddress address=packet.getAddress();int port=packet.getPort();byte[] data2="客户端你好,我是服务器".getBytes();//2.创建数据报,包含响应的数据信息DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);//3.响应客户端socket.send(packet2);//4.关闭资源socket.close();}}

启动程序,在控制台输出这样一句话,等待Android端发信息过来:



然后,开始进行android端的代码编写。


这里我们先写一个测试demo,就不新建线程了,直接强行获取在主线程里进行网络操作的权限

MainActivity.java

package com.example.pc.client2;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import com.example.pc.client2.Tool.toolSend1;import java.io.IOException;public class Client2_MainActivity extends AppCompatActivity {    private Button btnSend;    private EditText etGetText;    private TextView tvRecevied;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_client2__main);        intLayout();    }    private void intLayout() {        btnSend = (Button) findViewById(R.id.btnSend);        btnSend.setOnClickListener(new Click());        etGetText = (EditText) findViewById(R.id.etGetText);        tvRecevied = (TextView) findViewById(R.id.tvReceviedStr);    }    private class Click implements View.OnClickListener {        @Override        public void onClick(View v) {            //通过一个工具来实现发送信息            String sendStr = String.valueOf(etGetText.getText());            String receivedStr = null;            try {                receivedStr=toolSend1.send(sendStr);            } catch (IOException e) {                e.printStackTrace();            }                tvRecevied.setText("received:" + receivedStr);                System.out.println("received:" + receivedStr);                   }    }}


工具类部分代码:

package com.example.pc.client2.Tool;import android.os.StrictMode;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;/** * Created by pc on 2015/10/24. */public class toolSend1 {    public static String send(String sendStr) throws IOException {         /* * 向服务器端发送数据 */        //1.定义服务器的地址、端口号、数据        //(cmd: arp -a)        byte[] bs = new byte[] { (byte) 192, (byte) 168, (byte)191, (byte)1 };        InetAddress address= null;        try {            address = InetAddress.getByAddress(bs);        } catch (UnknownHostException e) {            e.printStackTrace();        }        int port=8800;        byte[] data=sendStr.getBytes();        //2.创建数据报,包含发送的数据信息        DatagramPacket packet=new DatagramPacket(data, data.length, address, port);        //3.创建DatagramSocket对象        DatagramSocket socket= null;        try {            socket = new DatagramSocket();        } catch (SocketException e) {            e.printStackTrace();        }        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads()                .detectDiskWrites().detectNetwork().penaltyLog().build());        //4.向服务器端发送数据报        try {            socket.send(packet);        } catch (IOException e) {            e.printStackTrace();        }/* * 接收服务器端响应的数据 */        //1.创建数据报,用于接收服务器端响应的数据        byte[] data2=new byte[1024];        DatagramPacket packet2=new DatagramPacket(data2, data2.length);        //2.接收服务器响应的数据            socket.receive(packet2);        //3.读取数据        String reply=new String(data2, 0, packet2.getLength());        //4.关闭资源        socket.close();        return reply;    }}


服务器端收到信息后进行相应:



客户端收到服务器端返回的信息:



很明显,这里返回的信息出现了乱码。这由于中文编码格式的原因造成的,我们需要对编码格式进行设定,这里我们统一使用utf-8。


byte[] data2="客户端你好,我是服务器".getBytes("UTF-8");


把这一句的参数设置为utf-8就可以了,用其他编码格式的也是这样设置。



开头说到,Android4.0以后是不允许在主线程里进行网络链接操作的,上面我们是强行在主线程里进行网络操作,但是只能撑一时不能撑一时。比如,此时手机网络开关没有打开或者服务器关闭没有响应的情况下,线程就会卡在那然后程序强退掉,显然,这是很危险的,所以我们必须新建线程进行网络操作,


下面介绍两种新建线程的方法。


在此之前,我们先把强行在主线程进行网络操作的一句代码注释掉

  StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads()                .detectDiskWrites().detectNetwork().penaltyLog().build());


1.扩展java.lang.Thread类,也就是把run()方法写到线程里面。

这里我们一般用handle机制实现activity和Runnable之间的交互

贴代码:

package com.example.pc.client2;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import com.example.pc.client2.Tool.toolSend1;import java.io.IOException;public class Client2_MainActivity extends AppCompatActivity {    private Button btnSend;    private EditText etGetText;    private TextView tvRecevied;    private String sendStr = null;    private String receivedStr = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_client2__main);        intLayout();    }    private void intLayout() {        btnSend = (Button) findViewById(R.id.btnSend);        btnSend.setOnClickListener(new Click());        etGetText = (EditText) findViewById(R.id.etGetText);        tvRecevied = (TextView) findViewById(R.id.tvReceviedStr);    }    private class Click implements View.OnClickListener {        @Override        public void onClick(View v) {            //通过一个工具来实现发送信息            sendStr = String.valueOf(etGetText.getText());            Thread thread = new Thread(new Runnable() {                @Override                public void run() {                    // TODO Auto-generated method stub                    try {                        receivedStr = toolSend1.send(sendStr);                    } catch (IOException e) {                        e.printStackTrace();                    }                    Message message = new Message();                    message.what = 1;                    mHandler.sendMessage(message);                }            });            thread.start();        }    }    public Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {                case 1:                    tvRecevied.setText("received:" + receivedStr);                    System.out.println("received:" + receivedStr);                    break;                default:                    break;            }            super.handleMessage(msg);        }    };}

2. 实现Runnable接口,让类实现Runnable接口,然后把run方法单独提出来

package com.example.pc.client2;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import com.example.pc.client2.Tool.toolSend1;import java.io.IOException;public class Client2_MainActivity extends AppCompatActivity implements Runnable  {    private Button btnSend;    private EditText etGetText;    private TextView tvRecevied;    private String sendStr = null;    private String receivedStr = null;    private Thread thread;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_client2__main);        intLayout();         thread=new Thread(this);    }    private void intLayout() {        btnSend = (Button) findViewById(R.id.btnSend);        btnSend.setOnClickListener(new Click());        etGetText = (EditText) findViewById(R.id.etGetText);        tvRecevied = (TextView) findViewById(R.id.tvReceviedStr);    }    private class Click implements View.OnClickListener {        @Override        public void onClick(View v) {            //通过一个工具来实现发送信息            sendStr = String.valueOf(etGetText.getText());            thread.start();        }    }    public void run() {        // TODO Auto-generated method stub        try {            receivedStr = toolSend1.send(sendStr);        } catch (IOException e) {            e.printStackTrace();        }        Message message = new Message();        message.what = 1;        mHandler.sendMessage(message);    }    public Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {                case 1:                    tvRecevied.setText("received:" + receivedStr);                    System.out.println("received:" + receivedStr);                    break;                default:                    break;            }            super.handleMessage(msg);        }    };}






更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(二)| 一文带你读懂Nginx的正向与反向代理
  3. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  4. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  5. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  6. Android应用程序模型:应用程序,任务,进程,线程
  7. Android中ContentProvider的实现及定义自己的ContentProvider
  8. Android(安卓)ContentResolver使用说明
  9. ANDROID GridView 分页平滑滑动 效果的实现(基于android TV遥控器

随机推荐

  1. Android(安卓)错误信息捕获发送至服务器
  2. android jni中将大数据回调到java层的时
  3. 使用Ramdisk加速Android工程的编译 (Andro
  4. Android聊天列表Demo(QQ,微信,等通讯工具的
  5. Android(安卓)教程:如何刷入通讯基带
  6. 价格公道的 ViewSonic ViewPad 7e Androi
  7. 利用android_ndk开发OpenGLES如何利用上
  8. 作为一个Android开发者,你迷茫了吗?(内附1T
  9. 通过View.post()获取View的宽高引发的两
  10. android 微博登录与分享集成