0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google AI StudioだけでAndroidアプリを作ってみた

0
Posted at

この文章は本人が書いています。AIは使っていません。多分疑われないだろうけど。
なお、私はAndroidプログラマー歴15年くらいになります。
また、AIコーディング経験はほぼ無く初心者です。Geminiを使って、これまで自分で検索していたような内容を直接投げるとか、クラス設計の壁打ちだったり、単純なenumは作らせたり、エラーログ貼り付けて対応策聞いてみたり、あとは作業で必要なシェルスクリプトは完全に任せたり、その程度はしたことがある、という感じです。

やろうと思ったきっかけ

私は朝が大変苦手です。アラームのスヌーズも全て止めきって二度寝、三度寝はザラにあります。起きてから「声を出せば目が覚めやすいのでは」という感覚があり、アラームを声で止める、「合い言葉アラーム」をずっと作りたいと思っていました。
しかし、サンデープログラミングをするほどの熱意や時間はもはやない。ということで、数年、あったらいいなーと思いつつ何もしないでいました。
ちょっと時間が出来たときにAIコーディングについて調べていて、Google AI StudioでAndroidのアプリが作れるようになっていると知り、これは試してみるのに最適な題材ではないか?と考えてトライしてみることにしました。

やったこと

・Google AI Studioに日本語だけで指示してAndroidのアプリを作ること
・Webエミュレータ上での動作確認
・実機をUSB接続しての転送、動作確認

やらなかったこと

・ドキュメント制作(要件定義、仕様書、etc...)
・コードレビュー
・Unit及びUIテスト実装の指示(どうやるかこれから検討する)

使ったもの

Google AI Studio(無料版)
実機(Pixel 7a)

アプリ概要

事前に設定した言葉・文章(今後"フレーズ"と呼称します)を音声認識して一致したら止めるアラームアプリ。
完全ローカルオフラインで動くアプリ。

感想だけ知りたい方は感想総評簡単なまとめあたりをお読みください。

AIへの指示詳細

1.初回プロンプト指示内容

特にセキュリティもないと思うので全部晒します。
初回に投げるプロンプトとしては長いかなと思いましたが、長年構想はしていただけに要件は細かく決まっていたとも言えます。これが功を奏して1発目の仕上がりが大変良質になったと思われます。

・シンプルなアラームアプリを作りたい 
・アラームを止めるのは音声入力で、事前に設定した言葉と一致するかどうかで判断します 
・スヌーズは不可にしてください 
・止めるための音声認識画面ではアラーム音は小さくし、バイブは止めてください 
・設定画面では「アラーム音」を選択できるようにしたいです。音量も変更できるようにしてください 
・設定画面ではバイブのオン・オフが出来るようにしたいです。振動パターンは固定で良いです 
・アラームの設定は「日時」と「曜日繰り返し」の設定が出来るようにしたい 
・アラームの設定は1つだけで良いです。複数の時間設定を保持しません 
・アプリのテーマカラーは落ち着いた青~紫の間の色にしてください 
・UIはシンプルなマテリアルデザインにしてください 
・アラームはバックグラウンド再生にしません 
・アラーム画面には「止める」ボタンがあるが、これは音声認識を起動するので、マイクのようなアイコンにしてください。 
・アラーム画面には現在時刻を表示してください 
・音声認識画面では、認識した日本語がリアルタイムで画面上にテキストとして表示されるようにしてください 
・音声認識画面では、音声入力が1分間行われなかった場合、自動的にアラーム画面に戻ってください。その際、音量と振動を戻してください 
・音声認識に成功した場合のみアラームを停止できるようにしてください、ただし成功判断は「指定された単語・文章」を認識した時のみとする。また、認識成功の判定ワードと精度は設定画面でカスタマイズ可能にしてください。

まず、プロンプトを入力中に驚いたことは、「この機能、設定が必要では?」というプロンプトの提案がかなり的確に随時出てくることです。
上部のプロンプトで、丁寧語になっている部分は、ほぼ、Google AI Studio自身が提案したプロンプトそのままです。(一部違うものもあります)
「アラーム」「音声認識」の提案だけで、実は基本的に必要な要件というのは定まってしまうものなのだなと感じました。人間が言語化するのに時間がかかる部分が、AIによって短縮されてしまうというのを実感した事案でした。
逆に、そういった部分をAIが代替(だいたい)してくれることで、人間の言語化能力が低下していかないか心配にもなります。

