Preface
When it comes to inter-communication between Android, everyone will think of AIDL at the first time, but due to the limitations of the Binder mechanism, AIDL cannot transmit super-large data.
So how do we transmit big data between processes?
Android provides us with another mechanism: LocalSocket
It creates a socket channel locally for data transfer.
So how do you use it?
First we need two applications: client and server
Server Initialization
override fun run() { server = LocalServerSocket("xxxx") remoteSocket = server?.accept() ... }
First create a LocalServerSocket service. The parameters are the service name. Note that this service name needs to be unique. This is the basis for connecting the two ends.
Then call the accept function to wait for the client to connect. This function is block thread, so in the example, a new thread is started.
When the client initiates the connection, accept will return the LocalSocket object and then the data can be transferred.
Client Initialization
var localSocket = LocalSocket() (LocalSocketAddress("xxxx"))
First create a LocalSocket object
Then create a LocalSocketAddress object, the parameter is the service name
Then call the connect function to connect to the service. You can use this socket to transmit data.
Data transmission
The socket objects on both ends are the same class, so the sending and receiving codes on both ends are logically consistent.
passand
The input and output stream can be obtained and data transmission is carried out through reading and writing of the stream.
Note that when reading and writing streams, you must open a new thread to process.
Because the socket is bidirectional, both ends can send and receive, that is, read and write
Send data
var pool = () var runnable = Runnable { try { var out = (data) () } catch (e: Throwable) { ("xxx", "xxx", e) } } (runnable)
Sending data is an active action, and each time you send, you need to start another thread, so if it is multiple times, we need to use a thread pool to manage it.
If you need to send data multiple times, you can encapsulate it into a function
Receive data
Receiving data is actually a while loop, looping to read data. It is best to start after the connection is successful, such as the client.
(LocalSocketAddress("xxx")) var runnable = Runnable { while (){ var input = (data) ... } } Thread(runnable).start()
The receiving data is actually a while loop that keeps reading. It continues to loop before reading the data, and then processes and loops again when reading the data. Therefore, there is only one other thread here, and there is no need for a thread pool.
Transfer of complex data
The above is just a simple example, and it is impossible to transmit complex data. If you want to transmit complex data, you need to use it.DataInputStream
andDataOutputStream
。
First, you need to define a set of protocols.
For example, define a simple protocol: the transmitted data is divided into two parts, the first part is an int value, indicating the length of the subsequent byte data; the second part is byte data. This way you know how to read and write
Write data
var pool = () var out = DataOutputStream() var runnable = Runnable { try { () (data) () } catch (e: Throwable) { ("xxx", "xxx", e) } } (runnable)
Read data
var runnable = Runnable { var input = DataInputStream() var outArray = ByteArrayOutputStream() while (true) { () var length = () if(length > 0) { var buffer = ByteArray(length) (buffer) ... } } } Thread(runnable).start()
This will enable the transmission of complex data without causing data confusion.
Transmit super large data
Although the above can transmit complex data, problems will also arise when our data is too large.
For example, transmitting pictures or videos, assuming that the byte data length reaches 1228800, then we pass
var buffer = ByteArray(1228800) (buffer)
All data cannot be read, only a part of it is read. It will also cause confusion in the subsequent data because the read position is misaligned.
The length of the read is about 65535 bytes, because TCP is wrapped by IP packets, and there will be a packet size limit of 65535.
But be careful! When writing data, if the data is too large, it will be automatically subcontracted, but when reading data, it seems that it cannot cross the packet at a time, which leads to the above result. Only one packet can be read, and the subsequent one will be confused.
So how should this super-large data be transmitted? We use a loop to write it bit by bit, read it out bit by bit, and constantly correct the offset according to the results. Code:
Write
var pool = () var out = DataOutputStream() var runnable = Runnable { try { () var offset = 0 while ((offset + 1024) <= ) { (data, offset, 1024) offset += 1024 } (data, offset, - offset) () } catch (e: Throwable) { ("xxxx", "xxxx", e) } } (runnable)
Read
var input = DataInputStream() var runnable = Runnable { var outArray = ByteArrayOutputStream() while (true) { () var length = () if(length > 0) { var buffer = ByteArray(1024) var total = 0 while (total + 1024 <= length) { var count = (buffer) (buffer, 0, count) total += count } var buffer2 = ByteArray(length - total) (buffer2) (buffer2) var result = () ... } } } Thread(runnable).start()
This can avoid the problem of mismatch in the length of the read due to subcontracting
The above is the detailed explanation of LocalSocket between Android processes. For more information about Android LocalSocket, please follow my other related articles!