Android平台下的TCP/IP传输(客户端)

  在工科类项目中,嵌入式系统与软件系统或后台数据库之间的信息传输是实现“物联网”的一种必要的途径,对已简单概念的物联网,通常形式都是一个单片机/嵌入式系统实现数据的采集及其处理,通过蓝牙,wifi或者是ZigBee等无线模块进行传输,再由一些软件端来显示数据实现人机交互。

  例如在进行的一个项目中,需要在stm32上获取位置的信息,再传输到移动设备或者电脑端来显示数据,选用wifi来作为传输媒介,那么就要考虑wifi间数据传输的形式——TCP或者UDP传输。

  简单记录一下在实际开发中,利用Android平台下TCP/IP协议来实现与搭载WIFI模块的硬件系统进行通信的程序设计与实现。

  设计一个界面,三个EditText,两个Button,还有一个用于显示的TextView;整体使用LinearLayout的布局(个人喜好,结构清晰)

  程序如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:gravity="center"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:hint="IP地址"
            android:id="@+id/IPAddress"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <EditText
            android:hint="端口号"
            android:id="@+id/port"
            android:layout_weight="2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/connect"
        android:text="开始连接"
        />

    <EditText
        android:hint="输入需要发送的信息"
        android:id="@+id/sendData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/send"
        android:text="发送数据"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:background="#eeeeee"
        android:id="@+id/information"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

  实现一个大致的界面,如下所示:

Android平台下的TCP/IP传输(客户端)

  接下来是功能实现部分,在TCP/IP协议的网络连接,需要两个主要信息:IP地址,以及端口号。

  在JAVA环境下,TCP连接是相对简洁的,这也是JAVA的一个优点:

  Socket socket=new Socket(IP_Address,Port);

  一句简单的话就可以实现网络连接。

  还需要一个BufferedReader和一个PrintWriter来实现数据的传输,当Socket操作完成之后,对其进行设定:

mBufferedReaderClient = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
mPrintWriterClient = new PrintWriter(mSocket.getOutputStream(),true);

  然后开辟其它线程来实现数据的传输以及一些视图的更新。

  java部分代码如下:

package com.example.hp.acceleration;

import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class MainActivity extends AppCompatActivity {

    private Button mButtonConnect;
    private Button mButtonSend;
    private TextView mTextViewMessage;
    private boolean isConnect;
    private String Information;
    private EditText mEditTextIP;
    private EditText mEditTextPort;
    private EditText mEditTextSendData;

    private Socket mSocket=null;
    private BufferedReader mBufferedReaderClient=null;
    private PrintWriter mPrintWriterClient=null;


    private String IP="";
    private int port;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()//磁盘读取操作
                .detectDiskWrites()//磁盘写入操作
                .detectNetwork()//网络操作
                .penaltyLog()//在Logcat中打印违规异常信息
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects()//泄露的SqLite对象
                .penaltyLog()
                .penaltyDeath()
                .build());

        mButtonConnect=(Button)findViewById(R.id.connect);
        mButtonSend=(Button)findViewById(R.id.send);
        mTextViewMessage=(TextView)findViewById(R.id.information);
        mEditTextIP=(EditText)findViewById(R.id.IPAddress);
        mEditTextPort=(EditText)findViewById(R.id.port);
        mEditTextSendData=(EditText)findViewById(R.id.sendData);

        mTextViewMessage.setMovementMethod(ScrollingMovementMethod.getInstance());
        mTextViewMessage.setTextIsSelectable(true);

        isConnect=false;
        mButtonSend.setEnabled(false);


        mButtonConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (isConnect)
                {
                    isConnect=false;
                    mButtonConnect.setText("开始连接");
                    mButtonSend.setEnabled(false);
                    mTextViewMessage.setText("");
                    if(mSocket!=null) {
                        try {
                            mSocket.close();
                        } catch (IOException e) {

                        }
                    }
                }else{
                    isConnect=true;
                    mButtonConnect.setText("断开连接");

                        mButtonSend.setEnabled(true);
                        IP=mEditTextIP.getText().toString();
                        String portString=mEditTextPort.getText().toString();
                        if (portString.length()>1){
                            port=Integer.valueOf(portString);
                        }
                        Thread thread=new Thread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    mSocket=new Socket(IP,port);
                                    mBufferedReaderClient = new BufferedReader(new InputStreamReader
                                            (mSocket.getInputStream()));
                                    mPrintWriterClient = new PrintWriter(mSocket.getOutputStream(),
                                            true);
                                    Message msg=new Message();
                                    msg.what=0;
                                    mHandler.sendMessage(msg);
                                }catch (IOException e) {
                                    mTextViewMessage.setText("error");
                                }
                                char[] buffer=new char[256];
                                int num=0;
                                while (isConnect)
                                {
                                    try{
                                        if ((num=mBufferedReaderClient.read(buffer))>0) {
                                            Information=getInfoBuff(buffer,num);
                                            Message msg=new Message();
                                            msg.what=1;
                                            mHandler.sendMessage(msg);
                                        }
                                    }catch (Exception e) {
                                    }
                                }

                            }
                        });
                        if (IP.length()>1&&portString.length()>=1)
                        {
                            thread.start();
                        }else
                        {
                            mTextViewMessage.setText("IP地址错误或端口号错误");
                        }

                }
                }
        });


        mButtonSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Thread thread=new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String string=mEditTextSendData.getText().toString();
                            mPrintWriterClient.print(string);
                            mPrintWriterClient.flush();
                        }catch (Exception e){
                        }
                    }
                });
                thread.start();
            }
        });


    }
    private String getInfoBuff(char[] buff,int count){
        char[] temp=new char[count];
        for(int i=0;i<count;i++){
            temp[i]=buff[i];
        }
        return new String(temp);
    }


    Handler mHandler=new Handler(){
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            if (msg.what==0){
                Toast.makeText(MainActivity.this,"连接成功!",Toast.LENGTH_SHORT).show();
            }
            else if (msg.what==1){
                mTextViewMessage.append(Information+"\r\n");

            }
        }
    };

}

  最后一点,在Android环境下,需要在AndroidManifest.xml文件下赋予权限

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

  以上几个权限是Android使用wifi进行TCP协议下通讯必须的几个。

 

Android平台下的TCP/IP传输(客户端)

上一篇:Metal 练习:第三篇-添加Texture


下一篇:uni-app 云打包证书生成笔记