2.初回ビルド

702秒=11.7分で完了しました。
ただし、この時点で複数のデザインを提案してきますので、それの分を含んでいると思われます。
Web画面上でプレビューが出来ましたが、メイン画面のみ参照できました。

私が1人で実装していたら、多分2週間は掛かったでしょうから、驚異的な早さです。

Google AI Studioからは、実装完了報告とともに、簡単な要件定義書のようなものが返答で返ってきます。これは「要件定義書として整えて」と指示したらもっとそれっぽくなるかも知れませんが、その部分はChatGPTとかのほうが向いているかなと思ったので今回はやりませんでした。

以下、返答分の抜粋です。


音声認識でアラームを解除する目覚まし時計アプリ 「Voice Alarm」 の実装が完了しました。
UI・UX設計、データベース設計、音声認識および安全な設計を徹底し、快適で実用的なマテリアル3アプリケーションを構築しました。

🎨 主な機能と実装内容

  1. 穏やかなコズミック(青〜紫)デザインテーマ
    • 落ち着ち着いた夜空や睡眠をイメージした、鮮やかで優しいインディゴブルーからマイルドパープル(PrimaryBluePurple & SecondaryLavender)のテーマカラースキームを採用。
    • Material 3対応のダイナミックカラーは意図的にオフにし、常にこのリラックス効果の高いカラーパレットで描画されるよう固定しています。
    • 画面間の切り替え(クロスページナビゲーション)には、滑らかに連動するフェードイン・フェードアウトのアニメーション(200ms)を適用。
  2. 堅牢な Room ローカルデータベース永続化
    • 設定は1つのみ保持する仕様に準拠。AlarmSettings エンティティは、日時設定、繰り返し曜日設定、アラーム音の種類、音量、バイブレーションの設定状態、停止判定ワード、判定精度(しきい値)などをすべて保持。変更はすべてリアルタイムで自動保存されます。
  3. スマートなアラーム時刻設定(日時 & 曜日繰り返し)
    • 曜日繰り返し(月〜日): 繰り返したい曜日を丸いチップで直感的に複数選択でき、選択された曜日の中で直近のトリガー時刻を自動算出。
    • 日時指定: 曜日を繰り返さない一回限りの日時でも、ネイティブの DatePicker / TimePicker を使用して安全に設定可能。
  4. 100%端末内で完結するシンセサイザー音源&バイブレーション
    • アラーム音の種類:
      • 和風チャイム (CHIME_SYNTH): 起床を促す優しい arpeggio メロディ。
      • デジタル電子音 (BEEP_PULSE): 連続するダブルアップ・電子ビープ音。
      • 瞑想風シンセ (ZEN_MEDITATION): 深い睡眠から徐々に起こす緩やかな波。
    • 実機・エミュレータどちらでも外部音源ファイル破損によるエラーが発生しないよう、Androidの AudioTrack APIを用い、端末内でコルーチンにより高音質な音波(サイン波)をリアルタイム合成(シンセサイズ)し再生。スヌーズは不可に制限しています。
  5. 音量の急低下 & バイブ強制オフ仕様 - アラーム鳴動画面からマイクアイコン「話して止める」をタップすると音声認識画面へ推移。
    • 推移すると同時に、認識処理を妨げないようにアラーム音量が即座に元の 15% に低下し、バイブレーションが完全に強制停止されます。
  6. リアルタイム日本語判定 & 60秒自動タイムアウト
    • 音声認識画面(Speech-to-Text)では、マイクが聞き取った日本語をリアルタイムで中央のボードに大きくテキスト表示。
    • 音声入力が1分間行われなかった場合、自動的にアラーム画面(鳴動中)に引き返します。これに伴い、アラーム音量も元の大きさに戻り、バイブレーションも自動的に再開されます。喋るたびに自動でタイマーが60秒にリセットされるため、判定に手戻りがあってもスムーズに喋り直せます。
  7. 音声の高度なあいまい一致(Levenshtein & 部分一致判定)
    • ただの文字列の完全一致だけでなく、マイクが話者の語尾(「アラーム停止してください」などの言葉の前後)まで聞き取った状況も考慮。
    • 部分一致(Containment チェック) と、文字の微細な聞き取りエラーを解消するローカルなレーベンシュタイン距離(Levenshtein Distance)アルゴリズム(50%〜100%の設定可能な認識精度) を組み合わせた高度な親切判定。
  8. 【検証用】シミュレーター内蔵(オフライン検証が可能)
    • エミュレータやマイクの権限が無い環境でも挙動をテストできるよう、音声認識画面の下部にテスト用のテキスト入力&送信欄を標準搭載。「アラーム停止」など任意の文字を送信して、指定のしきい値での停止判定が正しく機能するか簡単に確認可能です。

