In most cases, what we come into contact with are some conceptual articles. I hope this article can bring you a different experience, so that you can better digest the knowledge related to inter-process communication.
tips: In actual development, if inter-process communication is required, it is recommended to use Binder, Broadcast, ContentProvider, etc. These mechanisms are more efficient and safer.
1. Binder
Use AIDL
Reference: https://blog.csdn.net/qq_42751010/article/details/132182022
2. Pipeline
Server code:
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedWriter import java.io.OutputStreamWriter import java.io. PipedInputStream import java.io. PipedOutputStream class ServerMainActivity : AppCompatActivity() {<!-- --> private lateinit var outputStream: PipedOutputStream private lateinit var inputStream: PipedInputStream override fun onCreate(savedInstanceState: Bundle?) {<!-- --> super.onCreate(savedInstanceState) setContentView(R. layout. activity_main) outputStream = PipedOutputStream() inputStream = PipedInputStream(outputStream) lifecycleScope.launch(Dispatchers.IO) {<!-- --> startServer() } } private suspend fun startServer() {<!-- --> val writer = BufferedWriter(OutputStreamWriter(outputStream)) while (true) {<!-- --> // read the request content from the pipe val request = withContext(Dispatchers.IO) {<!-- --> readRequestFromPipe() } val response = if (request == "open_camera") {<!-- --> openCamera() "Camera opened" } else {<!-- --> "Invalid request" } // write the response content to the pipe withContext(Dispatchers.IO) {<!-- --> writer. write(response) writer. newLine() writer. flush() } } } private suspend fun readRequestFromPipe(): String {<!-- --> val reader = BufferedReader(InputStreamReader(inputStream)) return withContext(Dispatchers.IO) {<!-- --> reader. readLine() } } private fun openCamera() {<!-- --> // Open the operation of the camera } }
Client code:
import android.os.Bundle import android.util.Log import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedReader import java.io.InputStreamReader import java.io. PipedInputStream import java.io. PipedOutputStream class ClientMainActivity : AppCompatActivity() {<!-- --> private lateinit var connectButton: Button private lateinit var outputStream: PipedOutputStream private lateinit var inputStream: PipedInputStream override fun onCreate(savedInstanceState: Bundle?) {<!-- --> super.onCreate(savedInstanceState) setContentView(R. layout. activity_main) connectButton = findViewById(R.id.connectButton) connectButton.setOnClickListener {<!-- --> lifecycleScope.launch(Dispatchers.IO) {<!-- --> sendRequestToServer() } } outputStream = PipedOutputStream() inputStream = PipedInputStream(outputStream) } private suspend fun sendRequestToServer() {<!-- --> try {<!-- --> // write the request content to the pipe outputStream.write("open_camera".toByteArray()) // wait for server response val response = withContext(Dispatchers.IO) {<!-- --> readResponseFromPipe() } Log.d("ClientMainActivity", "Received response: $response") } catch (e: Exception) {<!-- --> e. printStackTrace() } } private suspend fun readResponseFromPipe(): String {<!-- --> val reader = BufferedReader(InputStreamReader(inputStream)) return withContext(Dispatchers.IO) {<!-- --> reader. readLine() } } }
3. Socket
Server code:
import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedReader import java.io.InputStreamReader import java.io.PrintWriter import java.net.ServerSocket class ServerActivity : AppCompatActivity() {<!-- --> override fun onCreate(savedInstanceState: Bundle?) {<!-- --> super.onCreate(savedInstanceState) setContentView(R. layout. activity_server) // Start the coroutine to execute server-side Socket communication lifecycleScope. launch {<!-- --> startServer() } } private suspend fun startServer() {<!-- --> val serverSocket = ServerSocket(8080) // Create a ServerSocket object and listen to the specified port while (true) {<!-- --> val clientSocket = serverSocket.accept() // wait for client connection // handle client request launch(Dispatchers.IO) {<!-- --> val reader = BufferedReader(InputStreamReader(clientSocket. getInputStream())) val writer = PrintWriter(clientSocket. getOutputStream(), true) val request = reader.readLine() // read the request sent by the client Log.d("ServerActivity", "Received request: $request") // process the request and return the response val response = "Hello, client!" writer. println(response) Log.d("ServerActivity", "Sent response: $response") if (request == "open_camera") {<!-- --> // After receiving the request to open the camera, call the code of the server to open the camera openCamera() } writer. close() reader. close() clientSocket. close() } } } private fun openCamera() {<!-- --> Log.d("ServerActivity", "Opening camera...") //... } }
Client code:
import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedReader import java.io.InputStreamReader import java.io.PrintWriter import java.net.Socket class ClientActivity : AppCompatActivity() {<!-- --> private lateinit var connectButton: Button private var clientSocket: Socket? = null private var writer: PrintWriter? = null private var reader: BufferedReader? = null override fun onCreate(savedInstanceState: Bundle?) {<!-- --> super.onCreate(savedInstanceState) setContentView(R. layout. activity_client) connectButton = findViewById(R.id.connectButton) connectButton.setOnClickListener {<!-- --> // send request to server lifecycleScope.launch(Dispatchers.IO) {<!-- --> sendRequestToServer("open_camera") } } // connect to the server on creation lifecycleScope.launch(Dispatchers.IO) {<!-- --> connectToServer() } } private suspend fun connectToServer() {<!-- --> val serverAddress = "localhost" // server address val serverPort = 8080 // server port clientSocket = Socket(serverAddress, serverPort) // Create a Socket to connect to the server reader = BufferedReader(InputStreamReader(clientSocket?.getInputStream())) writer = PrintWriter(clientSocket?.getOutputStream(), true) Log.d("ClientActivity", "Connected to server") } private suspend fun sendRequestToServer(request: String) {<!-- --> writer?.println(request) // Send the request to the server Log.d("ClientActivity", "Sent request: $request") val response = reader?.readLine() // read the response from the server Log.d("ClientActivity", "Received response: $response") } override fun onDestroy() {<!-- --> super. onDestroy() try {<!-- --> // close connection and resource writer?. close() reader?. close() clientSocket?. close() } catch (e: Exception) {<!-- --> e. printStackTrace() } } }
4. File sharing and semaphores
Server code:
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File import java.util.concurrent.Semaphore class ServerMainActivity : AppCompatActivity() {<!-- --> private lateinit var requestFile: File private lateinit var responseFile: File private lateinit var semaphore: Semaphore override fun onCreate(savedInstanceState: Bundle?) {<!-- --> super.onCreate(savedInstanceState) setContentView(R. layout. activity_main) requestFile = File(filesDir, "camera_request.txt") responseFile = File(filesDir, "camera_response.txt") semaphore = Semaphore(0) lifecycleScope.launch(Dispatchers.IO) {<!-- --> startServer() } } private suspend fun startServer() {<!-- --> while (true) {<!-- --> // Wait for the semaphore, indicating that there is a new request semaphore. acquire() if (requestFile. exists()) {<!-- --> // read request file val request = withContext(Dispatchers.IO) {<!-- --> requestFile. readText() } val response = if (request == "open_camera") {<!-- --> openCamera() "Camera opened" } else {<!-- --> "Invalid request" } // write to response file withContext(Dispatchers.IO) {<!-- --> responseFile.writeText(response) } // Release the semaphore and notify the client that there is a response to read semaphore. release() } } } private fun openCamera() {<!-- --> // Open the operation of the camera } }
Client code:
import android.os.Bundle import android.util.Log import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File import java.util.concurrent.Semaphore class ClientMainActivity : AppCompatActivity() {<!-- --> private lateinit var connectButton: Button private lateinit var requestFile: File private lateinit var responseFile: File private lateinit var semaphore: Semaphore override fun onCreate(savedInstanceState: Bundle?) {<!-- --> super.onCreate(savedInstanceState) setContentView(R. layout. activity_main) connectButton = findViewById(R.id.connectButton) connectButton.setOnClickListener {<!-- --> lifecycleScope.launch(Dispatchers.IO) {<!-- --> sendRequestToServer() } } requestFile = File(filesDir, "camera_request.txt") responseFile = File(filesDir, "camera_response.txt") semaphore = Semaphore(0) } private suspend fun sendRequestToServer() {<!-- --> try {<!-- --> // Create a request file and write the request content requestFile.writeText("open_camera") // Release the semaphore to notify the server of a new request semaphore. release() // wait for server response semaphore. acquire() val response = withContext(Dispatchers.IO) {<!-- --> responseFile. readText() } Log.d("ClientMainActivity", "Received response: $response") } catch (e: Exception) {<!-- --> e. printStackTrace() } } }