IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android基于socket网络通信开发 -> 正文阅读

[移动开发]Android基于socket网络通信开发

前言:

前段时间有朋友叫我帮封装下socket,闲来无事就顺带的做了,顺便充实自己,再就是怕忘记所以记录下。

写的不好或哪里可以完善的请多多指出,毕竟第一次写,自己文笔不好还是有自知之明的。^^


一、socket是什么?

网上介绍socket的文章一大堆,我就不废那功夫了(主要懒^^),有需要的自行网上查找就好。

代码整体是用kotlin写的,毕竟官方也推荐嘛。当然Java也可以调用并不影响使用。以下内容只有客户端代码,基于调试助手测试。socket整体的收发代码都写在了service中。

二、使用步骤

1.activity调用

代码如下(示例):

class ServiceActivity: Activity() {

    lateinit var myBinder: SocketService.MyBinder
    lateinit var socketService: SocketService

    private val connect = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            //实例化socketService
            myBinder = p1 as SocketService.MyBinder
            socketService = myBinder.getService()
        }

        override fun onServiceDisconnected(p0: ComponentName?) {}
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val intent = Intent(this, SocketService::class.java)
        startService(intent)//启动service
        bindService(intent, connect, Context.BIND_AUTO_CREATE)//将该activity与对应service绑定

        socketService.sendMessage("11")//发送消息
    }
}

代码看起来还是很简单的。依次启动service、绑定service。这里采用binder对象的方式实现service与activity之间的通信,并实例化socketService,之后就可收发信息。

2.SocketService的创建

代码如下(示例):

class SocketService : Service() {

    val mBinder = MyBinder()

    var isReconnect: Boolean = true

    companion object {
        lateinit var mThreadPool: ExecutorService
        lateinit var socket: Socket
        lateinit var outputStream: OutputStream
        lateinit var inputStream: InputStream
        lateinit var isr: InputStreamReader
        lateinit var br: BufferedReader

        var ip = "192.168.3.33"
        var port = 8000
    }

    class MyBinder : Binder() {
        fun getService(): SocketService {
            return SocketService()
        }
    }

    override fun onBind(p0: Intent?): IBinder {
        return mBinder
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        initConnect(ip, port)
        return super.onStartCommand(intent, flags, startId)
    }

    fun initConnect(ip: String, port: Int) {
        mThreadPool = Executors.newCachedThreadPool()
        mThreadPool.execute(object : Thread() {
            override fun run() {
                try {
                    Log.d("service", "开始连接")
                    socket = Socket(ip, port)
                    Log.d("service", socket.isConnected.toString())
                } catch (e: Exception) {
                    Log.w("service", e.toString())
                }
            }
        })

        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE)
        mHandler.postDelayed(reciveBeatRunnable, RECIVE_BEAT_RATE)
    }

    fun sendMessage(msg: String) {
        mThreadPool.execute(object : Thread() {
            override fun run() {
                try {
                    outputStream = socket.getOutputStream()
                    outputStream.write(msg.toByteArray())
                    outputStream.flush()
                } catch (e: Exception) {
                    Log.w("service", e.toString())
                }
            }
        })
    }

    val RECIVE_BEAT_RATE: Long = 1 * 1000     //每隔1秒检测服务端发送的数据
    val HEART_BEAT_RATE: Long = 2 * 1000      //每隔2秒发送心跳
    var mHandler: Handler = Handler()

    var reciveBeatRunnable: Runnable = object : Runnable {
        override fun run() {

            mThreadPool.execute(object : Thread() {
                override fun run() {
                    try {
                        inputStream = socket.getInputStream()
                        isr = InputStreamReader(inputStream)
                        br = BufferedReader(isr)
                        Log.d("service", br.read().toString())
                    } catch (e: Exception) {
                        Log.w("service", e.toString())
                    }
                }
            })
            //每隔一定的时间,对服务端发送的数据检测
            mHandler.postDelayed(this, RECIVE_BEAT_RATE)
        }
    }

    var heartBeatRunnable: Runnable = object : Runnable {
        override fun run() {

            Log.d("service", "心跳包检测socket连接状态")

            mThreadPool.execute(object : Thread() {
                override fun run() {
                    try {
                        outputStream = socket.getOutputStream()
                        outputStream.write("test".toByteArray())
                        outputStream.flush()
                    } catch (e: Exception) {
                        Log.d("service", "开始重连")
                        reconnectSocket()
                    }
                }
            })
            //每隔一定的时间,对服务端发送的数据检测
            mHandler.postDelayed(this, HEART_BEAT_RATE)
        }
    }

    fun reconnectSocket() {
        mHandler.removeCallbacks(heartBeatRunnable)
        mHandler.removeCallbacks(reciveBeatRunnable)
        outputStream.close()
        inputStream.close()
        isr.close()
        br.close()
        socket.close()
        mThreadPool.shutdown()

        if (isReconnect) {
            initConnect(ip, port)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        isReconnect = false
        outputStream.close()
        br.close()
        socket.close()
        mThreadPool.shutdown()
    }
}

该处采用ExecutorService创建线程池进行Socket、OutputStream、InputStream、InputStreamReader、BufferedReader的实例化。采用向服务端不断地发送数据来检测连接是否正常,并每隔一秒回检测服务端是否向客户端发送数据。使用时需修改对应的ip地址及端口号。

注:该程序运行时必须确保服务端是开启状态,以及客户端与服务端在同一局域网下,否则会报初始化失败异常


总结

文章自我感觉写的不怎么样,第一次写写的不好下次努力。有不懂的或者优化完善的建议欢迎提出,大家一起进步^^。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-19 12:00:17  更:2021-10-19 12:01:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:48:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码