这学期有个课设,我们组我负责一个手机APP的开发,虽然刚开始说要实现什么智能导航,类似高德地图那种,但最后阉割的只剩一个Socket通信了,因为之前没有接触过(可能之后也不会再接触),记录一下开发中遇到的问题。

1.开发工具:Andriod Studio,主要功能:实现与开发板的Socket通信,具体是手机端收到板子消息按钮变色或者文本框显示对应文字,手机端也会发送消息给板子,让板子跳转用户操作界面,整个就是一个简单的前端,逻辑不需要手机端处理。手机端只负责显示。
2.实现效果:

3.一些关键问题和收获:
1)andriod studio 的使用:
感觉还是比较复杂的,前期的一些环境配置有点忘了,按照提示做就可以,主要是手机运行环境的一些配置,然后之后在打包程序安装在手机上出了点问题,需要密钥,按网上指导就可以。
对自带模板的灵活使用:as自带很多模板,比如我开发的这个丑陋的app就是在bottom Navigation Activity这个现成模板的基础上进行开发的。

之前as排版的Xml文件,下载手机上就会变乱。后面不知不觉就好了,注意这个问题。
2)Socket通信:
这个是这个项目的一个主要工作,其中遇到的第一个问题,怎么创建Socket通信:

class ConnectThread extends Thread {public void run() {try {//新建Socketsocket = new Socket("192.168.4.1", 8086);System.out.println("创建Socket成功");} catch (IOException e) {e.printStackTrace();}}}

Socket的收发信息:注意Socket的收发信息或者说对网络的操作不能直接在主线程进行,一般都需要开子线程。
Socket的收信息:

final byte[] buffer = new byte[1024];//创建接收缓冲区try {inputStream = socket.getInputStream();System.out.println("Socket接收数据成功");} catch (IOException e) {e.printStackTrace();}int len = 0;//数据读出来,并且返回数据的长try {len = inputStream.read(buffer);System.out.println("接收数据大小" + len);} catch (IOException e) {e.printStackTrace();}//BUFFER 内容转为字符串String recvStr = new String(buffer, 0, len);

Socket的发信息:

