基于局域网内物联网的androidAPP开发——实现消息上报与命令下达

Android物联网应用程序开发 最简单的界面布局 XML Attributes有三个属性:①设置前景色Android:foreground②控制前景色的重心Android:foregroundGravity③根据参数值决定是设置测试所有的元素Android:measureAllChildren。Activity活动(核心组件,里面有基本函数)→Frame片段(跨设备扩展能力)→Layout布局(排列设置)→Wideget小部件(按钮、文本框、编辑框......)①XML方式,使用XML文件描述界面布局(优势:将程序的表现层和控制层分离; 阅读详情

目录

写在前面

前提准备 

本次干的事情——编写安卓app

正文

比如 子线程定时获取数据库信息实时更新UI

 比如子线程判断主线程事件进行数据操作实现对设备的控制


写在前面

为实现第三方移动端控制的要求,我需要实现一个在个人局域网内控制设备的移动端APP。

前提准备 

一个已经实现好通信控制的硬件和相关外设(单片机)。

一块stm32主控板,若干块通信模块(esp32,lora模块)。

一个emqx的mqtt消息服务器。

一个自己写网络接口的java客户端(一个基于springboot整合mybatis的后端服务器,提供命令调用的接口和监听硬件采集的数据并转储于数据库)。

这个java客户端连接mqtt服务器,订阅数据获取的主题,发布对应主题的消息以控制硬件。

在以上的前提都准备后,理论上我已经干的差不多的,安卓只是一个写界面来更好地服务与我控制的操作而已。。。。我可以在网页上直接访问java客户端提供的接口,来访问硬件采集的数据,控制硬件的外设,以及干更多你想干的事情(比如RF高频卡感应来模拟门禁,通过发送的信息实现语音播报和语音控制等等)

本次干的事情——编写安卓app

我的想法就是越简单越好,这会让人更加地清晰和明白,我没有像网上一般的那样让安卓去连接

mqtt服务器,然后通过安卓与mqtt服务器直接打交道,(获取数据和命令控制)。但是,我只是想直接简单明了的调用接口,以最简单的http请求的方式实现我的目的。为了这个,java客户端干了所有的事,再提供访问的接口。

参考我的java客户端

局域网内用JAVA建立MQTT客户端监听MQTT服务器消息并持久化到数据库_昊月光华的博客-优快云博客_java mqtt服务端

java客户端运行

 提供接口(http请求)访问

发布命令

当然安卓连接mqtt服务器也不是一件难事,问题在于假如我有多个应用程序都要访问数据和控制呢?哪不是每一个都得连接mqtt服务器,每一个都要写监听对应主题以及发布主题消息的方法?

当然,目前很多的外网云平台正是提供第三方访问的接口请求。也就是API

比如巴法云平台,华为云平台等等。

正文

首先是编写界面和交互逻辑代码,最主要的也就是主线程与子线程的通信,也就是子线程获取数据,主线程更新界面。

这里有常见几种的情形:

  • 在一个页面内(activity)内,创建一个内部类(继承线程类,重写run方法),子线程不断地获取数据,然后通过runonUIthread 更新界面。
  • 主线程持有子线程的handler引用,子线程收到主线程发过来的message ,通过message.what判断是哪个控件发过来的,然后进行数据操作(访问数据库等等),数据操作完后,通过runonUIthread 更新UI界面。

比如 子线程定时获取数据库信息实时更新UI

在首页中

package com.example.yuezhenhao;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.yuezhenhao.HttpRequest.DAO;

import java.security.PrivateKey;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private View exit,mainpage,control,chart,querypage;

    private TextView runt, temp, humi, ls,tl,hl,ll,state,isc;
    private  String TAG="MAIN";
    int i=0;
    private Handler mHandler= new Handler(Looper.getMainLooper()) {
        @Override
        //重写handleMessage方法,根据msg中what的值判断是否执行后续操作
        public void handleMessage(Message msg) {

            if (msg.what == 0) {
                i++;
                runt.setText(String.valueOf(i));


            }
        }
    };





    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //开启工作线程
        WorkThread workThread = new WorkThread();
        workThread.start();
         querypage=findViewById(R.id.querypage);



        init(); //初始化控件


        //转主页
        mainpage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e(TAG, "ToMainPage ");
            }
        });
        //转控制页面
        control.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e(TAG, "To Control");
                Intent intent = new Intent(MainActivity.this, Conrrol.class);
                startActivity(intent);

            }
        });

        //转图表页面
        chart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e(TAG, "To Chart");
                Intent intent = new Intent(MainActivity.this, DatesTable.class);
                startActivity(intent);
            }
        });
        //退出程序
        exit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //退出整个应用程序
                Log.e(TAG, "exit" );
                finishAffinity();
                System.exit(0);

            }
        });

       // 转查询页面
        querypage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Log.e(TAG, "query" );
                Intent intent = new Intent(MainActivity.this,  QuertDate.class);
                startActivity(intent);


            }
        });




    }




    /**
     * 初始化组件
     */
    public void init() {

        runt = findViewById(R.id.conf);
        temp = findViewById(R.id.temp);
        humi= findViewById(R.id.humi);
        ls = findViewById(R.id.ls);

        tl = findViewById(R.id.tl);
        hl= findViewById(R.id.hl);
        ll = findViewById(R.id.ll);
        isc=findViewById(R.id.isc);

        state=findViewById(R.id.state);
        state.setText("连接中");

        mainpage=findViewById(R.id.mainpage);
        control=findViewById(R.id.control);
        chart=findViewById(R.id.table);

        exit=findViewById(R.id.exit);


    }





