Android JetpackCompose での OptionMenu - Alternative for OptionMenu in JetpackCompose

Android JetpackCompose で TopAppBar に入れるべく「メニューボタン」をどうするか。

こんな感じになりました。

今現在は、この Box + DropDownMenu でいこうかと思っています。

以下記事から。

A DropdownMenu behaves similarly to a Popup, and will use the position of the parent layout to position itself on screen. Commonly a DropdownMenu will be placed in a Box with a sibling that will be used as the 'anchor'.

DropdownMenu は Popup と同様の動作をし、親レイアウトの位置を利用して画面上に配置されます。DropdownMenu
は「アンカー」として使用される兄弟を持つ Box に配置されます。

👉 android - Jetpack compose popup menu - Stack Overflow hatena-bookmark


@Composable
fun MenuButton() {

  val context = LocalContext.current
  var expanded by remember { mutableStateOf(false) }

  Box {

    IconButton(onClick = { expanded = true }) {
      Icon(Icons.Filled.MoreVert, null)
    }

    DropdownMenu(
      expanded = expanded,
      onDismissRequest = { expanded = false },
    ) {
      DropdownMenuItem(
        onClick = {
          expanded = false
          context.startActivity(
            Intent(Intent.ACTION_VIEW, Uri.parse("https://platform.openai.com/account/usage"))
          )
        }
      ) {
        Text(text = "Usage")
      }
      Divider()
      DropdownMenuItem(onClick = {
        expanded = false
        context.startActivity(
          Intent(Intent.ACTION_VIEW, Uri.parse("https://platform.openai.com/docs/api-reference"))
        )
      }) {
        Text(text = "API reference")
      }
    }

  }

}

こんなところでしょうか。

TopAppBar にセットするなら、以下のように action へ。


TopAppBar(
  title = { Text("Simple TopAppBar") },
  navigationIcon = {
    IconButton(onClick = { /* doSomething() */ }) {
      Icon(Icons.Filled.Menu, contentDescription = null)
    }
  },
  actions = {
    MenuButton()
  }
)

汎用性を上げるなら引数を考慮して、labelaction のペアのリストを渡してループ、などするとよいです。

👉 DropdownMenu | androidx.compose.material  |  Android Developers hatena-bookmark



パスワードどこに保存するか問題

現在使っているデバイス


- Macs
- iPhones
- Androids

「s」がついてるのは複数台という意味。

目標


- クラウド連携
- 自動入力
- ブラウザはChrome
- 無料

ひとつにまとめられないのでモヤモヤしてます。

みんなの考えるベストな方法は?

加えて「2段階認証ワンタイムパスワードジェネレーター」問題も発生しています。

ちなみに、ChatGPT の回答は以下です。

パスワードを保存する方法について、以下のような選択肢があります。

1. オンラインパスワードマネージャーを使用する
オンラインパスワードマネージャーを使用すると、すべてのパスワードをクラウド上で安全に保存できます。代表的なオンラインパスワードマネージャーには、LastPass、1Password、Dashlaneなどがあります。これらのツールは、自動入力機能や2段階認証ワンタイムパスワードジェネレーターのサポートなど、多くの機能を備えています。ただし、一部の機能には有料プランが必要な場合があります。

2. ブラウザのパスワードマネージャーを使用する
Chromeなどの主要なブラウザには、パスワードを保存する機能が備わっています。これらのパスワードマネージャーは無料で、自動入力機能も備えていますが、セキュリティ上のリスクがあるため、2段階認証ワンタイムパスワードジェネレーターのサポートはありません。

3. パスワードを手動で管理する
パスワードを手動で管理する場合、テキストファイルや紙に書き込んで保管することができます。ただし、これらの方法はセキュリティ上のリスクがあり、2段階認証ワンタイムパスワードジェネレーターのサポートもありません。

以上の選択肢から、オンラインパスワードマネージャーを使用することをお勧めします。また、2段階認証ワンタイムパスワードジェネレーターを使用する場合は、Google AuthenticatorやAuthyなどのアプリをインストールして使用することをお勧めします。これらのアプリは無料であり、多くのオンラインサービスでサポートされています。

代表的なオンラインパスワードマネージャーであるLastPassや1Password、Dashlaneでは、無料のプランがありますが、有料のプランの方がより多くの機能を提供しています。ただし、無料のプランでも基本的なパスワード管理機能は使えるため、初めての利用には十分です。

以上の表を見ると、各パスワードマネージャーにはそれぞれ独自の特徴があることがわかります。重要なのは、自分に合ったパスワードマネージャーを選ぶことです。パスワードマネージャーを使用することで、複雑なパスワードを簡単かつ安全に管理することができます。また、二要素認証などのセキュリティ機能を活用することで、アカウントのセキュリティを強化することもできます。

これでいいのかな。



Google Authenticator から secret を抽出する方法

まず、エクスポートから QRコードを表示。

Google Authenticator から secret を抽出する

テキスト化します。



otpauth-migration://offline?data=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※ 登録数が多ければ、XXX.. は、すごく長いです。

それをさらに以下のツールでデコードします。

👉 dim13/otpauth: Google Authenticator migration decoder hatena-bookmark

go を入れるのがだるいので対応するバイナリをダウンロードします。

dim13/otpauth: Google Authenticator migration decoder
👉 Release v0.5.1 · dim13/otpauth hatena-bookmark

どれなのか、良くわからないので、インストール先を調べます。


❯ uname -a
Darwin iMac.local 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64

❯ uname -m
x86_64

otpauth-v0.5.1-darwin-amd64.tgz をダウンロードして展開します。M1+なら「arm64」

先に取得したテキストを渡して実行します。


❯ ./otpauth -link "otpauth-migration://offline?data=XXXXX..."

otpauth://totp/Example%20Company:test@example.com?algorithm=SHA1&digits=6&issuer=Example+Company&period=30&secret=QUU6EA2GHORGMD22SN2YKU6VKISCKYAG
otpauth://totp/Henrik%20Schacks%20blog?algorithm=SHA1&digits=6&period=30&secret=5YGQ4IAR32CYA6PY
otpauth://totp/auth@test.com?algorithm=SHA1&digits=6&issuer=MyCompanyName.AbpZeroTemplate&period=30&secret=MFRDCZDFMQ3DAMDC
otpauth://totp/WordPress:ThinkingTeapot?algorithm=SHA1&digits=6&issuer=WordPress&period=30&secret=S55IFILZLA6DESAO
otpauth://totp/Google:example@gmail.com?algorithm=SHA1&digits=6&issuer=Google&period=30&secret=QJV3EN5JJJHGQ4PK3M6E576YMWUC5D4X
...

これの secret パラメータがそれ。base32 でエンコードされた文字列です。

👉 RFC 6238: TOTP: Time-Based One-Time Password Algorithm hatena-bookmark

他のTOTPジェネレータにも登録しておくと安心できます。

👉 「GitHub」で2要素認証の義務化、3月13日から - ケータイ Watch hatena-bookmark