(返答分抜粋ここまで)

アラーム音は、サウンドトラッカーで選ばせる想定でしたが、勝手にシンセで音を作ってくれました:grin: これは面白いのでそのままにすることに。

また、音声認識や精度の制御はまったく知見が無いので、もう完全にお任せです。特に「7.音声の高度な曖昧一致」に書かれている内容は「ふむふむほうほう」という感じで、そんなアルゴリズムがあるのかと感心すると同時に、そういう所まで考慮が必要だったのかという気づきにもなりました。この時点で、どんなライブラリ使っているのだろうかとか、コードを覗くのが楽しみになっています。

「8.検証用シミュレータ内蔵」の項目は、完全に想定外の「マイクの権限が無い環境」という点に関する考慮で、いわゆる「要件漏れ」に該当しますが、これを拾うのはすごいなと思いました。

3.デザイン選択

メイン画面のUIデザインが7種類くらい提案されました。
この時点で、ラベルが英語のみのものや逆に日本語のみのものがあったり、混ざっていたりするものもあるなど、なんかバラバラでした。
なので、デザインを選択した後で「日本語のみにして」という指示が必要そうだなと把握しました。

デザイン選択にはボタンが用意されているので、それをクリックするだけです。
ボタンをクリックすると以下のような指示が自動的に送られます。

Apply the "Sleek Interface" design theme to the app.

英語のプロンプトだったので、返答も英語で返ってきます:sweat:


I have applied the Sleek Interface design theme to the Voice Alarm application:
(以下略)


なお、最後に

All unit and screenshot tests are compiling and passing successfully.

とも返ってくるのですが、これは信じない方がいいです。
というか、確かに嘘は言っていないのですが、作成されたテストというのはAndroidStudioでプロジェクトを新規作成したときにデフォルトで作成される"ExampleXXXXTest"しかないからです。
私は当初、「へえ~テストも自動で作ってくれるんだ」と思っていましたが、途中でファイル全体を確認したときに「ExampleTestしかないやんけ!」とずっこけました:joy:

4.指示の追加と修正

さきほど気付いたように、「日本語だけにする指示が必要だな」とか、いろいろ追加や修正の指示をしました。

・アプリ名は「合い言葉アラーム」にしてください
・各ラベルは日本語にしてください。言語選択機能も不要です。
・アラームを止めるための単語・文章は、事前に3つ登録でき、リストで確認・編集・削除が出来るようにしてください。また、使用するフレーズを、「1つ選択して固定」と、「登録された中から毎回ランダムで使用」のどちらかを選べるようにしてください。
・ランダムで選ぶ場合、前日と同じになっても大丈夫です。

これも問題なく実装してくれましたが、このとき、Web上のエミュレータの実行ログに「エラー」が数件出ているのに気付きました。
その時点で、

Fix the errors in the app

というプロンプトを送りますか?という提案が自動的に出ています。
なのでそれを何度かクリックし、やっとエラーが0になったところで、実機に転送して動作確認してみることに。

なお、出ていたエラーの大半は、AppOps Attribution Issueといものでした。設定が推奨されるattributionTagが付いていない、という指摘のようですが、これは、余りに出過ぎるので途中でAI自身が"これはノイジーな警告だ"と判断しているのが笑えました:laughing:

それ以外には、EXACT_ALARMを使ってないというエラーもありました。この点は、人間が作っていれば真っ先に付与するはずのものなので、そういった「アラームアプリなのだから確実な時間で起動できないとダメだよね」という"連想"が、まだAIには無理なのかなあという感触ですね。

5.実機転送と確認