//工作线程刷新主页数据
class WorkThread extends Thread {
        private  String _temp;
    private  String _humi;
    private  String _ls;

    //定义阈值
    private  String TempLimit;
    private  String HumiLimit;
    private  String LsLimit;
    private  String _isc; //是否自动控制

    private boolean cons=false;
    private   Handler workhandler;
    private  int time=0;
    public void run() {
        new Timer().schedule(new TimerTask() {
            @SuppressLint("ResourceAsColor")
            @Override
            public void run() {
                time++;
                JSONArray  limits= null;
                JSONObject LatestDates=null;
                try {
                    limits = DAO.GetLimit();
                    LatestDates=(JSONObject) DAO.GetLatest().get(0);

                    cons=true;
                    TempLimit=((JSONObject)limits.get(0)).getString("val");
                    HumiLimit=((JSONObject)limits.get(1)).getString("val");
                    LsLimit=((JSONObject)limits.get(2)).getString("val");
                    _isc=((JSONObject)limits.get(3)).getString("val");


                    _temp=LatestDates.getString("msg1")+"℃";
                    _humi=LatestDates.getString("msg2")+"%";
                    _ls=LatestDates.getString("msg3")+"lx";


                    if(_isc.equals("1")){
                        _isc="开启";
                    }
                    else
                        _isc="关闭";

                } catch (Exception e) {
                    e.printStackTrace();
                    cons=false;

                }



                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        runt.setText(time+"s");
                        tl.setText(TempLimit);
                        hl.setText(HumiLimit);
                        ll.setText(LsLimit);
                        isc.setText(_isc);

                        temp.setText(_temp);
                        humi.setText(_humi);
                        ls.setText(_ls);


                        if(cons)state.setText("已连接");
                        else {
                            state.setText("断开连接");
                            state.setTextColor(R.color.red);
                        }
                    }
                });

            }
        }, 0, 1000);


    }
}


}







 

 

 比如子线程判断主线程事件进行数据操作实现对设备的控制

package com.example.yuezhenhao;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.StrictMode;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.Toast;

