Python(TCP server) -> Android/Kotlin(TCP client)へ画像送信
ひとまず送れたということで殴り書き。
やりたいことを成し遂げるまでは課題は山のようにある。
・分割しなくても1度に送受信できる大きさの画像(1773Byte)
・画像のパスはpythonのコードと同じ階層
from PIL import Image import socketserver import io #ひとまず同じ階層に置いた img = Image.open('palm32.png') img_bytes = io.BytesIO() img.save(img_bytes,format="PNG") img_bytes = img_bytes.getvalue() #print(len(img_bytes)) #len(img_bytes)でバイトサイズを取得する class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip() print("{} wrote:".format(self.client_address[0])) print(self.data) self.request.sendall(img_bytes) #<-画像を送信 #y = bytearray([0x01,0x02,0x03,0x04]) #print(y) #self.request.sendall(y) if __name__ == "__main__": HOST, PORT = '127.0.0.1', 2001 with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server: server.serve_forever()
Kotlin
package xxx import android.graphics.BitmapFactory import android.os.Bundle import android.util.Log import android.widget.Button import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.launch import java.nio.ByteBuffer const val MSG_CONNECTION_SUCCESS = 111 // 接続成功 const val MSG_CONNECTION_FAILED = 222 // 接続失敗 const val MSG_IOEXCEPTION = 333 // 例外発生 class MainActivity : AppCompatActivity() { private var tcpcom: ComTcpClient? = null val ip = "10.0.2.2" val port = "2001" private val TAG = MainActivity::class.java.simpleName override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) connect() val imgView = findViewById<ImageView>(R.id.imageView) val button = findViewById<Button>(R.id.sendButton) button.setOnClickListener{ //todo なんかメッセージ送る val sendArray = ByteBuffer.allocate(30) sendArray.putInt(0x01020304) sendArray.putInt(0x05060708) val byteArray = ByteBuffer.allocate(640000) try { tcpcom?.sendOrReceive { outputStream, inputStream -> outputStream.write(sendArray.array()) inputStream.read(byteArray.array()) //todo whileで受信し続ける必要がある /* ByteArrayOutputStream BitmapFactory.decodeByteArray()*/ //println("受信メッセージ:"+byteArray.getInt()) val img = BitmapFactory.decodeByteArray(byteArray.array(),0,byteArray.array().size) print(img) } //imgView.setImageBitmap(img) } catch(e: Exception){ Log.d(TAG,"Failed...") } } val channel = Channel<Int>() GlobalScope.launch(Dispatchers.Main) { when (channel.receive()) { MSG_CONNECTION_SUCCESS -> { Log.d(TAG,"Success!") } MSG_CONNECTION_FAILED -> { Log.d(TAG,"Failed...") // エラー処理 } MSG_IOEXCEPTION -> { Log.d(TAG,"Exception!") //エラー処理 } } } } fun connect(){ val channel = Channel<Int>() if (!ip.isEmpty() && !port.isEmpty()) { tcpcom = ComTcpClient(ip, port.toInt(), channel) tcpcom?.connect() } } }
Client側でinputStreamをループさせ続けることで大きなサイズの画像も受信することができた。1MB程度まで確認。
なおServer側は画像のbytearrayを一度で投げている。
受信もといループの画像サイズは手動設定。
try { tcpcom?.sendOrReceive { outputStream, inputStream -> outputStream.write(sendArray.array()) while(byteSize<1400000) { inputStream.read(byteArray.array()) allByteArray.write(byteArray.array()) byteSize += 1024 } //println("受信メッセージ:"+byteArray.getInt()) val img = BitmapFactory.decodeByteArray(allByteArray.toByteArray(),0,allByteArray.toByteArray().size) handler.post{ imgView.setImageBitmap(img) } print(img) } //imgView.setImageBitmap(img) }
handlerを使ってviewの更新もできた。一歩前進。
実際はサイズ調整も必要になりそう。
Kotlin:
qiita.com