Android で外部キーボード使用時の日本語入力を快適にする (SKK) | tech - 氾濫原 というのを書いたが、設定できない部分で自分にあわない挙動があったので、fork して変更した。
以下の点だけ
- egg-like-newline な挙動に (変換中の RET で改行を入力しない)
- 辞書登録時に何も入力せず RET した場合は元の状態に戻るように
GitHub Actions で自動ビルドするようにしてある。
Android で外部キーボード使用時の日本語入力を快適にする (SKK) | tech - 氾濫原 というのを書いたが、設定できない部分で自分にあわない挙動があったので、fork して変更した。
以下の点だけ
GitHub Actions で自動ビルドするようにしてある。
Android では、アプリのサイズをできるだけ減らしたりするために、リリース前にアプリ全体のコードの最適化 (いわゆるツリーシェイキング) が推奨されている。動作としては、実行されるコードを解析で割り出しで、不要なコードを全て削除、というものになる。
基本的には minifyEnabled true を build.gradle に書けばよくて、簡単なアプリケーションなら、マニフェストから起動される Activity を解析してそこから呼ばれるクラスやメソッドは削除されないようになるので、これだけですむ。
が、リフレクションや JNI、または capacitor のように JavaScript のエンジンを一度経由して呼ばれるクラスなどは、この解析パスで到達できない。結果として、性質上、実行時にエラーが起こることになる。
capacitor の場合、JavaScript 経由で呼ばれるものには全て keep しておく必要がある。
-keep public class com.getcapacitor.plugin.App {
static *;
public *;
}
-keep public class com.getcapacitor.plugin.Device {
static *;
public *;
}
-keep public class com.getcapacitor.plugin.Filesystem {
static *;
public *;
}
-keep public class org.apache.cordova.CordovaPlugin
-keep public class fr.drangies.cordova.serial.**
-keepclasseswithmembers class com.hoho.android.usbserial.driver.** {
static *;
public *;
}
-printconfiguration /tmp/full-r8-config.txt
-printusage /tmp/usage.txt `-keep public class com.getcapacitor.plugin.Filesystem` だけだと名前が変わってしまう。ProGuard の指定方法がややこしつてよくわからなかったが、上記のようにしたらうまくいった。
cordovarduino という Cordova のプラグインを利用しているので、それ系の設定もある。
`-printusage` で指定したファイルには「削除された」クラスやメソッド名が出力される。必要なメソッドが意図せず削除されているかも?と思ったらこのファイルを見てみる。
手元にある Elecraft KX3 の測定をしてみる。
(ちなみに当局の KX3 は「平成17年12月以降にアマチュア局の保証を受けて免許を受けた無線機」に該当するのでスプリアス確認保証は不要、のはず)
以下を根拠に測定する
測定結果を提出データとして使うためには測定器(スペアナ)が1年以内に校正されていなければならないので、現実的に個人でこれを行うのは難しい。
しかしアマチュアであれば JARD に対してスペアナ(校正済みでなくてもよい) の測定結果をもって保証してもらうという手がある。
アマチュアの場合広い帯域を一括で免許をうけるので、どの周波数を使うのかと思うが、割り当て帯域幅によって異なり、帯域幅が1MHz以下なら指定周波数 (免許状に書いてある、周波数帯域の中央) で測定をすれば良いらしい。別表第35
ただし電波形式は免許を受けるすべての形式で行う必要がある。
スプリアス領域における不要発射等の測定方法の陸上関係無線設備(一般)にしたがう。
スペアナの設定のうちRBW, VBW, 検波モードが必ず指定された通りになっていることを確認すること。
探索したピークに周波数をあわせて振幅をはかる
面倒なので 40m (7100kHz) の CW だけでやる。変調をかけ最大送信電力にするということになっている。できるだけ厳しい条件でやるという意図だと思われるので、短点連続(帯域が最大)でやってみる。技適の手順だと25ボーとか、外部変調装置がある場合その最高速度みたいな手順みたいだが…
10W 7100kHz の場合、帯域外領域のスプリアス発射強度の許容値は 50mW (17dBm) 以下かつ、基本周波数の平均電力より40dB低い値。スプリアス領域での不要発射の強度の許容値は 50μW (-13dBm)以下。
必要周波数帯 (BN) は基本的に占有周波数帯幅の許容値と同値になるので CW の場合は 0.5kHz。スプリアス領域 は 2.5BN 離れた領域なため、7100±1.25kHz の外側がスプリアス領域。
7MHz の場合、基本波が9kHz〜100MHzのケースのためなのでスプリアスの測定範囲は 9kHz〜1GHz。ただし10倍高調波まで見る。
帯域外領域の測定を勘違いしていました。別表第一 スプリアス発射又は不要発射の強度の測定方法 によると帯域外領域は無変調で行うようです。
ということで撮りなおしました。(Ref Offset を40dBいれているので、直読できるようになってます)
以下の画像はキーイング状態なので正確な測定ではないです。
一旦必要周波数帯と帯域外発射を見る。帯域外発射の範囲は 7100±1.25kHz なので、7100kHz を CENTER にして 2.5kHz SPAN で見てみる。
「帯域外領域のスプリアス発射強度の許容値は 50mW 以下かつ、基本周波数の平均電力より40dB低い値。」基本周波数の平均電力より -64dB 低いので後者の条件は達成、10W は 40dBm なので、帯域外領域の発射強度は -24dBm。50mW は約17dBmなので達成している。
上下にあるので、下から見ていく。
下側 RBW=1kHz の範囲
なにもなさそう。
下側 RBW=10kHz の範囲
なにもなさそう。
上側 RBW=10kHz の範囲
高調波が出てる。40dBm -62 なので -22dBm。50μW (13dBm) 以下なので合格
RBW=100kHz の範囲
見つからず。
「ITU-R 勧告SM.329-10における指針」に従って、基本周波数の10倍高調波まで見れば良いことにはなっている。つまり 7MHz なら 70MHz まで見れば十分なはず。
スプリアス強度が許容値を超えていた場合はどのぐらい超えたかを確定させるため、スプリアス振幅測定を行う必要がある。
今回は超えていないがこれもやってみる。14.2MHz を CENTER にして、ゼロスパンにする。
1Fに住んでいて、ハザードマップでは最悪2mの浸水、ということは事前に調べてあった。土曜日10時ごろには既に、浸水地域に対してエリアメールで警戒レベル4が出た。実際まだ上陸まで時間がだいぶあるのに多摩川の水位が非常に上がっていた。子どももいるので暴風域に入ってから移動はしたくないし、万が一のときマンションの階段をかけのぼるのもあまりやりたくない。とかいろいろ考えた結果避難を決断。11時ごろに傘がさせる程度の雨の中避難所に (かっぱは着てたが)。
避難したことがなかったので、ちゃんと避難所が開設されているのか不安だったが一応開いていた。一旦かなり狭い部屋に案内されたあと、人が増えてきたので体育館が解放された。
そこで近くに住む妻方の親戚も避難してきて合流。食料や貴重品に不安があったので、子どもを親戚にあずけて一旦帰宅。短時間にだいぶ風雨が強くなっており、往復だけでずぶぬれに。
ところで避難所も浸水地域のため、体育館も安全ではなく、加えてさらに避難者が増えていたので、全体的に体育館は使わず、校舎内の一定階数以上を使うようにと再三の変更があった。
小学校側の担当者と市の担当者がいるみたいで、若干せめぎあいがあるみたいだった。小学校側としては児童のものがあり授業の円滑な継続のためには教室などは解放したくないようだった。当初は特別教室しか解放されていなかったが、増え続ける避難者に対して足りなくなり解放されていた。
21時ぐらいに台風が最接近して、急激に納まっていった。風雨の状況が全くわからない場所にいたので、そのへんの恐怖感は全くなかった。22時ぐらいから帰りはじめる避難者もいた。24時ぐらいにはほぼ完全に風雨がおさまっていたが、子どもが寝ていたし自宅の状況もわからないし、水位も下がりきっているわけではないので、そのまま明るくなるのを待った。
結局何事もなく、停電も断水も浸水もなかった。影響ある地点は越水まで1m程度でなんとか決壊しなかった。治水事業に感謝。
避難は結果的には辛いだけで無駄だったが、判断自体は間違いではなかったと思いたい。ただ避難先はもっと先に考えといたほうがよかった。漠然と公設避難所と思っていたが、これはかなり厳しいなと思った。ホテルとかに避難できればたぶんベストだと思った。
ちょっと困ったことが起きており、一昨日からワンオペ。
普段ルーチンに入っていないので、一番面倒なのが食事。平日は朝食だけ用意すれば良い。もともと延長保育にしてもらっているので昼食・夕食は保育園で出してくれる。休日はまだ考えてない。
洗濯ものは自分と子供だけなら洗ったものを着るという単純ローテできるので、実用上は別に仕舞う必要がなく、洗って乾燥したのを出しておくだけでなんとかなる。もともと洗濯・乾燥まではルーチンに入っているので困ったことは起きない。
掃除はもともと気になったときにしかやってないので負荷は増えない。床面はルンバがある程度綺麗に保ってくれる。あとはコードレス掃除機でさっとやるぐらい。
子どもは習いごと、勉強を見るのがそこそこ時間をとる。
まぁもう5歳になると結構聞きわけある年齢だし、やることやったら何やっててもいいルールにしていると、一人でゲームやったりして、その間は手があけられるのはありがたい。事情を話せばある程度はわかってくれるし、なんなら洗濯物とかを手伝ってくれてありがたい。
前回 に引き続き NiZ のキーマップをごにょごにょする。
とりあえず表題の通り、キーマップの書きかえまではできた。
#!/usr/bin/env ruby
require "./niz.rb"
require 'progress_bar'
override_mapping = lambda do |mapping|
# mapping[level][key_id] = hwcode
# level:
# 0: normal
# 1: Right Fn
# 2: Left Fn
# key_id: 1-66
# hwcode: See ./niz.rb HWCODE constant
mapping[0][61] = 68 # Set key_id 61 (right side of space) = 68 (super)
mapping[0][62] = 71
mapping[0][63] = 74
end
#################################################################
niz = NiZ.new
Timeout.timeout(1) do
begin
niz.open
rescue => e
$stderr.puts "#{e.inspect} retrying open device..."
retry
end
end
puts "Version: #{niz.version}"
puts "#{niz.keycount} keys"
puts "Reading key mapping..."
progress = ProgressBar.new(niz.keycount * 3)
read_all = niz.read_all do |count, keymap|
progress.increment!
end
mapping = NiZ.mapping_from_array(read_all)
override_mapping[mapping]
puts "Writing key mapping..."
progress = ProgressBar.new(niz.keycount * 3)
niz.write_all(mapping) do |count|
progress.increment!
end
キーマップの書きかえコマンドを送ると、まず既存のキーマップが全てリセットされるみたい。つまり、プロトコル的には一部のキーだけを書きかえということはできない。常に全部のキーマップを送信する必要がある。
なので、一部の書きかえを実現したいのであれば、
という手順になる。
NiZ は内部的にキーに対応する数値を HWCODE という名前で持っている。このコードは USB HID の scan code や、multi media キーや、その他いろいろな機能キーを一意に特定するものになっている。HWCODE は ASCII や Usage とまったく別の規則で割り当てられているようで、マッピングは気合で作るしかない。
気合で作るしかないので、おおむね作った。https://github.com/cho45/niz-tools-ruby/blob/master/niz.rb#L13 ということで、ここを読んでいる良い子のみんなは気合を入れる必要がなくなった。
自分で使わないのでまったく調べてない。マクロ登録用のコマンドがあるっぽい。
CorvusSKK にしてみた。Ctrl-SPC で IME のオン・オフをしたいので、設定する。
「キー0」タブが IME の ON/OFF 用のキーを設定する画面になっている。スペースキーは 0x20 なので、0x20 と入力して修飾キーとして CTRL を選択し、ON と OFF それぞれについてキーを追加する。
順番にどういう意味があるかわかってないけど、一応一番上にしておいた。こういう感じに。
https://play.google.com/store/apps/details?id=jp.kcm.thumbctrl.en.layout これを入れて、レイアウトから Caps Lock -> Ctrl 置き換えする。いろいろレイアウトが追加されるけど、とりあえずこれで良い。
http://ray-mizuki.la.coocan.jp/software/skk_jp.html SKK for Android を apk から入れて、設定する
これでほぼ違和感なく入力できる。ただ、SKK for Android には RET したとき改行しない設定がないので、ちょっと気をつけて入力する必要がある。
JRE込みのPyCharmで日本語入力がおかしい · Issue #24 · codefirst/aquaskk · GitHub この問題と同じだと思う。
どうも JDK のバージョンによって変な挙動になるらしい。ので、Android Studio の bundled JDK を使うのをやめる。
Selecting the JDK version the IDE will run under – IDEs Support (IntelliJ Platform) | JetBrains この手順に従う
Shift 連打とかで Choose Runtime... のダイアログを出す。
適当に 1.8.0 の JDK を選んで Install ボタンを押すと勝手に再起動する。
これでおわり。
なんとなく AdoptOpenJDK 11 を入れて指定したら、起動しなくなってしまった。起動しないので Choose Runtime も使えない。
macOS の場合 ~/Library/Preferences/AndroidStudio3.5 以下に設定ファイルがある。~/Library/Preferences/AndroidStudio3.5/studio.jdk というファイルがあるので、これを消せばデフォルトの JDK に戻すことができる。
Capacitor をつかって NanoVNA-Web-Client を Android アプリ化してみた。
あんまりハマりどころはなかったのでそれほど書くことはないけど、いくつかメモ。
アプリサイズを減らすためにできるだけリソースを減らす必要がある。node_modules 以下を雑に入れると数十MBになってしまうので、気をつける。
Web 版のリソースを完全にそのまま入れるより、必要なリソースだけをコピーするようなビルドスクリプトを書いたほうが良さそう。今回は Makefile でなんとかした。
Ionic のブログに Photoshop template があるので、これを利用させてもらう。
が、ブログの通り cordova-res を使うとうまくいかなかったので、Makefile と ImageMagick でなんとかした。
res: convert images/splash.png -gravity center -resize 480x320^ -extent 480x320 ./android/app/src/main/res/drawable/splash.png convert images/splash.png -gravity center -resize 800x480^ -extent 800x480 ./android/app/src/main/res/drawable-land-hdpi/splash.png convert images/splash.png -gravity center -resize 480x320^ -extent 480x320 ./android/app/src/main/res/drawable-land-mdpi/splash.png convert images/splash.png -gravity center -resize 1280x720^ -extent 1280x720 ./android/app/src/main/res/drawable-land-xhdpi/splash.png convert images/splash.png -gravity center -resize 1600x960^ -extent 1600x960 ./android/app/src/main/res/drawable-land-xxhdpi/splash.png convert images/splash.png -gravity center -resize 1920x1280^ -extent 1920x1280 ./android/app/src/main/res/drawable-land-xxxhdpi/splash.png convert images/splash.png -gravity center -resize 480x800^ -extent 480x800 ./android/app/src/main/res/drawable-port-hdpi/splash.png convert images/splash.png -gravity center -resize 320x480^ -extent 320x480 ./android/app/src/main/res/drawable-port-mdpi/splash.png convert images/splash.png -gravity center -resize 720x1280^ -extent 720x1280 ./android/app/src/main/res/drawable-port-xhdpi/splash.png convert images/splash.png -gravity center -resize 960x1600^ -extent 960x1600 ./android/app/src/main/res/drawable-port-xxhdpi/splash.png convert images/splash.png -gravity center -resize 1280x1920^ -extent 1280x1920 ./android/app/src/main/res/drawable-port-xxxhdpi/splash.png optipng $(wildcard ./android/app/src/main/res/*/splash.png)
リリースしたことある気がしていたが、よく考えたら前職で数回やっただけなので個人のアカウントではやったことがなかった。いろいろストアの使い勝手が変わっていた。
無料アプリの開発者視点からすると、別に Play Store に出すメリットはぜんぜんない。他の端末にさくっと入れたいときに便利かな、と思う。けど、それも普通にウェブサイト経由で .apk ダウンロードして入れればいいだけなので、それほど致命的に面倒くさいわけではない。まぁ Play Store のショバ代は初回に $25 なので Apple (毎年$99もとる) よりは格段に優しいといえる。
NiZ のアプリケーションは Windows 向けしかない。プロトコルが気になったので、とりあえず打鍵回数を読み出すところをまでをやってみた。環境は macOS で hid_api gem を使い、Ruby で書いた。
実行するとこういう出力をする。最後の数字がキーに対応するカウント。
key= 1 hwcode= 1 ESC: 35 key= 2 hwcode= 15 1: 66 key= 3 hwcode= 16 2: 92 key= 4 hwcode= 17 3: 114 key= 5 hwcode= 18 4: 119 key= 6 hwcode= 19 5: 53 key= 7 hwcode= 20 6: 99 key= 8 hwcode= 21 7: 18 key= 9 hwcode= 22 8: 115 key= 10 hwcode= 23 9: 76 key= 11 hwcode= 24 0: 171 key= 12 hwcode= 25 -: 307 key= 13 hwcode= 26 =: 78 key= 14 hwcode= 41 \: 38 key= 15 hwcode= 14 `: 33 key= 16 hwcode= 28 TAB: 575 key= 17 hwcode= 29 Q: 253 key= 18 hwcode= 30 W: 627 key= 19 hwcode= 31 E: 1461 key= 20 hwcode= 32 R: 911 key= 21 hwcode= 33 T: 1137 key= 22 hwcode= 34 Y: 616 key= 23 hwcode= 35 U: 1317 key= 24 hwcode= 36 I: 1662 key= 25 hwcode= 37 O: 1536 key= 26 hwcode= 38 P: 549 key= 27 hwcode= 39 [: 584 key= 28 hwcode= 40 ]: 41 key= 29 hwcode= 27 BS: 1662 key= 30 hwcode= 67 L-CTRL: 18 key= 31 hwcode= 43 A: 1794 key= 32 hwcode= 44 S: 914 key= 33 hwcode= 45 D: 853 key= 34 hwcode= 46 F: 249 key= 35 hwcode= 47 G: 520 key= 36 hwcode= 48 H: 828 key= 37 hwcode= 49 J: 671 key= 38 hwcode= 50 K: 1424 key= 39 hwcode= 51 L: 696 key= 40 hwcode= 52 ;: 452 key= 41 hwcode= 53 ': 155 key= 42 hwcode= 54 RET: 1281 key= 43 hwcode= 55 L-Shift: 1610 key= 44 hwcode= 56 Z: 177 key= 45 hwcode= 57 X: 128 key= 46 hwcode= 58 C: 459 key= 47 hwcode= 59 V: 253 key= 48 hwcode= 60 B: 384 key= 49 hwcode= 61 N: 1352 key= 50 hwcode= 62 M: 482 key= 51 hwcode= 63 ,: 383 key= 52 hwcode= 64 .: 255 key= 53 hwcode= 65 /: 161 key= 54 hwcode= 66 R-Shift: 850 key= 55 hwcode= 156 R-Fn: 135 key= 56 hwcode= 67 L-CTRL: 1653 key= 57 hwcode= 166 L-Fn: 6 key= 58 hwcode= 69 L-Alt: 35 key= 59 hwcode= 68 Super: 703 key= 60 hwcode= 70 Space: 2037 key= 61 hwcode= 68 Super: 7 key= 62 hwcode= 71 R-Alt: 5 key= 63 hwcode= 74 R-Ctrl: 5 key= 64 hwcode= 88 Left Arrow: 24 key= 65 hwcode= 89 Down Arrow: 19 key= 66 hwcode= 90 Right Arrow: 34 key= 67 hwcode= 0 : 0 key= 68 hwcode= 0 : 0 key= 69 hwcode= 0 : 0 key= 70 hwcode= 0 : 0 key= 71 hwcode= 0 : 0 key= 72 hwcode= 0 : 0 key= 73 hwcode= 0 : 0 key= 74 hwcode= 0 : 0 key= 75 hwcode= 0 : 0
すべて HID 上で行われる。64bytes 固定で read/write する。
日本語で説明するよりソースコード読んだほうが早いので説明するのをやめる。
NiZ キーボード側から、現在のキーマップを取得する。66キーのモデルなので、66キー × 3レイヤー (ノーマル・左Fn・右Fn) で 198 個の論理キー定義がある。
これによって、キーID (1〜66) と、割当られているキーコード (.pro ファイルの HWCODE) のマッピングを得られる。
カウントは66個の数値の配列のようなものが得られる。インデックスがそれぞれキーIDに対応していると思われる。
インデックスからキーマップを得てカウントと共に表示すればおわり。
macOS だからか、実装が悪いのか、どこが悪いのかわからないが、挙動が不安定
何回か繰替えすと成功する。
hid_api は timeout のメソッドがあるにも関わらず timeout の処理が抜けているので、モンキーパッチを書いてる。PR 作ろうかと思ったけど結構放置されてそうでめんどい。
read した形式で書き戻せばいいだけだと思う。
Windows に USBPcap を入れて、公式のアプリケーションを操作しながらログをとった。
あとは気合
https://github.com/cho45/niz-tools-ruby github にうつしました
>
(この写真のキー配列はデフォルトのものではなく、既にカスタマイズ済みです。mac 用のキーキャップが付属しており、HHKB を基準にできるだけキーキャップもあわせています)
https://www.nizkeyboard.com/ が公式っぽい。中華製の静電容量無接点キーボード (HHKBやRealforceなどと同じ分類)。
HHKB と比べると以下のような特徴がある
価格が安いだけなら買うつもりはなかったけど、キーが HHKB よりも軽くて Bluetooth 接続が可能で、Type-C 接続な点で気になった。66キー(HHKBとほぼ同じ大きさ) 35g のモデルを買ってみた。スペック通りなら HHKB 信者を止めることになる。
デフォルトだと「Office モード」というモードらしく、キーのリマップが効かないモードになっている。 Fn+M キーを同時に2秒押して Program モードというモードにしなくてはいけない。
専用アプリを使ってのキーカスタマイズはこのモードでしか適用されない。
試しうちしてすぐ気付いたが、左 Ctrl (というか位置的には Caps-Lock)、スペース、RET、Shift が叩くように入力しないと反応しない、または普通に使っていて入力をとりこぼすことがわかった。
https://www.nizkeyboard.com/2019/07/07/some-keys-doesnt-work-look-at-this/ 公式にこういうエントリがあるぐらいなので頻出問題みたい。手順では F2 F10 を押しながらキャリブレーションすると書いてあるけど、単に基準となるキーが変わるだけで、どのキーを押しながらでもキャリブレーションできる。自分の場合は左 Shift + スペースを軽く押しながらキャリブレーションすることで、気になる範囲の取りこぼしはなくなった気がする。
市販のキーボードは「普通に動く」けれど、それはもうそれだけですごいのだ、ということに気付く。キーボードの信頼性というのはそこで、普段意識するようなことはない。最低限ちゃんと思った通りに入力できなければならない。
NiZ は(自分の場合は)キャリブレーションなしには全く使いものにならないものだった。普通に考えたら初期不良だし、キーボードをキャリブレーションしたらなおるとか思いもしないだろう。そういう初期調整も含めての安価な値段だと思う。
良い点は冒頭でもほとんど記したけど
とかいろいろある。このキーボードにしかない特徴があるので、うまくキャリブレーションするか、あたり個体を掴めれば良い選択かもしれない。
とりあえず普段遣いできる感じのキャリブレーションはすることができたので、しばらく使ってみるつもり。
USB デバイスとしては `ID 0483:512a STMicroelectronics 66EC-S ` で認識されている。STM32 っぽい……と言いたいところだけど、中華デバイスは STM32 互換の MCU に STM32 のツールで作ったファームウェアを書いていたりするので、これだけでは判断できない。
JTAG も SWD も CPU 内部のレジスタを読み書きすることで、CPU 側にある任意の機能を呼び出している。なので、デバッグプロトコルは JTAGとSWDの上に乗っており、CPU によって異る。
(高級な print デバッグを想像するとよい。が、自分は使ったことがないのでわからない)
USB から CMSIS-DAP を使って JTAG/SWD を操作し、CPU 内部の CoreSight に接続する、という感じ。
このへんややこしいが、「SERGGER J-Link」はデバッガハードウェアの名称でもあり、USB 接続時のプロトコルでもある。
ST-Link も同様で、ST-Link2 ST-Link3 というデバッガハードウェアもあるし、USB 接続時のプロトコルでもある。
LPC-Link2 は USB 接続時のプロトコルとして SEGGER J-Link / CMSIS-DAP / Redlink (nxp の独自プロトコル) を切り替えられるボード。
結局どのプロトコルでも、同じCPUならできることは一緒。だが、ホスト側のドライバの関係でパフォーマンスに違いがでることがある。
https://github.com/GoogleChromeLabs/comlink
「Comlink makes WebWorkers enjoyable.」と書いてあるが、キモは postMessage の抽象化なので、iframe 間通信にも使用することができる。ただ、origin の取り扱いをする必要があるので、ラッパーが必要。といってもラッパーも Comlink.windowEndpoint() という形で Comlink 自身に用意されている。
iframe の親でも小でも、どちらでも Comlink.expose することができる (役割は反転できる)。ただ、その際に該当する window インスタンスが必要なので、iframe の親側では小フレームのロードを待たなければならない。
Cordova は file: で実行される。Capacitor は http: (Android) で実行される。
この違いは案外大きい。ESM (type="module" などでロードされる ECMAScript Modules) は application/javascript でなければ実行されないという厳格なルールがあるが、file:// ではすべてのファイルに mime-type が設定されないため、実行できない。回避する方法は結局のところ localhost にサーバを立てるぐらいしかない。この点だけでももう Cordova は厳しい。
Cordova はビルド時に必要なソースコードを生成する。このため実際のビルドは必ず cordova コマンドを介す。
Capacitor はソースコードのスキャフォルドを最初に生成する。レポジトリには各プラットフォームの完全なプロジェクトが生成される。このため、実際のビルドは Android Studio や Xcode など、ネイティブな環境で行われる。