說起 Android 進行間通信,大家第一時間會想到 AIDL,但是由于 Binder 機制的限制,AIDL 無法傳輸超大數據。
那么我們如何在進程間傳輸大數據呢?
Android 中給我們提供了另外一個機制: LocalSocket。它會在本地創建一個 socket 通道來進行數據傳輸。
那么它怎么使用?
首先我們需要兩個應用: 客戶端和服務端。
override fun run() {
server = LocalServerSocket("xxxx")
remoteSocket = server?.accept()
...
}
先創建一個 LocalServerSocket 服務,參數是服務名,注意這個服務名需要唯一,這是兩端連接的依據。
然后調用 accept 函數進行等待客戶端連接,這個函數是 block 線程的,所以例子中另起線程。
當客戶端發起連接后,accept 就會返回 LocalSocket 對象,然后就可以進行傳輸數據了。
var localSocket = LocalSocket()
localSocket.connect(LocalSocketAddress("xxxx"))
兩端的 socket 對象是一個類,所以兩端的發送和接受代碼邏輯一致。
通過 localSocket.inputStream 和 localSocket.outputStream 可以獲取到輸入輸出流,通過對流的讀寫進行數據傳輸。
注意,讀寫流的時候一定要新開線程處理。
因為 socket 是雙向的,所以兩端都可以進行收發,即讀寫。
發送數據
var pool = Executors.newSingleThreadExecutor()
var runnable = Runnable {
try {
var out = xxxxSocket.outputStream
out.write(data) out.flush()
} catch (e: Throwable) {
Log.e("xxx", "xxx", e)
}
}
pool.execute(runnable)
localSocket.connect(LocalSocketAddress("xxx"))
var runnable = Runnable {
while (localSocket.isConnected) {
var input = localSocket.inputStreaminput.read(data)
...
}
}
Thread(runnable).start()
首先需要定義一套協議。
寫數據
var pool = Executors.newSingleThreadExecutor()
var out = DataOutputStream(xxxSocket.outputStream)
var runnable = Runnable {
try {
out.writeInt(data.size) out.write(data) out.flush()
} catch (e: Throwable) {
Log.e("xxx", "xxx", e)
}
}
pool.execute(runnable)
讀數據
var runnable = Runnable {
var input = DataInputStream(xxxSocket.inputStream)
var outArray = ByteArrayOutputStream()
while (true) {
outArray.reset()
var length = input.readInt()
if(length > 0) {
var buffer = ByteArray(length)
input.read(buffer)
...
}
}
}
Thread(runnable).start()
var buffer = ByteArray(1228800)
input.read(buffer)
寫入
var pool = Executors.newSingleThreadExecutor()
var out = DataOutputStream(xxxSocket.outputStream)
var runnable = Runnable {
try {
out.writeInt(data.size)
var offset = 0
while ((offset + 1024) <= data.size) {
out.write(data, offset, 1024)
offset += 1024
}
out.write(data, offset, data.size - offset)
out.flush()
} catch (e: Throwable) {
Log.e("xxxx", "xxxx", e)
}
}
pool.execute(runnable)
讀取
var input = DataInputStream(xxxSocket.inputStream)
var runnable = Runnable {
var outArray = ByteArrayOutputStream()
while (true) {
outArray.reset()
var length = input.readInt()
if(length > 0) {
var buffer = ByteArray(1024)
var total = 0
while (total + 1024 <= length) {
var count = input.read(buffer)
outArray.write(buffer, 0, count)
total += count
}
var buffer2 = ByteArray(length - total)
input.read(buffer2)
outArray.write(buffer2)
var result = outArray.toByteArray()
...
}
}
}
Thread(runnable).start()