転送は簡単、USBケーブルでAndroidスマホとPCを繋ぎ、"Install"ボタンをクリックするだけ。
親切に「開発者オプション」を有効にする手段まで表示してくれます。(ただし英語)

実機で実際に動かした結果、いくつか気になった点が。

(1) アラームのテスト画面で中止する手段が無い
(2) システムの戻るボタンで、「前の画面」に戻れない
→私がAndroidを重用する一番のメリットなのでここは譲れない
(3) 設定したフレーズが長い文章のときに、画面が見切れている

これらを順番に修正するよう、複数回に分けて指示しました。

(1) に対するプロンプト:

アラームのテスト起動後、入力を中止してメイン画面に戻れるようにしてください

ここから、指示が日本語だったにもかかわらず返答が英語になる現象が。
まあなんとか読めるのでそのまま進めます。


Added an elegant red-accented 「入力を中止して戻る」 (Cancel Input & Return) button directly under the main "話して止める" button.


結果として、「入力を中止して戻る」ボタンを追加してくれました。
しかもちゃんと注意を引きやすいように赤めの色に設定してます。

6.ロールバック(前の状態にリストア)できる

さて、次に(2)の戻る動作に対する処理を追加させます。

(2)に対するプロンプト:

戻るジェスチャーやシステムの戻るボタンで、「入力を中止して戻る」ボタンと同じ挙動をするようにしてください

この指示は結果として失敗でした。
よく分からないところにBackHandlerによる処理が追加されていたためです。

(この辺りから、Googleの返答が英語だった場合に、実際にコードを見て確認する、ということを始めています。コードの確認もプレビュー画面で"Code"をクリックするだけ。Githubのようなファイルエクスプローラが表示されます)

また、「入力を中止して戻る」ボタンが、実際のアラーム鳴動画面にも表示されていて、押すとアプリが終了してアラームも止まってしまうことに気付きました。

ここで便利なのが、Google AI Studioにはロールバック=以前の状態に戻す機能があることです!
"Restore"ボタンを押すだけ。
これで今の指示は無かったことに戻ります。

改めて、次の指示を。

アラームのテスト起動画面は設定画面と同様にナビゲーショングラフに載せて、「前の画面に戻れる」ようにしてください。
ただし、実際のアラーム画面では戻れてはいけません。

ここで、私は1つ勘違いをしていました。設定画面から、戻る操作で前の画面に戻れると思い込んでいたのです。それは左上に戻るナビゲーション(左向き矢印アイコン)が表示されているから。
Navigationが使われていると思っていたのです。
しかし実際には使っていないので、AIはそこを完全に見なかったことにしたようで、結局BackHandlerを使った実装を押し通してきました。

AIは、BackHandlerを使って戻る操作に対応するのと、アラーム鳴動画面では「入力を中止して戻る」ボタンを非表示にする、という対応をしてきました。
ここで、私は「テスト画面と、実際のアラーム鳴動画面は同じScreenを使い回しているのだ」と気付きます。

まあ、それはそれでいいか・・・と、次の指示に進みました。
多分、今後さらに複雑な画面構成になることが分かっているなら、この辺でNavigationをつかって作り直す指示が必要になってくるかと思われます。

7.スクロール追加

(3)の修正に関して、指示するのはいくつか方向性があると思います。

  1. 「見切れることがあるので修正して」とだけ指示する
  2. 通常、解決策としては簡単なのが「全体を縦スクロール可能にする」なので、それだけ指示する
  3. 「見切れの原因」は情報として同時に与えたうえで、「直して」とだけ指示する
  4. 「見切れの原因」と「縦スクロール可能にして」と修正方針を同時に与える

それぞれ試してみても良かったのですが、自分がバグ報告として単に「見切れることがある」と言われるより、「ここが長いフレーズだと」と条件が分かっている方が作業が早いし、対処法も分かっているので、4のどちらも指示する方向にしました。
(今となっては、「直して」とだけ指示したときにどんな手段をAIが取ったかは興味はありますね。)

(3)に対するプロンプト:

フレーズが長い文章の時、アラーム画面の下部が見切れます。アラーム画面全体を縦にスクロールできるようにしてください

期待通り、全体を"verticalScroll"にしてくれたうえで、必要なレイアウトの再構成までやってくれました。

