当前位置: 首页 > news >正文

安卓 tcp 客户端

安卓 tcp 客户端

Server:8888 是Qt 写的Tcp 服务器 ip 是 192.168.2.103 port是8888
安卓手机运行 kotlin 语法的Tcp Client ,连接,收发数据
效果如下图

在这里插入图片描述

Tcpclient

package com.example.myapplicationimport android.os.Handler
import android.os.Looper
import android.util.Log
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.Socketclass TcpClient(private val ipAddress: String, private val port: Int) {private lateinit var socket: Socketprivate lateinit var reader: BufferedReaderprivate lateinit var writer: BufferedWriter// 接收线程private val messageReceiverThread = Thread {//主消息处理器,用于向外部发送tcp收到的数据val handler = Handler(Looper.getMainLooper())val buffer = StringBuilder()val charBuffer = CharArray(1024) // 调整缓冲区大小while (!Thread.currentThread().isInterrupted) {try {
//                val receivedData = reader.readLine() ?: ""
//                Log.d("TcpClient",receivedData)
//                handler.post {
//                    onDataReceived(receivedData)
//                }val bytesRead = reader.read(charBuffer)if (bytesRead == -1) {// 如果没有更多数据可读,则退出循环Log.d("TcpClient","continue")continue}// 清空缓冲区buffer.clear()// 将读取的数据追加到缓冲区buffer.append(charBuffer, 0, bytesRead)// 通知UI线程更新UIhandler.post {Log.d("TcpClient","buffer : "+buffer.toString())onDataReceived(buffer.toString())}} catch (e: Exception) {Log.e("TcpClient","Exception")e.printStackTrace()break}}}// 外部调用,定义数据接收监听器接口interface DataReceivedListener {fun onDataReceived(data: String)}private var dataReceivedListener: DataReceivedListener? = null// 外部调用,设置数据接收监听器fun setDataReceivedListener(listener: DataReceivedListener) {dataReceivedListener = listener}// 通知数据接收事件private fun onDataReceived(data: String) {dataReceivedListener?.onDataReceived(data)}// 1fun connectToServer() {try {socket = Socket(ipAddress, port)reader = BufferedReader(InputStreamReader(socket.getInputStream()))writer = BufferedWriter(OutputStreamWriter(socket.getOutputStream()))} catch (e: Exception) {e.printStackTrace()}}fun sendMessage(message: String) {try {writer.write(message)
//            writer.newLine()writer.flush()} catch (e: Exception) {e.printStackTrace()}}// 2fun startMessageReceiver() {messageReceiverThread.start()}fun stopMessageReceiver() {messageReceiverThread.interrupt()}fun close() {try {socket.close()} catch (e: Exception) {e.printStackTrace()}}
}

MainActivity

package com.example.myapplicationimport android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.Editable
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.TextViewclass MainActivity : AppCompatActivity() {private lateinit var ipAddress: Stringprivate var port: Int = 0private lateinit var recvText: EditTextprivate lateinit var tcpClient: TcpClientoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)recvText = findViewById(R.id.recvText)// start tcpval startButton: Button = findViewById(R.id.startBtn)// 设置按钮点击事件startButton.setOnClickListener {// 设置IP地址和端口(请根据需要修改)ipAddress = findViewById<EditText?>(R.id.ipText).text.toString()port = findViewById<EditText?>(R.id.portNum).text.toString().toInt()// 创建TcpClient实例tcpClient = TcpClient(ipAddress, port)// 设置数据接收监听器tcpClient.setDataReceivedListener(object : TcpClient.DataReceivedListener {override fun onDataReceived(data: String) {// 在数据接收回调中更新UIupdateUI(data)}})// 在新线程中执行连接操作Thread {tcpClient.connectToServer()tcpClient.startMessageReceiver()}.start()}// stop tcpval stopBtn: Button = findViewById(R.id.stopBtn)stopBtn.setOnClickListener {Thread {tcpClient.stopMessageReceiver()tcpClient.close()}.start()}// send on threadval sendBtn: Button = findViewById(R.id.sendBtn)sendBtn.setOnClickListener {Thread {var sendText : EditText= findViewById(R.id.sendText)tcpClient.sendMessage(sendText.text.toString())}.start()}var cleanBtn:Button = findViewById(R.id.cleanBtn)cleanBtn.setOnClickListener {recvText.text.clear()}}private fun updateUI(data: String) {Log.d("MainActivity","data:"+data)val editableText = Editable.Factory.getInstance().newEditable(data)recvText.text?.append(editableText)}}

activity_main.xml