 //控制子线程开始public void buttonFunc() {// 在主线程中需要发送数据的代码片断前插入// 阻塞主线程,使子线程按照“同步”的方式执行try {System.out.println("线程开始");new Thread(sendthread).start();    // 线程启动new Thread(sendthread).join();     // 线程加入执行队列,主线程被阻塞,等待子线程执行完毕} catch (Exception e) {e.printStackTrace();System.out.println(e.toString());}}// 发送数据子线程final Runnable sendthread = new Runnable() {@Overridepublic void run() {try {System.out.println("发送数据的子线程执行中");try {try {//输出流初始化outputStream = socket.getOutputStream();System.out.println("outputStream创建成功");} catch (IOException e) {e.printStackTrace();}try {//写入数据outputStream.write(sendbuf);outputStream.flush();System.out.println("数据写入成功");} catch (IOException e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}System.out.println("数据发送成功,子线程执行完毕");} catch (Exception e) {e.printStackTrace();System.out.println("子线程:"+ e.toString());}}};

socket的数据解析及数据格式:
收信息需要先转换为string类型,发信息如果要发16进制,byte数组直接写成16进制的形式。

源码:
美食城:

package com.example.parkingassitant2.ui.home;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;import com.example.parkingassitant2.databinding.FragmentHomeBinding;import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;public class HomeFragment extends Fragment {private FragmentHomeBinding binding;//发送数据保存byte[] sendbuf = {(byte) 0xaa, (byte) 0xaa,0x03, (byte) 0x12,0x03,0x18, (byte) 0xaa};Socket socket = null;        //定义socketOutputStream  outputStream = null;    //定义输出流(发送)public View onCreateView(@NonNull LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {HomeViewModel homeViewModel =new ViewModelProvider(this).get(HomeViewModel.class);binding = FragmentHomeBinding.inflate(inflater, container, false);View root = binding.getRoot();ConnectThread ct;ct = new ConnectThread();ct.start();//江底捞final Button jiangdilao = binding.xiaocaiyuan;//湖底捞按钮final Button hudilao = binding.A2;//河底捞按钮final Button hedilao = binding.B1;//海底捞按钮final Button haidilao = binding.B2;//KFC按钮final Button KFC = binding.C1;//小菜园按钮final Button xiaocaiyuan = binding.C2;//万达影城按钮final Button wanda = binding.D1;//星巴克按钮final Button starbuck = binding.D2;//江底捞按钮监听函数jiangdilao.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x12, 0x03, 0x18, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//湖底捞按钮监听函数hudilao.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x21, 0x03, 0x27, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//河底捞按钮监听函数hedilao.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x22, 0x03, 0x28, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//海底捞按钮监听函数haidilao.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x11, 0x03, 0x17, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//小菜园按钮监听函数xiaocaiyuan.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x13, 0x03, 0x19, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//星巴克按钮监听函数starbuck.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x14, 0x03, 0x1a, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//肯德基按钮监听函数KFC.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x23, 0x03, 0x29, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});//电影院按钮监听函数wanda.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//不同按钮对应不同的数据流sendbuf = new byte[]{(byte) 0xaa, (byte) 0xaa, 0x03, (byte) 0x24, 0x03, 0x2a, (byte) 0xaa};buttonFunc();Toast.makeText(getContext(), "预约成功,请更新停车场信息!", Toast.LENGTH_SHORT).show();}});return root;}class ConnectThread extends Thread {public void run() {try {//两个不同IP地址。网络助手和板子//socket = new Socket("192.168.71.1", 8086);//新建Socketsocket = new Socket("192.168.4.1", 8086);System.out.println("创建Socket成功");} catch (IOException e) {e.printStackTrace();}}}@SuppressLint("SuspiciousIndentation")@Overridepublic void onDestroyView() {super.onDestroyView();binding = null;try {if(socket != null) {socket.close();}} catch (IOException e) {e.printStackTrace();}}//控制子线程开始public void buttonFunc() {// 在主线程中需要发送数据的代码片断前插入// 阻塞主线程,使子线程按照“同步”的方式执行try {System.out.println("线程开始");new Thread(sendthread).start();    // 线程启动new Thread(sendthread).join();     // 线程加入执行队列,主线程被阻塞,等待子线程执行完毕} catch (Exception e) {e.printStackTrace();System.out.println(e.toString());}}// 发送数据子线程final Runnable sendthread = new Runnable() {@Overridepublic void run() {try {System.out.println("发送数据的子线程执行中");try {try {//输出流初始化outputStream = socket.getOutputStream();System.out.println("outputStream创建成功");} catch (IOException e) {e.printStackTrace();}try {//写入数据outputStream.write(sendbuf);outputStream.flush();System.out.println("数据写入成功");} catch (IOException e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}System.out.println("数据发送成功,子线程执行完毕");} catch (Exception e) {e.printStackTrace();System.out.println("子线程:"+ e.toString());}}};
}

停车场:

package com.example.parkingassitant2.ui.dashboard;import android.annotation.SuppressLint;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;import com.example.parkingassitant2.databinding.FragmentDashboardBinding;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;public class DashboardFragment extends Fragment {private FragmentDashboardBinding binding;Socket socket = null;     //定义socketOutputStream outputStream = null;    //定义输入流(接收)public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {DashboardViewModel dashboardViewModel = new ViewModelProvider(this).get(DashboardViewModel.class);binding = FragmentDashboardBinding.inflate(inflater, container, false);View root = binding.getRoot();ConnectThread ct;ct = new ConnectThread();ct.start();return root;}class ConnectThread extends Thread{InputStream inputStream=null;    //定义输入流(接收)final Button A1 =binding.A1;final Button A2 = binding.A2;final Button D1 = binding.D1;public void run(){System.out.println(Thread.currentThread().getName()+": Hello");try {//socket = new Socket("192.168.71.1", 8086);socket = new Socket("192.168.4.1", 8086);binding.textView5.setText("连接成功");System.out.println("创建Socket成功");} catch (IOException e) {System.out.println("创建Socket失败");e.printStackTrace();}try{while (true){final byte[] buffer = new byte[1024];//创建接收缓冲区try {inputStream = socket.getInputStream();System.out.println("Socket接收数据成功");} catch (IOException e) {e.printStackTrace();}int len = 0;//数据读出来,并且返回数据的长try {len = inputStream.read(buffer);System.out.println("接收数据大小" + len);} catch (IOException e) {e.printStackTrace();}//BUFFER 内容转为字符串String recvStr = new String(buffer, 0, len);//找到读取开始处,一般为0int stadex = recvStr.indexOf("aaaa");System.out.println("解析数据开始位置" + stadex);int check_3,check_4,check_5,check_6;while(stadex < len){stadex = recvStr.indexOf("aaaa",stadex);int funcType_sta = stadex+4;int funcType_end = stadex+6;if(funcType_end > len || funcType_sta >= len){break;}//位置3是操作类型 02 是显示车牌预约停车场String pos3 = recvStr.substring(funcType_sta,funcType_end);// check_3 = Integer.parseInt(pos3);stadex = funcType_end;//停车预约功能中,位置4是车牌号String pos4 = recvStr.substring(stadex,stadex+2);//check_4 = Integer.parseInt(pos4);stadex += 2;//停车预约功能中,位置5是目的地String pos5 = recvStr.substring(stadex,stadex+2);//check_5 = Integer.parseInt(pos5);stadex += 2;String pos6 = recvStr.substring(stadex,stadex+2);//check_6 = Integer.parseInt(pos6);stadex += 2;//if( check_6 != check_3+check_4+check_5) break;stadex += 2;System.out.println("解析数据包" + "aaaa" + pos3 + pos4 + pos5 + pos6 + "aa");System.out.println("操作类型指示值:" + pos3);switch(pos3){case "01": {System.out.println("操作类型为欢迎车牌进站");String showText = null;switch (pos4) {case "01":showText = "欢迎京A00001";break;case "02":showText = "欢迎青ASB520";break;case "03":showText = "欢迎皖A66666";break;case "04":showText = "欢迎宁E88888";break;default:break;}binding.textView5.setText(showText);break;}case "04": {System.out.println("操作类型为停车预约");String showText = null;switch (pos4) {case "01":showText = "京A00001";break;case "02":showText = "青ASB520";break;case "03":showText = "皖A66666";break;case "04":showText = "宁E88888";break;default:break;}String address = null;switch (pos5){case "11":address = "海底捞";break;case "12":address = "江底捞";break;case "13":address = "小菜园";break;case "14":address = "星巴克";break;case "21":address = "湖底捞";break;case "22":address = "河底捞";break;case "23":address = "肯德基";break;case "24":address = "电影院";break;case "a1":address = "A1";break;case "a2":address = "A2";break;case "d1":address = "D1";break;default:break;}binding.textView5.setText(showText+"车主预约车位:" + address);break;}case "03": {System.out.println("操作类型为车位状态变更");switch (pos4) {case "a1": {if (pos5.equals("00")) {binding.A1.setBackgroundColor(Color.parseColor("#00FF00"));} else if (pos5.equals("01")) {binding.A1.setBackgroundColor(Color.parseColor("#FF0000"));} else if (pos5.equals("02")) {binding.A1.setBackgroundColor(Color.parseColor("#FFFF00"));}break;}case "a2": {System.out.println("pos5: ");System.out.println(pos5);if (pos5.equals("00")) {binding.A2.setBackgroundColor(Color.parseColor("#00FF00"));} else if (pos5.equals("01")) {binding.A2.setBackgroundColor(Color.parseColor("#FF0000"));} else if (pos5.equals("02")) {binding.A2.setBackgroundColor(Color.parseColor("#FFFF00"));}break;}case "d1": {if (pos5.equals("00")) {binding.D1.setBackgroundColor(Color.parseColor("#00FF00"));} else if (pos5.equals("01")) {binding.D1.setBackgroundColor(Color.parseColor("#FF0000"));} else if (pos5.equals("02")) {binding.D1.setBackgroundColor(Color.parseColor("#FFFF00"));}break;}default:break;}}default:break;}}}} catch (Exception ex) {ex.printStackTrace();}}}@SuppressLint("SuspiciousIndentation")@Overridepublic void onDestroyView() {super.onDestroyView();try {if(socket != null) {socket.close();}} catch (IOException e) {e.printStackTrace();}binding = null;}
}

Andriod入门级开发相关推荐

