2022/03/12

[js] Uint8Array はオブジェクト

まとめ

  • React Native → Android へ Uint8Array を渡したいとしても、base64 でエンコードするのが無難そう

 


おはなし

前の記事で ArrayList<Byte> を ByteArray に変換する話をした。
しかし、その前の条件が間違えていた。
React Native から Uint8Array を Android に渡したのだが、Uint8Array はオブジェクトであって配列ではないということだ。

Error: Exception in HostFunction: Malformed calls from JS: field sizes are different.

こんな例外が発生したのだ。

たぶん number[] を渡せばうまくいくのだろうが、やりたいことはそうではない。
おそらく Uint8Array も Kotlin の ByteArray と同じように効率が良いオブジェクトなのだと思う。
それを for とかでぐるぐる回して number[] に入れて渡すなんてことはしたくないのだ。

 

そんなわけで Uint8Array を眺めている。

Uint8Array
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array

まず、 Uint8Array.toString() で文字列にして String.toByteArray() で戻してみた。
・・・ダメ。
toString() は中のデータを無理やり文字列として扱う、ではなく、中のデータを 1バイトずつコンマ区切りで出力する、というものだった。

toLocaleString() がたぶんそういうことをしてくれそうなのだけど、locale の指定をするということは何かしらの変換をバイト単位とかで行うということだと思う。
それだったら・・・それだったら base64 にしてやりとりするのが一番無難じゃないか!

base64 なら無理やりな変換ではなくバイナリ向きだし、文字列になるし、何も問題はない。
問題なのは、せっかくプリミティブ向けに型を作ってあるのに申し訳ないという気持ちだけだ。

 

というわけで、こうなりましたとさ。

JavaScript側 : base64String = Buffer.from(Uint8ArrayData).toString('base64')
Android側 : Base64.decode(base64String, Base64.DEFAULT)