import com.example.yuezhenhao.HttpRequest.DAO;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Conrrol extends AppCompatActivity    {

    private Switch dev1,dev2,dev3,dev4;
    private Button msgbn1,msgbn2,msgbn3,pbt1,pbt2;
    private EditText msg1,msg2,msg3,mtor1,mtor2;
    private  boolean flag1=false;
    public  Handler mHandler;
    private  String TAG="CONTROL";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_conrrol);

        init();

        SubThread subThread=new SubThread();
        subThread.start();

        mHandler=new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                    if(msg.what == 1){
                        Toast.makeText(Conrrol.this, "操作成功", Toast.LENGTH_SHORT).show();
                    }
                    else
                        Toast.makeText(Conrrol.this, "操作失败", Toast.LENGTH_SHORT).show();
            }

        };

        //控制设备1-3的常规开和关
        dev1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (dev1.isChecked()) {
                    Log.e(TAG, "ON DEV1");
                    PackageDate(subThread.subhandler,"dev1","20");
                }
                else {
                    Log.e(TAG, "OFF DEV1");
                    PackageDate(subThread.subhandler,"dev1","0");
                }
            }
        });

        dev2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (dev2.isChecked()) {
                    Log.e(TAG, "ON DEV2");
                    PackageDate(subThread.subhandler,"dev2","20");

                }
                else {
                    Log.e(TAG, "OFF DEV2");
                    PackageDate(subThread.subhandler,"dev2","0");
                }
            }
        });

        dev3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (dev3.isChecked()) {
                    Log.e(TAG, "ON DEV3");
                    PackageDate(subThread.subhandler,"dev3","5000");
                }
                else {
                    Log.e(TAG, "OFF DEV3");
                    PackageDate(subThread.subhandler,"dev3","0");
                }
            }
        });

        //设置是否自动控制
        dev4.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (dev4.isChecked()) {
                    Log.e(TAG, "自动控制开启");
                    PkLimitAndIsc(subThread.subhandler,"4","1");
                } else {
                    Log.e(TAG, "自动控制关闭");
                    PkLimitAndIsc(subThread.subhandler,"4","0");
                }
            }
        });

        //给字段msg1设置阈值
        msgbn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String val=msg1.getText().toString();
                PkLimitAndIsc(subThread.subhandler,"1",val);

            }
        });
        //给字段msg2设置阈值
        msgbn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String val=msg2.getText().toString();
                PkLimitAndIsc(subThread.subhandler,"2",val);
            }
        });
        //给字段msg3设置阈值
        msgbn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String val=msg3.getText().toString();
                PkLimitAndIsc(subThread.subhandler,"3",val);
            }
        });

        //电机1控制, 支持PWM和正反转
        pbt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String val=mtor1.getText().toString();
                PackageDate(subThread.subhandler,"dev1",val);
            }
        });
        //电机2控制, 支持PWM和正反转
        pbt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String val=mtor2.getText().toString();
                PackageDate(subThread.subhandler,"dev2",val);
            }
        });




    }

    /**
     * 基于不同id的按钮控件打包数据
     * 数据:控制执行部件的数据
     */
    public  void PackageDate(Handler handler,String name,String val){

    Map[] li=new Map[2];
    try {
        li[0]=new HashMap();
        li[1]=new HashMap();
        li[0].put("name",name);
        li[1].put("val",val);
        Message msg=Message.obtain();
        msg.what=1;
        msg.obj=li;
        handler.sendMessage(msg);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

    /**
     * 基于不同id的按钮控件打包数据
     * 数据:设置阈值的数据或者是是否自动控制的标记
     */
    public  void PkLimitAndIsc(Handler handler,String name,String val){

        Message msg=Message.obtain();
        Object[] obj=new Object[2];
        obj[0]=new Object();
        obj[1]=new Object();
        obj[0]=name;
        obj[1]=val;
        msg.what=2;
        msg.obj=obj;
        handler.sendMessage(msg);

    }

    /**
     * 初始化控件
     */
    public void init(){
        dev1=findViewById(R.id.dev1);
        dev2=findViewById(R.id.dev2);
        dev3=findViewById(R.id.dev3);
        dev4=findViewById(R.id.dev4);

        msg1=findViewById(R.id.msg1);
        msg2=findViewById(R.id.msg2);
        msg3=findViewById(R.id.msg3);

        msgbn1=findViewById(R.id.msg_bn1);
        msgbn2=findViewById(R.id.msg_bn2);
        msgbn3=findViewById(R.id.msg_bn3);

        pbt1=findViewById(R.id.pbn1);
        pbt2=findViewById(R.id.pbn2);

        mtor1=findViewById(R.id.mtor1); //两个电机的可编辑框的值的获取
        mtor2=findViewById(R.id.mtor2);


    }



    //子线程协调主线程发起网络请求
    class SubThread extends  Thread {
        public Handler subhandler;

        public void run() {
            Looper.prepare();
            subhandler = new Handler(Looper.myLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case 1:
                            //解包发起请求
                            Map[] li= (Map[]) msg.obj;

                            try {
                                DAO.ControlDec((String) li[0].get("name"),(String) li[1].get("val"));
                                Log.e(TAG, "success" );
                                mHandler.sendEmptyMessage(1);
                            } catch (Exception e) {
                                e.printStackTrace();
                                mHandler.sendEmptyMessage(0);
                            }
                            break;
                        case 2:
                            try {
                                Object[] objects= (Object[]) msg.obj;
                                DAO.SetLimitAndIsc(objects[0].toString(),objects[1].toString());
                                Log.e(TAG, "success" );
                                mHandler.sendEmptyMessage(1);
                            } catch (Exception e) {
                                e.printStackTrace();
                                mHandler.sendEmptyMessage(0);
                            }
                            break;

                        default:
                            break;

                    }
                }

            };
            Looper.loop();

        }
    }

}

 

