上回书说到,STM32通过Socket建立TCP服务器之后可以通过TCP客户端来给它发出指令,但是电脑发指令就比较麻烦,所以花了两天时间学习力Android Studio来建立一个TCP客户端与单片机通信,今天的主要内容是Android是怎么通过线程发送一个字符串,以及Android的UI怎么建立
在Android Studio中就有现成的一些工具,可以直接拖出使用,2天学会主要是UI这么搞就没有花费时间。
首先建立一个Android的工程,选取空白模板,在该工程的res文件夹下的layout文件内的文件就是我们的项目UI,下面附上我的UI
接下来是UI对应代码,仅供参考:
以上代码写完,UI结束,效果为上图
话不多说,直接上代码,由于修改原因有一些代码是无效的,但是不影响App的使用,代码具体功能我会在代码内部解释
package com.example.a96913.myapplication;
import android.content.DialogInterface; //需要的库,Android Studio会帮忙定义的
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class MaintcpclientActivity extends AppCompatActivity //主动作
{
String datatoedit; // 用于Socket的发送buff
String data10=" LED1OFF";
String data20=" LED2OFF";
String data30=" LED3OFF";
String data40=" LED4OFF";
String data11=" LED1ON";
String data21=" LED2ON";
String data31=" LED3ON";
String data41=" LED4ON"; //以上为驱动我的STM32需要的信息,未加密,大佬别喷
Button Button;//连接服务器按钮对象
Button Button1;//1号接口按钮对象
Button Button2;//2号接口按钮对象
Button Button3;//3号接口按钮对象
Button Button4;//4号接口按钮对象
EditText edittotext;//接收的数据显示编辑框对象
Socket Socket = null;//Socket
boolean buttontitle = true;//定义一个逻辑变量,用于判断连接服务器按钮状态
boolean b1 = true;//定义一个逻辑变量,用于判断1号接口按钮状态
boolean b2 = true;//定义一个逻辑变量,用于判断2号接口按钮状态
boolean b3 = true;//定义一个逻辑变量,用于判断3号接口按钮状态
boolean b4 = true;//定义一个逻辑变量,用于判断4号接口按钮状态
boolean RD = false;//用于控制读数据线程是否执行
OutputStream OutputStream = null; //定义数据输出流,用于发送数据
InputStream InputStream = null; //定义数据输入流,用于接收数据
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maintcpclient);
Button = (Button)findViewById(R.id.Button); //获取连接服务器按钮对象
Button1 = (Button)findViewById(R.id.button); //获取1号接口按钮对象
Button2 = (Button)findViewById(R.id.button2);//获取2号接口按钮对象
Button3 = (Button)findViewById(R.id.button3);//获取3号接口按钮对象
Button4 = (Button)findViewById(R.id.button4);//获取4号接口按钮对象
edittotext = (EditText)findViewById(R.id.editText);//获取接收数据显示编辑框对象
}
//1号按钮按下
public void play1(View view)
{
//验证编辑框用户输入内容是否合法
if (b1 == true)
{
//如果按钮没有被按下,则按钮状态改为按下
b1 = false;
//启动一个新的线程,用于发送数据
datatoedit = data11;
ThreadSendData t1 = new ThreadSendData();
t1.start();
//改变按钮标题
Button1.setText("1号运行中");
}
else
{
Button1.setText("1号启动"); //如果按钮已经被按下,则改变按钮标题
b1 = true; //储存状态的变量反转
datatoedit = data10;
ThreadSendData t1 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t1.start();
}
}
//2号按钮按下
public void play2(View view)
{
if (b2 == true)
{
b2 = false;
datatoedit = data21; //如果按钮没有被按下,则按钮状态改为按下
ThreadSendData t2 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t2.start();
Button2.setText("2号运行中"); //改变按钮标题
}
else
{
Button2.setText("2号启动"); //如果按钮已经被按下,则改变按钮标题
b2 = true; //储存状态的变量反转
datatoedit = data20;
ThreadSendData t2 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t2.start();
}
}
//3号按钮按下
public void play3(View view)
{
if (b3 == true)
{
b3 = false; //如果按钮没有被按下,则按钮状态改为按下
datatoedit = data31;
ThreadSendData t3 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t3.start();
Button3.setText("3号运行中"); //改变按钮标题
}
else
{
Button3.setText("3号启动"); //如果按钮已经被按下,则改变按钮标题
b3 = true; //储存状态的变量反转
datatoedit = data30;
ThreadSendData t3 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t3.start();
}
}
//4号按钮按下
public void play4(View view)
{
if (b4 == true)
{
b4 = false; //如果按钮没有被按下,则按钮状态改为按下
datatoedit = data41;
ThreadSendData t4 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t4.start();
Button4.setText("4号运行中"); //改变按钮标题
}
else
{
Button4.setText("4号启动"); //如果按钮已经被按下,则改变按钮标题
b4 = true; //储存状态的变量反转
datatoedit = data40;
ThreadSendData t4 = new ThreadSendData(); //启动一个新的线程,用于发送数据
t4.start();
}
}
//连接服务器按钮按下
public void link(View view)
{
if (buttontitle == true) //判断按钮状态
{
buttontitle = false; //如果按钮没有被按下,则按钮状态改为按下
RD = true; //读数据线程可以执行
Connect_Thread Connect_thread = new Connect_Thread(); //并创建一个新的线程,用于初始化socket
Connect_thread.start();
Button.setText("断 开 连 接"); //改变按钮标题
}
else
{
Button.setText("连 接 服 务 器"); //如果按钮已经被按下,则改变按钮标题
buttontitle = true; //储存状态的变量反转
try
{
Socket.close(); //取消socket
Socket = null; //socket设置为空
RD = false; //读数据线程不执行
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class Connect_Thread extends Thread //用线程创建Socket连接
{
public void run()
{
try {
if (Socket == null) //判断socket的状态,防止重复执行
{
Socket = new Socket("172.16.108.64",50000); //如果socket为空则执行新建一个socket
InputStream = Socket.getInputStream();//获取socket的输入流和输出流
OutputStream = Socket.getOutputStream();
ThreadReadData t1 = new ThreadReadData();//新建一个线程读数据
t1.start();
}
}
catch (Exception e) //如果有错误则在这里返回
{
e.printStackTrace();
}
}
}
class ThreadReadData extends Thread //用线程执行读取服务器发来的数据
{
public void run()
{
String textdata; //定义一个变量用于储存服务器发来的数据
while (RD) //根据RD变量的值判断是否执行读数据
{
try
{
final byte[] ReadBuffer = new byte[2048]; //定义一个字节集,存放输入的数据,缓存区大小为2048字节
final int ReadBufferLengh; //用于存放数据量
//从输入流获取服务器发来的数据和数据宽度
//ReadBuffer为参考变量,在这里会改变为数据
//输入流的返回值是服务器发来的数据宽度
ReadBufferLengh = InputStream.read(ReadBuffer);
if (ReadBufferLengh == -1) //验证数据宽度,如果为-1则已经断开了连接
{
RD = false;//重新归位到初始状态
Socket.close();
Socket = null;
buttontitle = true;
Button.setText("连 接 服 务 器");
} else {
//如果有数据正常返回则进行处理显示
textdata = new String(ReadBuffer,0,ReadBufferLengh,"GB2312");//原始编码数据
edittotext.setText(new String(textdata.getBytes(),"UTF-8"));//转为UTF-8编码后显示在编辑框中
}
} catch (Exception e)
{
e.printStackTrace();
}
}
}
}
class ThreadSendData extends Thread //用线程发送数据
{
public void run()
{
try
{
OutputStream.write(datatoedit.getBytes()); //用输出流发送数据
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
//信息框按钮按下事件
public DialogInterface.OnClickListener click1 = new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.cancel();
}
};
}
以上就是动作代码部分,这里主要讲Android Socket TCP客户端怎么发送一个字符串:
首先要通过输出流Outputstream
1.在文件开头定义输出流Outputstream,初始化为空(以下展示的代码都放在主文件了,这里只是拿出来分析)
OutputStream OutputStream = null;//定义数据输出流,用于发送数据
InputStream InputStream = null;//定义数据输入流,用于接收数据
2.定义我们要发送的字符串
String datatoedit;//发送buff
String data10="LED1OFF";
String data20="LED2OFF";
String data30="LED3OFF";
String data40="LED4OFF";
String data11="LED1ON";
String data21="LED2ON";
String data31="LED3ON";
String data41="LED4ON";
3.发送字符串
//用线程发送数据
class ThreadSendData extends Thread
{
public void run()
{
try
{
OutputStream.write(datatoedit.getBytes()); //用输出流发送数据
}catch (Exception e){
e.printStackTrace();
}
}
}
这里使用了线程发送数据,由于我在每个按钮的出发工程中就已经将我要发送的对应字符串赋值给了变量datatoedit,所以在发送时直接发送了变量datatoedit
OutputStream.write(datatoedit.getBytes());
以上这一句就是讲我们要发送的字符串写到输出流中
**注意注意:**TCP发送时发送的内容为数组,所以要在字符串变量datatoedit后加上".getBytes()"目的是将字符串中的内容一个一个放到Bytes型数组中。
点击菜单栏上方绿色三角按钮或直接Shift+F10进行编译,设备自己选一个,安卓版本需要在6.0以上,因为我的代码是基于6.0写的,得到下图界面
之后尝试连接PC启动的网络调试助手,点击连接服务器后得到下图
显示连接成功之后测试各个按钮功能,得到下图
4个按钮功能正常。
再次点击连接服务器按钮(目前已经变为断开连接),得到下图消息
显示客户端离线,由上可知,所有按钮功能正常,真是可喜可贺!!可喜可贺!!
上述功能测试完成之后就能安装使用了哦,点击Android Studio菜单栏的Build→Build Bundle(s)/APK(s)→Build APK(s)稍等片刻之后就可以在项目文件目录下\app\build\outputs\apk\debug文件夹中找到apk文件,这就是新鲜出炉的Android App了,将文件拖到自己的安卓设备即可使用。
写博客不易,希望觉得对自己有用的同志转载的时候附上我SCDN的ASWaterbenben的大名,谢谢大佬!!!!