<?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:id="@+id/linearLayout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="406dp"android:layout_height="53dp"android:orientation="horizontal"><EditTextandroid:id="@+id/ipText"android:layout_width="204dp"android:layout_height="47dp"android:layout_weight="4"android:ems="10"android:inputType="text"android:text="192.168.2.103" /><EditTextandroid:id="@+id/portNum"android:layout_width="204dp"android:layout_height="45dp"android:layout_weight="1"android:ems="10"android:inputType="number"android:text="8888" /></LinearLayout><LinearLayoutandroid:layout_width="409dp"android:layout_height="55dp"android:orientation="horizontal"><Buttonandroid:id="@+id/startBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="start" /><Buttonandroid:id="@+id/stopBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="stop" /><Spaceandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1" /></LinearLayout><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="send data"android:textSize="20sp" /><EditTextandroid:id="@+id/sendText"android:layout_width="match_parent"android:layout_height="148dp"android:layout_weight="4"android:ems="10"android:gravity="start|top"android:inputType="textMultiLine" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/sendBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="send" /><Buttonandroid:id="@+id/cleanBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="clean recv" /></LinearLayout><TextViewandroid:id="@+id/textView3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="recv data"android:textSize="20sp" /><EditTextandroid:id="@+id/recvText"android:layout_width="match_parent"android:layout_height="202dp"android:layout_weight="4"android:ems="10"android:gravity="start|top"android:inputType="textMultiLine" /></LinearLayout>

AndroidManifest.xml 配置清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.myapplication"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.MyApplication"><activityandroid:name=".MainActivity"android:exported="false"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

build.gradle (app)

plugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'
}android {compileSdkVersion 30buildToolsVersion "30.0.3"defaultConfig {applicationId "com.example.myapplication"minSdkVersion 28targetSdkVersion 30versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation 'androidx.appcompat:appcompat:1.2.0'implementation 'com.google.android.material:material:1.2.1'implementation 'androidx.constraintlayout:constraintlayout:2.0.1'testImplementation 'junit:junit:4.+'androidTestImplementation 'androidx.test.ext:junit:1.1.2'androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

build.gradle (my proj )

使用国内镜像

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {repositories {maven { url 'https://maven.aliyun.com/repository/google' }maven { url 'https://maven.aliyun.com/repository/jcenter' }maven { url 'https://maven.aliyun.com/repository/public' }maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
//        google()
//        mavenCentral()}dependencies {classpath "com.android.tools.build:gradle:4.2.1"classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0'// NOTE: Do not place your application dependencies here; they belong// in the individual module build.gradle files}
}allprojects {repositories {maven { url 'https://maven.aliyun.com/repository/google' }maven { url 'https://maven.aliyun.com/repository/jcenter' }maven { url 'https://maven.aliyun.com/repository/public' }maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
//        google()
//        mavenCentral()
//        jcenter() // Warning: this repository is going to shut down soon}
}task clean(type: Delete) {delete rootProject.buildDir
}

相关文章:

安卓 tcp 客户端

安卓 tcp 客户端 Server:8888 是Qt 写的Tcp 服务器 ip 是 192.168.2.103 port是8888 安卓手机运行 kotlin 语法的Tcp Client &#xff0c;连接&#xff0c;收发数据 效果如下图 Tcpclient package com.example.myapplicationimport android.os.Handler import android.os.Loo…...

flutter plugins插件【三】【Flutter Intl】

3、 Flutter Intl 多语言国际化 在Android Studio中菜单Tools找到flutter intl创建多语言配置。 创建后会在pubspec.yaml出现 flutter_intl:enabled: true 在工程的lib会生成l10n与generated文件夹 l10n包含 intl_en.arb intl_zn.arb 我们在intl_en.arb添加 { home: &quo…...

简单了解ICMP协议

目录 一、什么是ICMP协议&#xff1f; 二、ICMP如何工作&#xff1f; 三、ICMP报文格式 四、ICMP的作用 五、ICMP的典型应用 5.1 Ping程序 5.2 Tracert(Traceroute)路径追踪程序 一、什么是ICMP协议&#xff1f; ICMP因特网控制报文协议是一个差错报告机制&#xff0c;…...

MVCC究竟是什么?

&#xff11;.MVCC概念 MVCC&#xff0c;全称多版本并发控制 MVCC究竟是什么&#xff1f; 通俗的来说MVCC就是为了在读取数据时不加锁来提高读取效率的一种办法&#xff0c;MVCC解决的是读写时线程安全问题&#xff0c;线程不用去抢占读写锁。MVCC中的读就是快照读&#xff0c…...

Kafka知识点总结

常见名词 生产者和消费者 同一个消费组下的消费者订阅同一个topic时&#xff0c;只能有一个消费者收到消息 要想让订阅同一个topic的消费者都能收到信息&#xff0c;需将它们放到不同的组中 分区机制 启动方法 生成者和消费者监听客户端...

K8s最基本概念

1.K8s概述和特性 k8s是谷歌在2014年开业的容器化集群管理系统 使用K8s进行容器化应用部署 使用K8s利用应用扩展 k8s目标实施让部署容器化应用更加简洁高效-------集群管理系统 1.1 K8s特性 1) 自动装箱&#xff1a;基于容器对应用运行环境的资源配置 2&#xff09;自…...

vulnhub渗透测试靶场练习2

靶场介绍 靶场名&#xff1a;easy_cloudantivirus 靶场地址&#xff1a;https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453 环境搭建 依旧使用VM VirtualBox搭建靶场&#xff0c;攻击机使用的是VMware中的kali&#xff0c;需要将VMware虚拟机kali和virtualbox靶机…...

在R中安装TensorFlow、TensorFlow_Probability、numpy(R与Python系列第二篇)

目录 前言&#xff1a; 1-安装tensorflow库 Step1: 下载R包tensorflow Step2&#xff1a;安装TensorFlow库 Step3&#xff1a;导入R中 2-安装tensorflow_probability库 Step1&#xff1a;下载R包&#xff1a;tfprobability Step2&#xff1a;安装TensorFlow Probability …...

十大管理——项目成本管理

目录 1.成本管理概念 2.成本管理的四个过程域 2.1四个过程的整体理解 ​2.2四个过程的ITO口诀版记忆 2.3过程1——制定项目管理计划 ​2.4过程2——项目成本估算​ 2.5过程3——项目成本预算 2.5过程4——项目成本控制 3计算题 1.成本管理概念 项目成本管理就是要确保…...

Java BIO、NIO、AIO学习总结

前言&#xff1a;关于BIO/NIO/AIO的文章已经汗牛充栋&#xff0c;俺最近比较闲试图系统学习一下&#xff0c;希望大侠多多指教&#xff01; 先来个例子理解一下概念&#xff0c;以银行取款为例&#xff1a; 同步 &#xff1a; 自己亲自出马持银行卡到银行取钱&#xff08;使用…...

sql各种注入案例

目录 1.报错注入七大常用函数 1)ST_LatFromGeoHash (mysql>5.7.x) 2)ST_LongFromGeoHash &#xff08;mysql>5.7.x&#xff09; 3)GTID (MySQL > 5.6.X - 显错<200) 3.1 GTID 3.2 函数详解 3.3 注入过程( payload ) 4)ST_Pointfromgeohash (mysql>5.…...

系统学习Linux-ELK日志收集系统

ELK日志收集系统集群实验 实验环境 角色主机名IP接口httpd192.168.31.50ens33node1192.168.31.51ens33noed2192.168.31.53ens33 环境配置 设置各个主机的ip地址为拓扑中的静态ip&#xff0c;并修改主机名 #httpd [rootlocalhost ~]# hostnamectl set-hostname httpd [root…...

IDEA2023隐藏.idea和.iml文件

IDEA2023隐藏.idea和.iml文件 1. 打开file -> setting,快捷键CtrlAlts2. Editor -> File types3. 点击右侧Ignore files and folders一栏4. 添加需要忽略的文件5. 最重要一步 IDEA新建项目会自动生成一个.idea文件夹和.iml文件&#xff0c;开发中不需要对这两个文件修改&…...

【深入浅出C#】章节 9: C#高级主题:反射和动态编程

反射和动态编程是C#和其他现代编程语言中重要的高级主题&#xff0c;它们具有以下重要性&#xff1a; 灵活性和扩展性&#xff1a;反射允许程序在运行时动态地获取和操作类型信息、成员和对象实例&#xff0c;这使得程序更加灵活和具有扩展性。动态编程则使得程序能够根据运行…...

Gorm简单了解

GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly. 04_GORM查询操作_哔哩哔哩_bilibili 前置&#xff1a; db调用操作语句中间加debug&#xff08;&#xff09;可以显示对应的sql语句 1.Gorm模型定义&#xff08;理解重点&#xff…...

第一百三十三回 StreamProvier

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了通道相关的内容&#xff0c;本章回中将介绍 StreamProvider组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 在Flutter中Stream是经常使用的组件&#xff0c;对该组件的监听可以StremBuilder&#x…...

java 多个list取交集

java 多个list集合根据某个字段取出交集 模拟多个list集合&#xff0c;如下图 如果只有一个集合那么交集就是当前集合&#xff0c;如果有多个集合&#xff0c;那么第一个集合当做目标集合&#xff0c;在通过目标集合去和剩下的集合比较&#xff0c;取出相同的值&#xff0c;运…...

文件上传与下载

文章目录 1. 前端要求2. 后端要求 1. 前端要求 //采用post方法提交文件 method"post" //采用enctype属性 enctype"" //type属性要求 type"file"2. 后端要求 package com.itheima.reggie.controller;import com.itheima.reggie.common.R; impo…...

SpringBoot 整合 RabbitMQ

1. 创建 SpringBoot 工程 把版本改为 2.7.14 引入这两个依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springfr…...

气象科普丨气象站的分类与应用

气象站是一种用于收集、分析和处理气象数据的设备。根据不同的应用场景和监测需求&#xff0c;气象站可以分为以下几类&#xff1a; 一、农业气象站 农业气象站是专门为农业生产服务的气象站&#xff0c;主要监测土壤温度、土壤湿度等参数&#xff0c;为农业生产提供科学依据…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...