精华内容
下载资源
问答
  • Android局域网群聊app

    2020-05-27 14:08:56
    使用工具Android Studio3.1.2,实现了局域网通信。任何一台设备都可在服务器与客户机之间切换,可多人群聊。只需多个队员连接到同一队长。
  • ESP8266接线方式,51C程序,AndroidAPP,ESP8266调试方式,路由器端口映射; 接线方式 VCC最好使用3.3V;5V 容易发热导致烧坏模块 ESP8266 单片机 VCC VCC CH_PD VCC GND GND URXD TXD UTXD RXD ...

    第一次写博客,记录一下方便自己查看
    文章内容:
    ESP8266接线方式,51C程序,AndroidAPP,ESP8266调试方式,路由器端口映射;

    接线方式

    VCC最好使用3.3V;5V 容易发热导致烧坏模块

    ESP8266 单片机
    VCC VCC
    CH_PD VCC
    GND GND
    URXD TXD
    UTXD RXD

    ESP8266调试方式

    使用串行数据线连接电脑,使用安可信官方提供的调试工具调试
    这里使用https://blog.csdn.net/ls1792304830/article/details/72380281?depth_1-
    这位博主的图片;我也是参考他的博客;特别感谢

    在这里插入图片描述

    打开调试工具
    图片上传顺序可能不一样 已经标注了步骤了 一共4步
    第一步
    在这里插入图片描述
    第四步 这里改完后要重新改连接的时候的波特率 重新打开串口才能连接
    在这里插入图片描述
    第二步
    在这里插入图片描述
    第三步
    在这里插入图片描述

    配置完模块就可以烧录程序到51中了

    51C程序

    直接复制;根据自己硬件参数修改波特率

    #include <reg52.h>
    #include "intrins.h"
    sbit LED1=P2^0;
    sbit LED2=P2^1;
    typedef unsigned int u16;
    typedef unsigned char u8;
    u8 receive[2];
    u8 sign=0;
    void delay1s(void)   //误差 0us
    {
        u8 a,b,c;
        for(c=46;c>0;c--)
           for(b=152;b>0;b--)
               for(a=70;a>0;a--);
        _nop_();  //if Keil,require use intrins.h
    }
    
    
    void delay600us(void)   //误差 -1.041666666667us
    {
        unsigned char a,b;
        for(b=61;b>0;b--)
            for(a=3;a>0;a--);
    }
    
    
    
    
    //初始化串口
    void Init()
    {
           SCON = 0x50;      //串口模式1,允许接收
           TMOD = 0x20;    //T1工作模式2,自动重装
           PCON = 0x80;      //波特率倍增
           REN = 1;
                                             //根据实际选择
    //  TH1 = 0xfa;          //波特率9600(11.0592)
        //   TH1 = 0xf3;          //波特率4800(12.0000)
      	   TH1 = 0xf4;          //波特率4800(11.0592)
           TL1 = TH1;
           RI=0;
           EA = 1;
           ES = 0;
           TR1 = 1;
    }
    //发送字符
    void send(u8 value)
    {
           ES=0; //关闭串口中断
           TI=0; //清发送完毕中断请求标志位
           SBUF=value; //发送
           while(!TI); //等待发送完毕
           TI=0; //清发送完毕中断请求标志位
           ES=1; //允许串口中断
    }
    //单片机向模块发送AT指令
    void wifi_init()
    {
           u8 j=0;
       u8 a[]="AT+CIPMUX=1\r\n";     //那两条掉电要重新配置的指令	  多路模式
       u8 b[]="AT+CIPSERVER=1,8266\r\n";
       while(a[j]!='\0')
       {
               send(a[j]);
               j++;
       }
           j=0;                        //清零准备发第二条指令
           delay1s();                    //延时一下
           while(b[j]!='\0')
       {
               send(b[j]);
               j++;
       }
           delay1s();
    }
    void wifi_data()
    {
           if(receive[0]=='A')
    	   {     LED1=0;    //亮
    	   		 LED2=1;
    			 delay1s();
    			 receive[0]="";
    			 LED1=1;
    			 LED2=0;
    			 delay1s();
    	   }
    	   //if(receive[0]=='A')     LED1=1;    //亮
    	   
           //if(receive[0]=='B')    LED1=1;    //灭
    }   
    void main()
    {
    	   delay1s();
           Init();
           wifi_init();
           while(1)
           {
                    wifi_data();
           }
    }
    //中断程序,此程序只把+IPD,x,x:后的有用数据存进receive数组里
    void ZD() interrupt 4
    {
           if(RI)
           {
                    RI=0;
                    if(sign==1)
                    {
                            receive[0]=SBUF;
                            sign=0;                    //保存receive[0]的数据
                    }
                    if(SBUF==':')       sign=1;
           }
    }
    

    硬件接线

    同上图 模块RXD接单片机TXD
    模块TXD接单片机RXD
    上电 等模块初始化化完成

    路由器端口映射

    在路由器中查找当前模块的IP 记录下来
    在路由器设置中找到端口映射 每个路由器地方不一样 找找就好了 有些叫端口转发,大概就是这个意思
    名字不一定一样
    在端口映射中添加映射
    一般来说
    映射名字 随便设置 如 ESP
    内网IP 就是刚刚记录的IP
    端口范围就随便了 我这边默认设置就可以了
    保存就好了

    APP

    APP比较LOW,就不上传了,有需要的可以联系我;

    正式测试

    上电模块初识话完成
    在手机上使用TCP网络助手以客户端的方式加入 刚刚查询的IP 端口为程序里设置的
    发送数据;根据你的需求改数据动作 ;我这里设置的是 发送A 就会改变IO口上电状况
    到此全部完成

    写的不好,请多多指教,写的错误的地方多谢指导。
    有什么问题可以添加我的WX 2086549721 备注来意

    展开全文
  • 局域网通信工具,源码,含客户端和服务器端,pc用,也可以连接手机端。 源码未包含app
  • 一天天太能心血来潮,昨天在看UDP的时候突然手痒想写一个基于UDP的聊天app,想着挺简单结果搞了很久才搞出来。话不多说,上代码。 这个项目使用Jetpack框架搭建,Kotlin编写。 1. UDP通信工具类 import android.text...

    一天天太能心血来潮,昨天在看UDP的时候突然手痒想写一个基于UDP的聊天app,想着挺简单结果搞了很久才搞出来。话不多说,上代码。

    这个项目使用Jetpack框架搭建,Kotlin编写。

    1. UDP通信工具类

    import android.text.format.Formatter
    import android.util.Log
    import com.psychedelic.udpchat.ChatEntity
    import com.psychedelic.udpchat.FROM_OTHERS
    import com.psychedelic.udpchat.FROM_SELF
    import com.psychedelic.udpchat.TAG
    import com.psychedelic.udpchat.listener.UdpMessageListener
    import com.psychedelic.udpchat.listener.UdpMessageSendListener
    import java.io.IOException
    import java.net.DatagramPacket
    import java.net.DatagramSocket
    import java.net.InetAddress
    import java.net.SocketException
    
    class UdpManager(ipAddress: Int,listener:UdpMessageListener) {
        private var mLocalIp:String ?=null
        private val mIntIpAddress = ipAddress
        private val mPort = 8211
        private val mListener = listener
        fun sendUdpMsg(data: String,sendListener: UdpMessageSendListener) {
            if (data.isEmpty() || data.isBlank()){
                return
            }
            /*这一步就是将本机的IP地址转换成xxx.xxx.xxx.255*/
            val broadCastIP = mIntIpAddress or -0x1000000
            mLocalIp = "/${Formatter.formatIpAddress(mIntIpAddress)}"
            Log.d(TAG, "sendUdpMsg ip = $broadCastIP")
    
            var sendSocket: DatagramSocket? = null
            try {
                val server: InetAddress = InetAddress.getByName(Formatter.formatIpAddress(broadCastIP))
                Log.d(TAG, "sendUdpMsg server = $server")
    
                sendSocket = DatagramSocket()
                val msg = String(data.toByteArray(),Charsets.UTF_8)
                Log.d(TAG,"msg = $msg")
                val theOutput = DatagramPacket((msg).toByteArray(), msg.toByteArray().size, server, mPort)
                Log.d(TAG, "mLocalIp = $mLocalIp")
    
                sendSocket.send(theOutput)
                sendListener.sendSuccess()
                Log.d(TAG, "sendUdpMsg send !!!")
            } catch (e: IOException) {
                e.printStackTrace()
            } finally {
                sendSocket?.close()
            }
        }
    
        fun receiverUdpMsg() {
            Log.d(TAG, "receiverUdpMsg")
            val buffer = ByteArray(1024)
            /*在这里同样使用约定好的端口*/
            var server: DatagramSocket? = null
            try {
                server = DatagramSocket(mPort)
                val packet = DatagramPacket(buffer, buffer.size)
    
                while (true) {
                    try {
                        server.receive(packet)
                        val content = String(packet.data, 0, packet.length, Charsets.UTF_8)
                        Log.d(TAG,"content = $content ")
                        Log.d(TAG, "get ip = ${packet.address} mLocalIP = $mLocalIp")
                        val msg = ChatEntity().apply { text = content }
                        if (packet.address.toString() == mLocalIp){
                            msg.fromWho = FROM_SELF
                        }else{
                            msg.fromWho = FROM_OTHERS
                        }
                        mListener.onMessageReceive(msg)
                        Log.d(TAG,"address : " + packet.address + ", port : " + packet.port + ", content : " + content)
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                }
            } catch (e: SocketException) {
                Log.d(TAG, "err")
                e.printStackTrace()
            } finally {
                server?.close()
            }
        }
    
    }
    

    通过WifiManager获取本地IP,然后给路由器发送UDP包,路由器会全频段广播,那么只要其他设备监听了这个端口就能收到消息,端口我写死了,以后会改成可设置的,这样也能监听其他设备的UDP广播。
    除了利用路由器发送广播的方式,也可以遍历0到255所有的IP地址查找局域网中的设备,获取到对方的IP地址后可以定向发,也可以去建立稳定的TCP连接,这里不展开了。广播的UDP消息自己也能收到,为了区分对比IP地址,收到的包IP地址如果和本机相同就是自己发的。

    2. XML页面

    写一个简单的聊天页面:
    在这里插入图片描述

    <?xml version="1.0" encoding="utf-8"?>
    <layout>
        <data>
    
        </data>
        <androidx.constraintlayout.widget.ConstraintLayout
            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:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            tools:context=".MainActivity">
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/chat_tool_bar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toTopOf="@+id/chat_recycle_view"
                android:elevation="15dp"
                android:background="#F2F2F2"
                app:titleTextColor="#bfbfbf"
                app:navigationIcon="@mipmap/back"
                >
            </androidx.appcompat.widget.Toolbar>
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/chat_recycle_view"
                app:layout_constraintTop_toBottomOf="@+id/chat_tool_bar"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintBottom_toTopOf="@+id/chat_bottom_bar"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:elevation="5dp"
                />
            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/chat_bottom_bar"
                android:layout_width="match_parent"
                android:layout_height="56dp"
                app:layout_constraintTop_toBottomOf="@+id/chat_recycle_view"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                android:elevation="15dp"
                android:background="#F2F2F2"
                >
                <Button
                    android:id="@+id/chat_button_send"
                    android:layout_width="60dp"
                    android:layout_height="40dp"
                    android:layout_marginEnd="10dp"
                    android:onClick="sendMessageButtonClick"
                    android:background="@drawable/chat_send_btn_selector"
                    android:text="@string/button_send"
                    android:textColor="#ffffff"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintLeft_toRightOf="@+id/chat_edit_text"
                    app:layout_constraintRight_toRightOf="parent"
                    />
    
                <EditText
                    android:id="@+id/chat_edit_text"
                    android:layout_width="0dp"
                    android:layout_height="40dp"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent"
                    android:layout_marginStart="20dp"
                    android:layout_marginEnd="10dp"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toLeftOf="@+id/chat_button_send"
                    android:background="#ffffff"
                    />
    
            </androidx.constraintlayout.widget.ConstraintLayout>
    
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    
    </layout>
    
    

    RecyclerView的Item布局,一个是收到消息的布局,一个是自己发送的消息布局

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="item"
                type="com.psychedelic.udpchat.ChatEntity" />
        </data>
        <androidx.constraintlayout.widget.ConstraintLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:id="@+id/chat_activity_ll_receive_chat_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:maxWidth="300dp"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                android:minHeight="43dp"
                android:layout_margin="20dp"
                android:gravity="center_vertical"
                android:background="@mipmap/chatfrom_bg_normal"
                android:text="@{item.text}"
                android:textSize="20sp"
                />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="item"
                type="com.psychedelic.udpchat.ChatEntity" />
        </data>
        <androidx.constraintlayout.widget.ConstraintLayout
            xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:id="@+id/chat_activity_ll_receive_chat_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:maxWidth="300dp"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                android:minHeight="43dp"
                android:layout_margin="20dp"
                android:gravity="center_vertical"
                android:background="@mipmap/chatto_bg_normal"
                android:text="@{item.text}"
                android:textSize="20sp"
                />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    3. Activity

    package com.psychedelic.udpchat
    
    import android.content.Context
    import android.content.pm.PackageManager
    import android.net.wifi.WifiInfo
    import android.net.wifi.WifiManager
    import android.os.Bundle
    import android.util.Log
    import android.view.View
    import androidx.appcompat.app.AppCompatActivity
    import androidx.databinding.DataBindingUtil
    import androidx.lifecycle.ViewModelProvider
    import androidx.recyclerview.widget.LinearLayoutManager
    import com.psychedelic.udpchat.databinding.ActivityMainBinding
    import com.psychedelic.udpchat.listener.MainActivityObserver
    import com.psychedelic.udpchat.listener.UdpMessageListener
    import com.psychedelic.udpchat.listener.UdpMessageSendListener
    import com.psychedelic.udpchat.mvvm.MainViewModel
    import com.psychedelic.udpchat.util.StatusBarUtil
    
    
    const val TAG = "MainActivity"
    class MainActivity : AppCompatActivity(),UdpMessageListener {
        private val mContext = this
    
        private var mList = ArrayList<ChatEntity>()
        private lateinit var mAdapter: ChatRvAdapter
        private lateinit var mBinding: ActivityMainBinding
        private lateinit var mWifiManager: WifiManager
        private lateinit var mWifiInfo: WifiInfo
        private lateinit var mViewModel: MainViewModel
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
            StatusBarUtil.setStatusTextColor(true, this)
            window.statusBarColor = resources.getColor(R.color.bar_color)
            supportActionBar?.setDisplayHomeAsUpEnabled(true)
            mViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
            mWifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
            mWifiInfo = mWifiManager.connectionInfo
            Log.d(TAG, "SSID = ${mWifiInfo.ssid}")
            mBinding.chatToolBar.title = mWifiInfo.ssid
            setSupportActionBar(mBinding.chatToolBar)
            mAdapter = ChatRvAdapter(this, mList, BR.item)
            mBinding.chatRecycleView.layoutManager = LinearLayoutManager(this)
            mBinding.chatRecycleView.adapter = mAdapter
            mBinding.chatToolBar.setNavigationOnClickListener {
                finish()
            }
            lifecycle.addObserver(MainActivityObserver(mContext,mWifiManager,mViewModel,this))
        }
    
    
        override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<out String>,
            grantResults: IntArray
        ) {
            if (requestCode == REQUEST_PERMISSIONS) {
                for ((index, permission) in permissions.withIndex()) {
                    if (grantResults[index] != PackageManager.PERMISSION_GRANTED) {
                        Log.d(
                            TAG,
                            "permission = $permission grantResults[index] = ${grantResults[index]}"
                        )
                    }
                }
            }
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    
    
        private fun refreshNewMessage(msg: ChatEntity) {
            Log.d(TAG, "refreshNewMessage msg = ${msg.text}")
            runOnUiThread {
                mList.add(msg)
                mAdapter.refreshData(mList)
                scrollToEnd()
            }
        }
    
        fun sendMessageButtonClick(view: View) {
            if (mBinding.chatEditText.text.isNotEmpty()) {
                mViewModel.sendUdpMsg(mBinding.chatEditText.text.toString(),
                    object : UdpMessageSendListener {
                        override fun sendSuccess() {
                            runOnUiThread {
                                mBinding.chatEditText.text.clear()
                            }
                        }
                    })
            }
        }
    
        private fun scrollToEnd() {
        	//刷新消息的时候需要将RecycleView滚动到最后一行以显示最新消息
            if (mBinding.chatRecycleView.adapter!!.itemCount > 0) {
                mBinding.chatRecycleView.smoothScrollToPosition(mBinding.chatRecycleView.adapter!!.itemCount)
            }
        }
    
        override fun onMessageReceive(msg: ChatEntity) {
            refreshNewMessage(msg)
        }
    }
    
    

    使用了lifeCycle,这里碰到了点坑,我以前不用ActionBar或者ToolBar,都是自己写的布局。这次用了ToolBar,发现其使用的时候逻辑顺序有严格要求,比如title设置必须在setSupportActionBar之前,setNavigationOnClickListener则必须要在setSupportActionBar之后,否则设置无效。

    还有我把当前Wifi的SSID也就是名称作为Title,一开始发现无论怎么获取得到的SSID都是空的,后来上网查发现Android 8.0之后需要添加上网络定位权限才能通过WifiManager获取到SSID,加上权限之后就好了。

        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    

    注意需要获取动态运行时权限,我放在LifeCycleObserver中了

    4. MainActivityObserver

    import android.Manifest
    import android.app.Activity
    import android.content.Context
    import android.content.pm.PackageManager
    import android.net.wifi.WifiManager
    import android.widget.Toast
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat
    import androidx.lifecycle.Lifecycle
    import androidx.lifecycle.LifecycleObserver
    import androidx.lifecycle.OnLifecycleEvent
    import com.psychedelic.udpchat.REQUEST_PERMISSIONS
    import com.psychedelic.udpchat.mvvm.MainViewModel
    
    
    class MainActivityObserver(context: Context,wifiManager: WifiManager,viewModel:MainViewModel,listener: UdpMessageListener):LifecycleObserver {
        private val mContext = context
        private val mListener = listener
        private val mViewModel = viewModel
        private var mWifiManager: WifiManager = wifiManager
        private val permissions = arrayOf<String>(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        fun create(){
            requestPermission()
            if (!lackPermission()){
                val ipAddress = mWifiManager.connectionInfo.ipAddress
                mViewModel.startReceiveUdpMsg(ipAddress,mListener)
            }else{
                Toast.makeText(mContext,"缺少网络权限,请授权后重试",Toast.LENGTH_LONG).show()
                (mContext as Activity).finish()
            }
        }
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun destroy(){
            mViewModel.shutDownExecutor()
        }
    
        private fun requestPermission(){
    
            if (lackPermission()) {
                ActivityCompat.requestPermissions(
                    mContext as Activity,
                    permissions,
                    REQUEST_PERMISSIONS
                )
            }
        }
    
        private fun lackPermission():Boolean{
            for (permission in permissions){
                if (ContextCompat.checkSelfPermission(mContext,permission)!= PackageManager.PERMISSION_GRANTED){
                    return true
                }
            }
            return false
        }
    }
    

    5. MainViewModel

    UDPManager的调用放在了ViewModel中

    import androidx.lifecycle.ViewModel
    import com.psychedelic.udpchat.listener.UdpMessageListener
    import com.psychedelic.udpchat.listener.UdpMessageSendListener
    import com.psychedelic.udpchat.net.UdpManager
    import java.util.concurrent.ExecutorService
    import java.util.concurrent.Executors
    
    class MainViewModel():ViewModel(){
        private lateinit var mReceiveExecutor: ExecutorService
        private lateinit var mSendExecutor: ExecutorService
        private lateinit var mUdpManager: UdpManager
    
        fun startReceiveUdpMsg(intIpAddress:Int,listener:UdpMessageListener){
            mUdpManager = UdpManager(intIpAddress,listener)
            mReceiveExecutor = Executors.newSingleThreadExecutor()
            mSendExecutor = Executors.newFixedThreadPool(5)
            mReceiveExecutor.submit { mUdpManager.receiverUdpMsg()}
        }
    
        fun sendUdpMsg(msg:String,listener: UdpMessageSendListener){
            mSendExecutor.submit {
                mUdpManager.sendUdpMsg(msg,listener)
            }
        }
    
        fun shutDownExecutor(){
            mSendExecutor.shutdown()
            mReceiveExecutor.shutdown()
        }
    
    }
    

    最后附上RecyclerView Adapter的代码

    6. ChatRvAdapter

    import android.content.Context
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.databinding.DataBindingUtil
    import androidx.databinding.ViewDataBinding
    import androidx.recyclerview.widget.RecyclerView
    import com.psychedelic.udpchat.databinding.ChatItemFromBinding
    import com.psychedelic.udpchat.databinding.ChatItemToBinding
    
    const val CHAT_TYPE_SEND_TXT = 1
    const val CHAT_TYPE_GET_TXT = CHAT_TYPE_SEND_TXT + 1
    
    class ChatRvAdapter(context: Context, list: ArrayList<ChatEntity>, variableId: Int) :
        RecyclerView.Adapter<ChatRvAdapter.ViewHolder>() {
        private val mContext = context
        private var mList: ArrayList<ChatEntity> = list
        private val mVariableId = variableId
    
        inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            private var binding: ViewDataBinding? = null
            fun getBinding(): ViewDataBinding {
                return binding!!
            }
    
            fun setBinding(binding: ViewDataBinding) {
                this.binding = binding
            }
        }
    
        fun refreshData(list:ArrayList<ChatEntity>){
            mList = list
            notifyDataSetChanged()
        }
    
        override fun getItemViewType(position: Int): Int {
            return mList[position].fromWho
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            if (viewType == CHAT_TYPE_SEND_TXT) {
                val chatSendBinding = DataBindingUtil.inflate<ChatItemToBinding>(
                    LayoutInflater.from(mContext),
                    R.layout.chat_item_to,
                    parent,
                    false
                )
                val viewHolder = ViewHolder(chatSendBinding.root)
                viewHolder.setBinding(chatSendBinding)
                return viewHolder
            } else {
                val chatFromBinding = DataBindingUtil.inflate<ChatItemFromBinding>(
                    LayoutInflater.from(mContext),
                    R.layout.chat_item_from,
                    parent,
                    false
                )
                val viewHolder = ViewHolder(chatFromBinding.root)
                viewHolder.setBinding(chatFromBinding)
                return viewHolder
            }
    
        }
    
        override fun getItemCount(): Int {
            return mList.size
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.getBinding().setVariable(mVariableId, mList[position])
            holder.getBinding().executePendingBindings()
        }
    }
    

    完整项目Github地址:UdpChat

    项目效果:
    在这里插入图片描述

    只要安装此APP那么在局域网下的所有人都可以加入这个聊天室,即使没有连接到因特网也可以,没有去收集发送方的MAC地址,所以这个软件是匿名聊天的,而且聊天记录放在内存中,没有做持久化,推出APP就会销毁。

    以后有空会拿这个DEMO用Room去做一下聊天记录存储,用mac标识联系人,并且提供加密传输选项。还是挺好玩的。

    Over!
    在这里插入图片描述

    展开全文
  • Conficker.AE病毒局域网扫描工具 可以检测域域网内所有电脑是否中了Conficker.AE病毒 链接:https://pan.baidu.com/s/1-sgVbpWVaom83QwNJhQQ0A 提取码:uofj 复制这段内容后打开百度网盘手机...

    Conficker.AE病毒局域网扫描工具     

    可以检测域域网内所有电脑是否中了Conficker.AE病毒 

     

    链接:https://pan.baidu.com/s/1-sgVbpWVaom83QwNJhQQ0A
    提取码:uofj
    复制这段内容后打开百度网盘手机App,操作更方便哦
    展开全文
  • 发现IPerf——局域网测速工具

    万次阅读 2018-05-30 11:55:01
    一开始想用安卓端与Win10端进行测试,但安卓端的都在Google APP商店上,所以找了下Wifi阿拉丁的APP。 Wifi阿拉丁也支持IPerf,不过是2.0.5的版本,所以在Win10也使用了2.0.5。 在Win10的命令行内运行命令.\iperf -...

    挖井人:Slyar
    水源:IPerf

    过程

    一开始想用安卓端与Win10端进行测试,但安卓端的都在Google APP商店上,所以找了下Wifi阿拉丁的APP。

    Wifi阿拉丁也支持IPerf,不过是2.0.5的版本,所以在Win10也使用了2.0.5。
    在Win10的命令行内运行命令.\iperf -s -u -i 1,开启服务器。

    资料

    IPerf Doc

    IPerf2的相关说明如下:

    • -f [bkmaBKMA] 以MBpsc为显示单位,默认是m,Mbps
    • -i # 每#秒报告带宽、时间跳动、丢失帧等信息
    • -l #[KM] 发送与接收包的大小,为#kB或#MB
    • -m 不认识,关于TCP_MAXSEG
    • -p # 设置服务器与客户端的通讯端口
    • -u 以udp的方式进行测速
    • -w #[KM] socket 的buffer大小,为#kB或#MB
    • -B host 在多网网卡的系统中,绑定指定网卡;也可能用在UDP的多播设置中
    • -C 兼容模式,兼容比当前版本低的IPerf
    • M #[KM] 类似于-w,与-m相关,不太明白TCP_MAXSEG
    • -N 让TCP无延迟???
    • -V 使用IPv6地址
    • -h help
    • -v version

    服务器的选项:

    • -s 进入服务器模式
    • -D 进入Daemon模式,只支持在Unix平台下,Win平台下只能用服务化
    • -o 输出结果到文件,Win平台下
    • c host 指定待连接的客户端,UDP下不太好用
    • -P # 指定服务器处理连接的个数,处理完后关闭服务器,默认是0=无限

    客户端的选项:

    • -b #[KM] 设置UDP速率,单位是bps,默认是1Mbps
    • -c host 指定服务器地址
    • -d 进入双向测试模式
    • -n #[KM] 发送包的数量,会覆盖-t的策略
    • -r 进入妥协测试模式
    • -t # 发送#秒,以-l的大小,默认10s
    • -L # 监听的端口
    • -P #
    • -S #
    • -T #
    • -F
    • -l 与-F相同
    展开全文
  • 安卓app局域网内访问PC服务端

    千次阅读 2018-12-27 21:44:49
    对于没有公网IP的服务器,我们如果想在真机上运行app访问PC端的服务,则需要手机跟PC在同一个局域网内。在开发测试时候可以在PC上通过第三方工具(比如猎豹免费WIFI)创建WIFI并在手机上面连接该WIFI,然后可以手机...
  • Android/uni-app读取局域网所有IP&MAC

    千次阅读 2019-11-20 10:03:25
    创建一个读取局域网ip的工具类IPUtils 参考自:https://gitee.com/kalshen/IpScanner/blob/master/app/src/main/java/com/yoofn/ipscanner/IpScanner.java 稍微有些修改,不过大致一致,只是输出为Map修改为字符串 ...
  • 设计背景与痛点: ...悟空文件分享,旨在局域网内方便、快速、安全分享文件,支持PC到PC,PC到手机,无需漫长的上传等待和U盘、移动硬盘来回拷贝,直接生成下载链接发给同事下载,节省文件拷贝和上传时间。
  • 因为有个需求,就是想看某手机app内部网络部分是如何实现的,所以要抓取其数据包(主要是 Http 协议部分),Windows 下可以用 Fidder 为手机设置代理实现,Mac 下有一款 Debookee 的软件可以实现同样的功能,但是...
  • Fiddler抓包工具-APP

    2016-05-18 14:09:27
    有时候需要查看APP的网络请求,但是直接安装类似功能的app又需要root,但是fiddler不需要,配置简单,使用方便,实在是抓包分析必备良具。 工具/原料 Fiddler 电脑 手机 手机和电脑要在同一个局域网 ...
  • 如今电信,联通,移动,各大运营商都推出了智能IPTV业务,一条宽带绑定了一个智能安卓机顶盒,可以高清看IPTV直播,点播,等各类资源!但是大部分机顶盒都被禁止了安装第三方APP...需要准备 : 电脑 ADB工具 电视1...
  • Fiddler工具使用介绍二 在上一篇中介绍了Fiddler的基本使用方法。通过上一篇的操作我们可以直接抓取浏览器的数据包。但在APP测试中,我们需要抓取手机APP上的数据包,应该怎么操作呢? Andriod配置方法: 1)确保...
  • 随着手机的功能越来越多,也越来越...但手机的小屏幕决定了它不可能成为一个合格的生产力工具,即使手机 app 再强大,也只能针对特定的任务。因此,办公时电脑和手机来回切便成了许多人的常态,这样的后果就是效率...
  • 同项目组的小伙伴想用自己的电脑访问我电脑上开发阶段的create-react-app创建的react项目。 试过了了各种内网穿透工具ngrok以及localtunnel等。 奈何打开效率实在太过于龟速。 于是不得不百度 react项目如何开启内网...
  • 2.手机和电脑在同一局域网 二、设置 1.打开fiddler>Tools>Fiddler Options>Connections 勾选Allow remote computers to connect 端口设置为8888 2.打开fiddler>Tools>Fiddler Options>HTTPS>…...
  • APP开发和测试的过程中有时需要使用多个真机设备,而且随着流程的成熟,也需要在闲暇(比如下班后)调取全团队的测试手机进行一些全自动的多机回归、Monkey冒烟测试以及一些脚本。所以对设备的有效管理和调取,...
  • 准备工具 1.Jmeter 2.Android手机 开始之前说明一下 source是源代码版,你需要自己编译成可执行的软件 binary是可执行版,直接可以只用 本篇是基于Windows的,所以需要下载zip包,解压后如下打开jmeter ...
  • 手机app抓包 工具:burpsuite 前提条件:在同一个无线局域网 安装证书:burpsuite导出证书,手机导入证书
  • APP的WIFI 要配置手动配置代理,而且电脑的和手机的网络要在同一个局域网 当要抓取的线上环境是HTTPS的域名的话,手机端需要安装证书 PC客户端还要配一个SSL 代理端口        ...
  • 但在APP测试中,我们需要抓取手机APP上的数据包,应该怎么操作呢? Andriod配置方法: 1)确保手机和Fiddler所在主机在同一个局域网中 2)获取Fiddler所在主机的ip地址,通过cmd命令进入命令编辑器,输入ipconfig -...
  • 最近由于实验室技术需要,组建网络服务,刚开始只是局限于局域网下,所以只采用ssh就足够了,连接同一个局域网,分布式控制机器合作,...2、搭建远程服务,我了解的到的免费的个人使用的主要有一下几种,主要都是app...
  • 需求在平常生活或工作中,我们经常需要传输文件,比如将电脑上下载的App传送到手机上、同事之间传输一些大型的文件。当我们遇到此类问题时,首先想到的就是使用QQ或者微信,更深一层,去网上搜索一些文件传输工具,...
  • 因为Fiddler抓包的原理就是通过代理,所以确保被测终端要和安装Fiddler的电脑在同一个局域网中。(也就是同一网段中) 确保防火墙允许Fiddler进程可以远程连接。(不行就关闭防火墙) 步骤1:开启Fiddler的远程连接...
  • 转载请注明出处:抓取app数据教程–fiddler抓包数据截取-薄荷app为例 ...3、同一个局域网网络 也就是连接同一个wifi环境 Fiddler不但能截获各种浏览器发出的HTTP请求, 也可以截获手机发出的HTTP/HTTP...
  • 在web开发中,抓包工具是经常需要用到的,本文介绍mitmproxy抓包的使用方法。 1.在cmd中安装mitmproxy,用pip install mitmproxy安装mitmproxy 2.在cmd中键入mitmweb,浏览器会自动打开以下页面 3. 电脑上安装...
  • PC作服务器与手机APP进行网络通信(附源码与TCP服务器小工具) 本人是用来做ESP8266与手机网络通信的,这里这是用电脑PC端模拟服务端,如果要实现与ESP8266只需将ESP8266作为服务器即可,目前本人暂时没时间去整理...
  • 【Android】socket局域网通信

    千次阅读 2015-09-16 09:09:49
    我有一段时间特别想实现一个短距离的手机交互软件,比如多人联机小游戏app或者是多人文件共享app等,思来想去,得出了两个方案,一个是使用手机自带的蓝牙设备,通过蓝牙技术实现两个手机的数据交换,而另一个就是...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 186
精华内容 74
关键字:

局域网工具app