这两点是最主要的,另外就是数据统计,比如画折线图对数据进行实时显示,还有对历史数据(传感器信息)进行查询等等。

 

 

 

参考

Android的handler消息收发处理——子线程与主线程(UI线程)间的通信_昊月光华的博客-优快云博客_android获取主线程handler

 

然后就是界面布局,我不追求美观,只要能用就行。

Java安卓移动物联网开发入门实战:从零构建第一个Android应用 封装是面向对象三大特性之一,指的是将数据(成员变量)和操作数据的方法绑定在一起,并对外隐藏内部实现细节,仅暴露必要的接口供外部调用。这种机制提高了安全性与模块化程度。在Java中,类使用class关键字定义:// 私有成员变量,外部无法直接访问// 公共getter/setter方法,提供受控访问return age;throw new IllegalArgumentException("年龄不能为负数");在中添加:release {release { 阅读详情

相关推荐

【探秘】二维异形件重叠移除算法:从度量到消除的实战解析

本文深入解析二维异形件重叠移除算法的核心技术与实战应用,涵盖重叠度量、零件扰动策略及消除方法。通过NFP(临界多边形)技术、空间分区加速等优化手段,有效解决异形件排版中的重叠问题,提升材料利用率和计算效率。适合制造业、CAD软件开发者及算法工程师参考。

weixin_28698059的博客 253

基于TCP/IP协议的物联网安卓应用开发基础教程(Android Studio开发)

基于TCP/IP协议的物联网安卓应用开发基础教程(Android Studio开发)

weixin_43351158的博客 1万+

hpm6750evk2开发板(一)菜鸟入门

hpm6750与我们平时常用的stm单片机在开发环境和开发方法上有很大的区别,所以上手还是需要花一点时间的,拿到板子先不要急着上电调试,我们先找资料学习一下了,免得多走冤枉路,以下是我整理的一些学习资源,包括开发板使用手册、芯片SDK、开发工具、视频资料等,建议先把使用手册和学习视频先看了,再取搭建环境测试。最近刚入手一块hpm6750evk2开发板,花了几天时间学习,算是菜鸟入门了,今天分享一下学习过程。看完资料后,把开发工具安装上,下一篇文章我们分享一下调试工程的过程和遇到的问题。

Silas1750的博客 3086

基于阿里云物联网平台的Android物联网软件框架(快速开发)

该工程是连接阿里云物联网平台的模板代码,将MQTT连接、JSON数据的订阅发布等操作封装,并且能够迅速将获取到的数据显示到手机界面上。使用了Servier进行网络连接的逻辑操作,并且使用自定义控件,绑定对用标识符的数据对象,实现了数据自动实时更新等操作,并且显示的自定义控件还可以修改显示的样式,可以加载gif图片等。

zhangyanping987的博客 8219

YOLO26 从零到工业落地全实战:自定义训练+多场景测试+边缘部署预备,踩坑实测100%可复现

很多人觉得训练是核心,其实不是——数据集的质量,直接决定了你模型的上限。我见过太多人,标注不规范、格式错误、数据集划分混乱,然后疯狂调参,训了几百轮还是不收敛,纯属白费功夫。我这次用的是工业零件缺陷检测自定义数据集,共3个类别:划痕、毛刺、变形,总计1200张图片,给大家讲一套标准的、可复现的数据集制作流程,不管你是做工业检测、安防、交通,都能直接套用。很多人拿到数据集,直接用默认命令训练,然后抱怨精度上不去。默认参数是给COCO数据集用的,你的自定义数据集,必须针对性调参,不然根本达不到最优效果。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 569

【保姆级教程】基于UNet++&MobileNetv3的语义分割模型从训练到RK3588部署:让边缘AI落地效率提升300%

通过SMP库一键构建encoder_name="mobilenet_v2", # 选择MobileNetv3作为骨干encoder_weights="imagenet", # 加载预训练权重加速收敛in_channels=3, # 输入图像通道数(RGB)classes=29, # Cityscapes数据集类别数activation=None # 输出无激活,便于后续损失计算本教程从“模型设计-训练-转换-边缘部署”全链路拆解了。

FJN110的博客 256

Android 之 上下文菜单、选项菜单、子菜单

[size=small][color=olive][b] 菜单 OptionMenu ContextMenu SubMenu; 1、选项菜单:OptionMenu 注意:一般的选项菜单:最多可以有两行,每行3个菜单项,当多余 6 个的时候或出现more,点击显示; 创建:重写 onCreateOptionsMenu() 方法; 事件:重写onOptio...