なお、エラーログが度々出るので、適宜"Fix the errors in the app"を指示しています。
そのためか、AIの返答が英語になったり、日本語になったり、時には混ざっていたり(概要は英語なのに、詳細が日本語とか)、なんとも面白い現象が起きます。

8.システムUIとのかぶりを修正

実機に転送していろいろ動作確認しているうちに、ようやく「設定画面からも戻る操作で前の画面に戻れない(アプリが終了してしまう)」ことに気付きました:sweat:
また、システムボタンが表示されているとアプリのUIと重なってしまうことにも気付きました。

修正指示のプロンプト:

・設定画面から、スワイプジェスチャーやシステムの戻るボタンで前の画面に戻れるようにしてください
・音声認識画面の下部が、システムUIの表示がONの場合に重なってしまっているため、適切な設定、または余白を追加してください

今回も、不具合の条件を提示してあげます(システムUIの表示がONの場合)。ただし、修正方針に関しては単に「適切に設定して」とだけ指示しました。
結果として、AIは

.navigationBarsPadding() 修飾子を追加適用

をしてくれました。
これでシステムボタンを表示する派の私でも快適に操作ができるようになりました。

これ、システムUIを使わない人が多いらしく、実際の仕事の現場でも起きやすい現象なので、注意したいところです。多分iPhone使いの人が設計・実装するから、そもそもシステムUIを表示する場合の検証が行われないまま進んでしまうことが多いんですよね。
自分は必ず表示して使うので、いつもせっせとこれ周りの不具合を発見しては報告して自分で修正しています:smirk:
とりあえず、今後AIに実装させる場合、最初や画面実装させる度に毎回、「システムUIと重ならないようにしてね」という指示は付けておく必要がありそうです。

9. データベース(Room)マイグレーション

その後、いくつかオプション追加や音声認識精度の見直しや認識エラーの表示などUI改善を指示しました。
結果としてかなり実用に耐える出来になりました。
メモリーリークなどに気付いて自分で改修してきたあたりはさすがでした。

ただ、オプションを増やした時点で、データベースに破壊的変更が行われていました。
既存データもそのままドロップしていたので、マイグレーションをちゃんとするよう指示しようと思い、まず以下のようにプロンプトしました。

Databaseバージョンアップが必要なとき、登録済のフレーズが消えないようにしてください

すると、AIは一度データをSharedPreferenceにコピーして復元するという力技を持ってきました。
さすがに有り得ないなーと思い、ロールバックしながらいくつか指示をしていきました。
だけどどうしても、「仮のファイルや仮のデータベースを作って1レコードずつ戻す」みたいな実装をしてきます。
それが良い場合もあるのでしょうが、今回はRoomのマイグレーション機能を使って欲しかったので、最終的に以下のように指示したら(個人的に)納得のいく実装をしてくれました。

Databaseバージョンアップが2->3で必要なとき、登録済のフレーズが消えないように、
ちゃんと移行関数を書いてください。

2から3のとき、という指示は無視されて全パターンが実装されましたが、まあそこは有って害があるものじゃ無いので受け入れることにしました。
「移行関数」(マイグレーション関数)をちゃんと書け、というのがやっと伝わった所以かなと思っています。

10. Github連携

なんと、Github連携が出来ます。
実は、途中途中、適宜Githubにコミットをpushしていました。
これもWebページ上で"Share"からGithubを選ぶだけ。Privateリポジトリでも可能です。
コミットメッセージも良きにまとめてくれます。
今回はどうせ全部AIが書いたものだし(=ネット上に公開されているコードを学習して書き起こされたもの)、ということで公開にしています。
こちらにありますので、ご参考までに。

合い言葉アラームサンプル
https://github.com/le-kamba/VoicePasswordAlarm

感想

1. 成果物に対する感想

実際に動かしてみて、個人のアプリとしては、全く問題が無いです。
アイコンがデフォルトアイコンなのでダサいくらい:laughing:
アイコンだけ別の生成AIで作ってもらおうかな。

なお、実際に朝使ってみましたが、とある早口言葉を実際に発声して止めて、そのまま二度寝しました。・・・だめやん:joy_cat:
声を出したところで、眠ければ人は二度寝する。ということで、期待した効果は無かったようです。
これ、自分で苦労してスクラッチで実装した後にこうだったら、ものすごい徒労感だったでしょうね😅ある意味、AIに作らせて試せて良かった。
ランダムで1個認識させるようにしてますが、3個全部言わせる方がいいのかも?🤔と思ってその修正もさせてみましたが、二度寝するのは変わらなかった・・・