  1. andriod socket开发问题小结

    andriod socket开发问题小结 个人信息:就读于燕大本科软件project专业 眼下大四; 本人博客:google搜索"cqs_2012"就可以; 个人爱好:酷爱数据结构 ...

  2. Python + Django 入门级开发手顺

    Python + Django 入门级开发手顺 一.python 简介 1.1 安装python 解释器,网址:Welcome to Python.org,没啥说的老规矩双击下一步(ps:python ...

  3. APP源码 教程 网页转APP 安卓Andriod应用开发 手机APP 移动网站

    本教程针对目前会制作网站并且想向网站移动端APP发展,并且善于技术钻研和研究的用户,怎么把网页转成APP.制作容易修改的APP.网站开发人员向移动APP制作端转变.快速开发APP,安卓Andriod应 ...

  4. Atmel为基于ARM7的可定制微控制器推出入门级开发工具包

    爱特梅尔公司(Atmel Corporation) 宣布推出AT91CAP7A-STK入门级开发工具包,是专为评测其基于ARM7 处理器的CAP可定制 微控制器(MCU)系列而设的入门级工具.CAP7 ...

  5. Spring2.5整合Ibatis入门级开发实例

    分类: SPRING IBATIS2010-11-22 20:19 1170人阅读 评论(0) 收藏 举报 ibatisspringstringpropertiesclassuser 最近一直在看sp ...

  6. Andriod Studio 开发环境搭建

    Andriod Studio从零开始的安卓开发环境搭建 官网下载android studio 阅读.勾选同意协议并点击下载 下载完成后打开 安装完成,打开后 创建项目 创建一个空Activity的项目 ...

  7. andriod的开发

    Android的开发过程 第一步:首先开发ui界面.activity_main.xml文件.主要就是画界面. 第二步:在java文件当中进行界面编程.在一个成熟的andriod系统中,有多个activ ...

  8. 写给小白的Construct2入门级开发指南

    Construct2是由Scirra有限公司开发的一款跨平台HTML5游戏引擎.Construct2的优势就在于入门简单快速上手,即使是对编程一无所知的人也可以用它很快地做出作品来.它的功能确实不如U ...

  9. UDF(PYTHON / JAVA)入门级开发

    开发前的声明         udf开发是在数据分析的时候如果内置的函数解析不了的情况下去做的开发,比方说你只想拆分一个字段,拼接一个字段之类的,就不要去搞udf了,这种基本的需求自带函数完全支持,具 ...

最新文章

  1. 手把手快速实现 Resnet 残差模型实战
  2. 【报错笔记】使用MultipartFile 出现异常:java.lang.ClassNotFoundException: org.apache.commons.fileupload...
  3. S5PV210的地址映射图
  4. C语言编杂志程序,c语言程序错误修改
  5. Problem D: 编程题B-向量的数量积
  6. IPv4与IPv6数据报格式
  7. [学习总结]6、Android异步消息处理机制完全解析,带你从源码的角度彻底理解
  8. 解三对角线性方程组的追赶法
  9. 3.excel 生成 sql
  10. 【Arcpy】Python in ArcGIS
  11. 基于JSP实现的影视创作论坛系统
  12. C++语言里的pow函数(初学)
  13. 奇虎终于涉足生活搜索
  14. 武音硕士研究生《计算机音乐作曲》培训,武汉音乐学院2016年硕士考试《计算机音乐作曲》大纲及参考书目...
  15. Pycharm 注册 Pycharm 破解 Pycharm 注册破解 亲测多法 仅此方有效 有效期至2099年
  16. 北京慈文影视制作有限公司诉被告北京百度网讯科技有限公司侵犯著作权纠纷一案判决书
  17. word无法打开请去应用商店_抖音去水印 | HTTP Catcher方法全解析
  18. openTSDB详解之Writing Data
  19. 聊聊soho办公-人们为什么越来越累
  20. blur和GaussianBlur

热门文章

  1. HCNP-Cloud云计算认证--学习
  2. 山东黄金三山岛金矿:智能矿山里的“掘金人”
  3. 收银管理系统给商超带来哪些便利?
  4. 基于用户id的最优邀请码生成方案
  5. linux snmp 客户端,从Linux SNMP说起到community strings
  6. h16网卡linux驱动下载,【驱动】在LINUX(ubuntu)系统下安装RTL8111/8168网卡驱动程序(技嘉H61主板)...
  7. 从初学者的角度一起谈谈设计模式之策略模式
  8. 用python发邮件为什么接收不了_使用python发送邮件和接收邮件
  9. 物联网大数据平台的主要功能和特点
  10. wemos D1 Mini (esp8266)实验九 --- blynk APP远程控制格力空调开机并显示温湿度DHT22