Sunzone 558

【深度学习新浪潮】Score Matching(分数匹配):原理、推导与PyTorch实战

在概率模型训练中,配分函数(归一化常数)是绕不开的难题——尤其是能量模型(EBM)、扩散模型等未归一化模型,直接计算配分函数几乎不可能。Score Matching(分数匹配)作为一种无归一化的参数估计方法,通过拟合概率密度的对数梯度(分数函数),彻底避开了配分函数的计算,成为生成建模、密度估计的核心技术之一。本文将从基础概念出发,逐步推导Score Matching的核心公式,并结合PyTorch实现一个可直接运行的实战案例,帮你彻底理解这一关键技术。Score Matching的核心是。

专注:太空算力、AI infra、异构调度、大模型成本工程 250

安卓物联网APP开发——基于编辑物联网平台环境实现远程控制数据传输

物联网app的开发

weixin_54536165的博客 5510

(五)深入理解Bluez协议栈之“GATT Server Profile”

上一篇介绍Bluez协议栈的了GAP Profile的实现,本章节我们继续介绍GATT Profile的实现,参考的程序是Peripheral。通过阅读它的实现代码可以发现,它广播部分是通过mgmt来实现的,然后在初始化完成之后,创建了一个L2CAP类型的socket,来负责实现GATT Server的逻辑。

1142

ARM Linux工控板+C# .NET Core:倍福ADS协议轻量化工业控制(附跨平台部署代码)

某自动化设备厂的倍福PLC控制系统曾依赖传统x86工控机:单台设备需配备1台Intel i5工控机(成本约8000元),功耗30W+,且Windows系统稳定性受工业环境干扰(如电磁辐射导致蓝屏)。更棘手的是,设备需部署在产线边缘(空间狭小),x86工控机的体积(4U机架)和散热需求(风扇噪音)难以适配;而多设备部署时,高硬件成本和高功耗导致年运维成本超20万元。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 954

ANDROID物联网开发

ANDROID物联网开发从入门到实战附源码 循序渐进地讲解了 Android物联网开发的基本知识。本书从获取源码和搭建应用开发环境开始讲起,依次讲解了基础知识篇、数据传输篇、信息识别篇、传感器应用篇和技术提高篇这 5大部分内容。 目录 第1篇 基础知识篇 第1章 Android系统介绍 2 1.1 纵览智能设备系统 2 1.1.1 Symbian(塞班) 2 1.1....

SilverFoxGame的博客 1554

智能硬件产品 App 全球发布 第 1 章:全球 App 发布战略设计

本章阐述智能硬件 App 全球发布战略,涵盖市场分析、竞争格局、用户画像及资源配置。通过制定可执行的全球化推广路径,整合地区法规合规、渠道分发策略与营销活动设计,助力团队快速进入主流商店并确立品牌影响力。同时构建可量化的 KPI 监控体系,指导项目进度追踪与效果复盘,确保产品迭代持续优化,降低运营总成本。

moton2017的博客 156

android物联网开发简书,Arduino物联网开发实例教程

## blinker解决方案blinker是一套跨硬件、跨平台的物联网解决方案,提供APP端、设备端、服务器端支持,使用公有云服务进行数据传输。可用于智能家居、数据监测等领域,可以帮助用户更好更快地搭建物联网项目。### blinker具备哪些优势**1. 支持多种连接方式**blinker提供当前最流行的连接方式支持,如蓝牙、WiFi、NBiot/GPRS,可以应对大多数物联网场景需求。**2....

weixin_39646628的博客 420

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Android物联网应用程序开发(智慧城市)—— 环境状态值范围设置界面开发

效果图: 代码: 布局: <?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" andro

杨明金的博客 22万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Android开发之局域网聊天软件

之前有掌握到了局域网内UDP通信技术,当时就有点蠢蠢欲动,想写个聊天的软件。后来软件工程课,老师让写一个小程序,就把这个完成了。 ChatActivity.java   聊天activity import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetAddress;

Mr_Sunshine3的博客 2735

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

stm32接入机智云平台实现app控制led灯

准备工具: stm32f407 单片机 esp8266 WiFi模块 PC 机智云app flash烧写工具 第一步烧写机智云Gagent固件 进入下载中心,选择硬件资源开发GAgent,选择我们要烧写的esp8266GAgent 把烧写下载好的GAgent固件 (1)选择和单片机匹配的flash大小 (2)GAgent_00ESP826_04020034_32Mbit.bi...