2. コード品質に対する感想

まず、最初に書いたとおり、UIテストやUnitテストは一切書いてくれていません。
ここは不満点ですね。
今後これを続きで指示して書いてくれるのか、やってみるかどうか検討中です。
テストを書く前に、一度コード全体をレビューして見てからかな~と思っています。
その方が的確なテスト設計の指示が出来そうなので。

全体的なコードの印象としては、結構良質そうな雰囲気はしています。
何も指示していませんがJetpack Composeで書いている辺りとか、さすがにトレンドを抑えているというか。(いまだにxmlな現場も多い)
音声入力のパーミッションあたりもプロンプトでは全く触れてませんがちゃんと実装されていました。

ざっとファイルツリーを見る限り、MVVM設計はされているようです。
ただし、画面は4つあるはずなのに、ViewModelクラスは1つしかないのが気にはなります。
これは1Activity with Jetpack Composeでは普通なのか?ちょっと判断が付かないので善し悪しの判断は保留にしておきます。(まだそういうプロジェクトに実際に関わったことが無い)

各ファイルをパッと見る限りは、変な実装もしていなさそうですが、詳しくは今後見ていく予定です。
コメントも適宜ありそうな気配ですが、果たしてどうか?

データ構造については、問題が無さそうでした。
「アラーム情報は1個だけで、複数保持する必要は無い」と指示していましたが、結局Room使ってデータベースに保存しており、勝手に拡張性が付与されていました。
まあ恐らく私もそうすると思うので気持ちは分かる、というところ。

文字列がコード内にべた書きなのも、そもそも「言語選択機能は不要」と指示しているので、やむを得ないかな。

このコードをどこか別のAIに食わせてレビューさせてみたらどうなるか?等も興味深いところですね。

kotlinコード以外の部分では、build.gradle.ktsも見てみましたが、結構コメントアウトされているライブラリがあったり、完全オフラインアプリなのにretrofitやokhttpが入っているままになっていたり、ちょいちょい最適化は必要そうな感じです。

総評

とりあえず簡単なものを作ってみた感じでは、凄く良い!
簡単なものの割には、最初にしっかり要件を指示出来ていたのが良かったのかなと思っています。

最初にデザインを選択するところは、実はどれも微妙でしっくりこなかったので、こだわりがある場合はちゃんとUIデザインを経て(人間なりAIなり)、ラフデザインを直接渡す方がいいかと思います。あと、プレビューで選んだものと、実際に動かしたアプリではUIが少し変わっていたので、その辺も注意が必要です。

それと、テスト全然書いてないのに、「テストパスしたのでデグレしてませんよ!」ってめちゃめちゃアピールしてこないで:cry:

続き(モバイルアプリのテストが書けるのか?コードレビューは?etc)はまたいずれ。

簡単なまとめ

出来上がったアプリのコード量
(app/src下で) 2828行(21ファイル)

総経過時間
4時間ほど
しかも、指示した後はビルド終わるまで待つだけなので他のことができる(コーヒー飲んだり洗濯したり)し、AIの作業が終わったら「ピコーン」って音で教えてくれるので気付きやすい。

:thumbsup_tone3:良いところ

  • プロンプトの時点で、必要そうな要件を提案してくれる(足りてない、ではない。既に指示していても同じような提案は出てくる)
  • そこそこ良さそうな品質のコードで実装してくれる
  • Github連携が出来る
  • 簡単に動作確認ができる(Web上のエミュレータ+USB接続の実機)
  • エラーの修正指示が簡単(修正方針が正しいのかどうかは未確認)

:thumbsdown_tone3:良くないところ

  • Google AI Studio自体のUIは現時点(2026/06/05)で英語しかない
  • AIからの返答が英語になったり日本語になったり混ざったりする
  • テストは自動では書いてくれない

※下の2つは、最初のプロンプト次第という気もしますが。

ちょっとした要望
Githubにpushするとき、mainに直接コミット/pushではなく、PR方式にしてくれたら色々便利かもですね~

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?