在工科类项目中,嵌入式系统与软件系统或后台数据库之间的信息传输是实现“物联网”的一种必要的途径,对已简单概念的物联网,通常形式都是一个单片机/嵌入式系统实现数据的采集及其处理,通过蓝牙,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>

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

  接下来是功能实现部分,在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传输(客户端)的更多相关文章

  1. Android平台下Dalvik层hook框架ddi的研究

    通过adbi,可以对native层的所有代码进行hook.但对于Android系统来说,这还远远不够,因为很多应用都还是在Dalvik虚拟机中运行的. 那么,有没有什么办法可以对Dalvik虚拟机中跑 ...

  2. [转帖]Android平台下OpenGL初步

    原文请看 Android平台下OpenGL初步 本文只关注于如何一步步实现在Android平台下运用OpenGl. 1.GLSurfaceView GLSurfaceView是Android应用程序中 ...

  3. 网络编程TCP/IP实现客户端与客户端聊天

    一.TCP/IP协议 既然是网络编程,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输.这里就要使用到TCP/IP协议. TCP/I ...

  4. android 网络编程--socket tcp/ip udp http之间的关系

    网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层,一般编程人员接触最多的就是应用层和运输层,再往下的就是所谓的媒体层了,不是我们研究的对象. 下面是应用层.运输层,网络 ...

  5. 前端工程师如何理解 TCP/IP 传输层协议?

    网络协议是每个前端工程师都必须要掌握的知识,TCP/IP 中有两个具有代表性的传输层协议,分别是 TCP 和 UDP,本文将介绍下这两者以及它们之间的区别. TCP/IP网络模型 计算机与网络设备要相 ...

  6. Android平台下OpenCV移植与使用---基于C/C++

    在<Android Studio增加NDK代码编译支持--Mac环境>和<Mac平台下Opencv开发环境搭建>两篇文章中,介绍了如何使用NDK环境和Opencv环境搭建与测试 ...

  7. 本学习笔记TCP/IP传输协议

    一个.通过网络发送数据,大致能够分为面向有连接与面向无连接两种类型: 1.面向无连接型包含以太网. IP.UDP等协议. 2. 面向有连接 型包含ATM.帧中继.TCP等 协议. 通过一张图了解一下: ...

  8. TCP/IP传输层,你懂多少?

    1. 传输层的主要功能是什么?2. 传输层如何区分不同应用程序的数据流?3. 传输层有哪些协议?4. 什么是UDP协议?5. 为什么有了UDP,还需要TCP?6. 什么是TCP协议?7. 怎么理解协议 ...

  9. 面试热点|理解TCP/IP传输层拥塞控制算法

    0x00.前言 通过本文你将了解到以下内容: 拥塞控制概念以及其背景 流量控制和拥塞控制的区别与联系 拥塞控制主要过程详解 伙伴们认真学习一下,让offer来得更猛烈些吧! 0x01.TCP/IP协议 ...

随机推荐

  1. nvcc fatal : Unsupported gpu architecture 'compute_11'

    使用VS编译OpenCV编译源代码时候,对Cmake生成的工程文件编译,会出现 nvcc fatal : Unsupported gpu architecture 'compute_11'  问题.原 ...

  2. C# 共享页调用css

    @RenderSection("Styles", required: false) @section Styles{ }

  3. C#--条形码和二维码的简单实现

    首先 简单的介绍一下条形码和二维码 条形码: 条形码技术是在计算机应用中产生发展起来的一种广泛应用于商业.邮政.图书管理.仓储.工业生产过程控制.交通运输.包装.配送等领域的自动识别技术.它最早出现在 ...

  4. PAT_A1129#Recommendation System

    Source: PAT A1129 Recommendation System (25 分) Description: Recommendation system predicts the prefe ...

  5. PAT_A1021#Deepest Root

    Source: PAT A1021 Deepest Root (25 分) Description: A graph which is connected and acyclic can be con ...

  6. Vue push() pop() shift() unshift() splice() sort() reverse() ...

    Vue 变异方法 push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度. pop() 方法用于删除并返回数组的最后一个元素. shift() 方法用于把数组的第一个元素从其中删除,并返回 ...

  7. Windows10系统如何清除记录和关掉xbox录制

    在Windows的Xbox平台玩游戏时,总会发现以前玩过的许多游戏进度都保留着,麻烦的是白白的成就条让人感到相当的不爽,并且想删除还删不掉.某些当年一边玩一边录制的游戏,每当重新打开的时候都会弹出录制 ...

  8. [luogu2587 ZJOI2008] 泡泡堂 (贪心)

    传送门 Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛 ...

  9. Nginx设置alias别名目录访问phpmyadmin

    引言:Nginx服务器通过设置alias别名可以使特定的目录(phpmyadmin目录)不出现在网站根目录下面,即使网站根目录被攻破,也不会影响到phpmyadmin目录里面的文件. 说明: 站点:h ...

  10. ZOJ 3362 Beer Problem

    Beer Problem Time Limit: 2000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original I ...