wangpan0330的博客 4983

自制APP连接OneNET---实现数据监控和下发控制(HTTP)

前言 本案例主要是实现使用自制的手机APP对OneNET云平台上的数据查看和下发命令控制单片机上的小灯亮灭,使用的HTTP协议接入OneNET,APP开发使用的是E4A中文安卓编程。 一、前期准备 1、STM32F103C8T6最小系统板 2、ESP8266-01S模块 3、安装E4A软件 APP展示: 视频演示: ..........

NICHUN12345的博客 1万+

Holer实现手机APP应用如何从公网访问内网WEB应用

手机APP应用公网访问内网WEB应用 本地安装了WEB服务端,手机APP应用只能在局域网内访问本地WEB,怎样使手机APP应用从公网也能访问本地WEB? 本文将介绍使用holer实现的具体步骤。 1. 准备工作 1.1 安装并启动WEB服务端程序 默认安装的WEB服务端的端口是80。 2. 实现步骤 2.1 下载并解压holer软件包 Holer软件包:holer-xxx.tar.gz Holer...

weixin_34248118的博客 526

手机APP如何访问局域网服务器

一、网络环境 手机和服务器(或个人电脑)连接同一个无线WIFI,或者电脑连接手机的热点。 二、服务部署 .Net项目:部署在IIS,端口最好是80,其它端口需要对外开发; Tomcat、Apache...等项目同理。 三、手机访问 1、通过cmd命令或者在网络共享中心中查看电脑的IP地址(如:本机电脑IP地址192.168.43.251); 2、通过手机浏览器访问部署好的项目网页(格...

bearlogic的专栏 1万+

【阿里云IoT+YF3300】14.阿里IoT Studio打造手机端APP

在上一篇《13.阿里云IoT Studio WEB监控界面构建》中,我们介绍了用阿里云IoT Studio(原Link Develop)可视化构建WEB界面程序。本篇文章将介绍用阿里云IoTStudio打造手机端APP。 和WEB开发类似,可以通过可视化拖拽的方式,方便地将各种图表组件与设备相关的数据源关联,无需编程,即可将物联网平台上接入的设备数据可视化展现。...

刘洪峰AIoT | 一叶启帆·万物智联 6279

android 局域网 推送,通过RabbitMQ实现消息推送功能 可同时实现局域网推送和广域网推送...

服务端pom文件org.springframework.bootspring-boot-starter-amqporg.springframework.bootspring-boot-starter-web配置文件server:port: 8022spring:#给项目来个名字application:name: rabbitmq-consumer#配置rabbitMq 服务器rabbitmq:ho...

weixin_39774490的博客 1201

在家远程办公,手机怎么连内网测试?

电脑安装远程工具,保证电脑连上了公司内网,例如我安装的是公司的SSL VPN Client,显示已连接 安卓或ios的测试手机与电脑连同一个wifi 电脑打开抓包工具,例如我安装的是charles 测试手机配置代理,连接charles 具体操作(ios手机为例):点击手机–设置–无线局域网–点击wifi名–点击http代理–手动–输入charles的ip和端口 注意: 这...

weixin_42231208的博客 6760

手机(局域网)远程连接 windows电脑

android 手机下载,Microsoft Remote Desktop   app;   ios 手机下载, app;       接下来就按 android, 打开左边菜单点击’user accounts' 添加要连接的计算机  ip地址  与 密码,         然后点击home返回首页   首页点击 右上角 + 号 ,点击desktop...

wsyzxss的博客 8741

安卓推送这件小事

今天来讲讲推送这件小事,事虽小,要做好却不容易。 推送难,难于上青天。 我们在讨论 Android 手机上的推送时,大多数情况是在说集成第三方推送,因为即使是像微信这样的大厂,也需要厂商加到启动白名单里才能保持在线。 iOS 手机使用 APNs(Apple Push Notification service)进行推送,而 Android 手机,也是有 GCM(Google Cloud Mess...

weixin_33769207的博客 318

《物联网Android程序开发案例式教程》Demo1:线性布局

《物联网Android程序开发案例式教程》案例一:线性布局

dede_de_的博客 2362
上一篇: L298N双路驱动直流电机方案(支持PWM+正反转)
下一篇: STM32正点原子TFT-LCD1.3寸(240x240)液晶显示屏移植
昊月光华
博客等级 码龄6年 340粉丝 158原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值