これまでに発売されたAndroid端末のdp解像度まとめ

はじめに

今年のGooglePlayコンソールのアップデートにより端末カタログという機能が追加されました。 これは以前から存在していた配信対象から特定端末を除外する機能に、端末の詳しいスペックを閲覧・検索する機能が追加されたものです。

GooglePlayコンソールのアプリ管理画面からリリース管理→端末カタログで遷移してアクセスできます。

f:id:nein37:20180102191720p:plain

この端末カタログはDPI値は表示できて便利なのですがDP解像度は記載されていないため、イレギュラーswdp端末を探す目的には若干不便でした。 そこで、端末カタログによって得た大量のデータからGoogle Play コンソールが認識している全端末のdp解像度まとめを作ってみました。

Android端末カタログ - Google スプレッドシート

作り方

端末カタログはAPIなどが用意されておらず、ページ内のリクエストなどをアレして端末情報のリストを探しました。 端末カタログにアクセスした際、1.6MBくらいのjsonレスポンスを受け取っている箇所があり、それが端末カタログの中身になります。 このJSONファイルはほとんどの key が 1 とか 2 なので頑張って解析する必要があります。

以下が端末1件分のデータです。

  {
    "1": "NuAns/neoreloaded",
    "2": {
      "1": "NEO [Reloaded]"
    },
    "3": [
      {
        "1": {
          "1": "NEO2",
          "2": [
            {
              "1": 1080,
              "2": 1920,
              "3": 420,
              "5": "2991501312",
              "6": "3072",
              "7": 25,
              "8": 196610,
              "9": 2
            }
          ],
          "4": "Qualcomm",
          "5": "MSM8953",
          "6": "NuAns",
          "7": [
            "NEO [Reloaded]"
          ],
          "8": true,
          "9": "https://lh3.googleusercontent.com/HLh04wdpYNiMf3WyzBUgJzbcvDb7ZxaMYHOy7Wpp7FaXbeGLbwPakW7MgKpaTns83MmU0FuPAxn_",
          "11": 1,
          "12": {
            "1": 4,
            "2": [
              4,
              5,
              6
            ]
          }
        },
        "2": {
          "1": true
        }
      }
    ]
  },

同一端末であってもOSバージョンの更新などによって別物扱いできるようになっていて、OSアップデートによるデフォルトDPIの変更などもキャッチできそうです。 このあたりはさすがGoogleという感じですね。

解像度やDPIなどの値は特徴的なのですが、フォームファクタ情報などはいろんな端末の詳細ページを見比べながらアタリをつけました。 残念ながら端末発売日や液晶サイズがなく、発売日での絞込やDPI値の乖離チェックができないのが残念です。 液晶サイズに関しては今後のアップデートでぜひ追加してほしいですね。

調査していく途中で、Android端末が スマートフォン、タブレット、ウェアラブル、TV、PC、STB、Auto、その他 という区分にわけられていることがわかったのですが、swdpで区分されているわけでもなく、外見による分類?という感じでした。 一部のファブレットやTV/PCなど分類が難しそうなものもあり、誰がどうやってフォームファクタを判定しているのか非常に気になりました。

このJSONファイルをそれっぽく並べ替えてcsvに変換し、スプレッドシートに突っ込んだものがこちら)になります。

雑感

端末カタログのデータを集計している途中、ノイズがかなり多いのが気になりました。 製造メーカーが不明な端末(OSバージョンによる重複があるため、厳密に端末数ではない)だけで5000台以上あり、本当に世に出ている端末なのかわからないものも多いです。 また、端末の解像度が一桁だったり明らかにおかしいものもあり、開発中の端末かなにかでBuild.MANUFACTURERが正しく入力されていないものも拾われているのでは…という気持ちです。

謎の端末が多く見つかる一方で、国内で流通している端末が見つからないこともあります。 ヘンテコDP解像度で有名な MediaPad T2 7.0 ProPLE-701L という型番ですが、これは名前、型番のどちらで探しても見つかりませんでした。 代わりに Huawei/华为揽阅m2青春版7_0 という端末(型番 hwple703l) という同一画面解像度で同一DPI端末があることがわかり、国内モデルはこれのローカライズモデルかな?と思ったりしました。

もう少し情報が増えてくれれば絞込による謎端末探しが捗りそうなので、Googleさんには頑張ってほしいですね。

スマートフォンタブレットのswdp分布を見てみましたが、やはりスマートフォンでは 320dp, 360dpタブレットでは 600dp, 800dp に大きく偏っていました。 ただし、スマートフォンでは 411dp, 480dp といった情報量の多い端末もそこそこ増えてきているようで、今後はAPIレベルによるswdp分布などもみたほうが良いかな?という気がしました。 タブレットでは768dp端末が600dp,800dpに次いで多くなっていて、 アスペクト比 4:3 端末も意識する必要がありそうです。

今後GooglePlayコンソールの機能が拡張されてスペック検索やdp解像度のチェックができればスプレッドシートも不要になりそうですが、それまでは定期的に更新しようと思っています。

Android端末のGoogleアシスタントから自アプリの検索を呼び出す

本日からGoogleアシスタント対応アプリを日本語で開発できるようになったようですね。 僕も最近 Google Home Mini を購入したので、日本語で使えるアプリが充実してくれると嬉しいです。

developers-jp.googleblog.com

実はAndroid端末のGoogleアシスタントでは、上記のようなGoogleアシスタント対応アプリの他に、端末内にインストールされているアプリの機能を呼び出すコマンドが実装されています。 これはGoogleアシスタントの前身、Google Nowに実装されていた Google Voice Actions という仕組みを利用したものです。 Android Developers の Common Intents ページにはこの Google Voice Actions からのインテントを受け取るための intent-filter 実装例が載っていて、この通り実装することで自作アプリで Google Voice Actions を受け取ることができます。

例として、今回は検索機能を上げてみましょう。

さきほどの Common Intents ページを見ると、search for cat videos on myvideoapp という音声指示で myvideoapp 上で cat videos を検索することができるようです。 内部的には com.google.android.gms.actions.SEARCH_ACTION アクションのインテントが発行され、それを myvideoapp が受けられる場合はアプリがこのインテントで起動され、対応していない場合はウェブ検索にフォールバックされます。 myvideoapp というのは 僕が試した限りでは AndroidManifest<application> タグ、 android:label の文字列と一致していれば認識するようで、いわゆるアプリ名と一致している必要がありました。

<application android:label="アプリ名">
    <activity android:name=".SearchActivity">
        <intent-filter>
            <action android:name="com.google.android.gms.actions.SEARCH_ACTION"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
    ...
</application>

というような定義のアプリケーションがあるとき、 SearchActivity 内で com.google.android.gms.actions.SEARCH_ACTION アクションの Intent から getStringExtra(SearchManager.QUERY) することで Google Voice Actions からの検索アクションを処理できます。 検索結果のActivityが分離されている場合、実装はとても簡単です。

…と、ここまでは良いのですが、アプリ内検索機能はまだ英語版 Googleアシスタントでしか動作しません。 この挙動を試すためには、Googleアシスタントの言語設定(Androidでは端末の言語設定を参照しています)を英語にした上で search for カニ on アプリ名 のようなキーワードを文字入力する必要があります。 幸いAndroidGoogleアシスタントは文字入力を受け付けるので日本語アプリでも呼び出すことができますが、言語設定が英語の場合、日本語アプリ名をもつアプリを起動することはできません。 この仕様は非常に残念ですね…。

しかし、Googleアシスタントが日本語対応した今、「アプリ名 で カニ を検索」のようなキーワードで日本語の端末内アプリ検索がサポートされる日も遠くないでしょう。 きっと他の Google Voice Actions も日本語対応が進んでいくはずです。 その日に備えて、Common Intents や Google Voice Actions の一覧に目を通しておきましょう。

Androidのユーザー補助サービス(Accessibility Service)は楽しい

先日クックパッドで開催された potatotips #42Android のセキュリティよくなってきた話という発表をしました。 Androidのセキュリティに関する改善の歴史と、ユーザー補助サービスによるアプリ権限奪取のデモという内容でしたが、短い時間での発表だったため、ユーザー補助サービスについてあまり十分な説明ができませんでした。

この記事では、ユーザー補助サービスのより詳細な説明や(悪用以外の)活用方法、個人的に問題として考えている部分について説明しようと思います。 発表ではネガティブな面をアピールしてしまいましたが、ユーザー補助サービスを使った開発は非常に奥深く面白いので、その楽しさを少しでも伝えられればと思います。

ユーザー補助サービスとは

ユーザー補助サービス(Accessibility Service)とは、Androidアプリとユーザーの間のやり取りをサポートするためのAndroidの機能です。 ユーザー補助サービスを利用するとアプリの切り替えや画面の更新、通知の変化を読み取って音声などの別の手段でユーザーに通知することができます。 また、逆にユーザーの操作を検出してアプリに他の種類のタッチイベントとして通知させることもできます。 どちらかの単方向ではなく、アプリとユーザーの双方向のやりとりを補助できるのが大きな特徴です。

どのように動作するのか

AccessibilityEventを介してアプリ更新やユーザーの操作を検知することができます。 ユーザー補助サービスを利用するアプリでは取得できるイベントや取得できるパラメータに関して細かく設定できます。 開発者は良心に基づき最小権限で実装することが求められますが、AccessibilityServiceInfoの設定項目が非常に複雑な上、ユーザーのからの許可は「ユーザー補助」として一括で扱われるため正しい設定が難しくなっています。 個人的にインストール済みアプリのユーザー補助サービス権限についてはかなり注意を払っていますが、その権限が動作に必要最小限なのかどうかは正直あまり自信がありません。

権限の話はさておき、ユーザー補助サービスが有効になったアプリではAccessibilityService(というService)を通じて様々なイベントを受け取ることができます。 Viewイベントの場合は発生源のView情報も受け取ることができますが、Viewそのものにアクセスすることはできず、あくまでユーザー補助サービスを通して可能な範囲でのデータ取得となります。

アプリ、ユーザーのイベントを受け取る

僕が特に面白いと思っているのはこの部分です。 最前面のアプリが切り替わった時にそのパッケージを取得したり、表示中画面の文字列に特定の文言が含まれているかを判定したりすることができます。 「あるアプリの情報を他のアプリから知ることができる」という部分の面白さは非常に奥深く、GoogleNowなどもこのような方法で表示中アプリの情報を得ているかもしれない、何かより面白いことができるかもしれないと思うとわくわくします。 ユーザーのタップ情報を検知して対象Viewのサイズや配置などを知ったり、アプリごとの利用時間を測ったり、簡単な実装でも色々変わったことができて非常に面白いです。

ただし、Viewの情報がわかるといってもAccessibilityNodeInfoを経由して取得できる項目は限られており、画像や色、スタイルといった情報は残念ながら取得できません…。

アプリにイベントを伝える

ユーザー補助サービスでは、ユーザーの代わりにView操作を行うことができます。 Viewのクリックや画面のスクロール、文字列の入力など、ユーザーがアプリで操作可能なことは大体行うことができます。 先日のデモではアプリの権限を許可するためのSwitchコンポーネントに対してクリック操作を行うことでユーザー操作を介さずに自アプリに権限を与えていました。 こちらのほうは汎用的に使える機能を実装するのが難しく、正直あまり使ったことがありません。 開発中のアプリの入力画面に対してテストデータの入力を補助できるような、デバッグ補助アプリのようなものを作れるかもしれません。 正直ユーザー補助サービスでやらなくても…という感じですが、別のパッケージで実装できるので本体アプリを操作する必要がないのが利点でしょうか。

利用例

例えば、ユーザー補助サービスを使うと以下のようなアプリを作ることができます。

  • 表示中のアプリのパッケージ名やViewIdから効率的に入力補助を行うパスワード管理アプリ
    • 実際に1passwordなどはこのような動作になっているようです
  • 最前面のアプリを変更するイベントを監視し、アプリの利用時間を計測するアプリ
    • RescueTimeなどはおそらくこういった実装になっています
    • 有名サービスとはいえユーザー補助サービスを許可するのは怖いので自分で実装してみるのも良いかもしれません
  • 画面をタップした際、押されたViewのサイズなどを知ることができるアプリ
    • DroidKaigi 2017 で門田さんが発表していたアプリです
    • ユーザー補助サービス自体はUIを持たないため、画面を通じてユーザーにフィードバックするのが難しくなりがちですね…

このように、アイデア次第で色々なアプリを作ることができるのが魅力です。 普通のアプリよりはるかに広範囲なものを操作できるのも楽しいですね。

問題点と今後の展望

すでに書いたとおり、もっとも大きな問題点は「ユーザー補助サービスの権限があまりに強すぎる」というところだと思います。 アプリやユーザーのイベントを受け取る、アプリの操作を行うという双方向のアクションが可能にも関わらず、設定は一箇所のみで確認も非常に簡素です。 これはユーザー補助サービス本来の目的としては正しいですが、セキュリティモデルとしては自分で開発していても心配になるレベルです。 より細かく権限設定できるようにするか、一部の頻出機能はユーザー補助サービスとは別の機能として切り出したほうが良いと感じています。

実際にAndroid Oでは文字列入力補助のためにAutofill Frameworkが導入され、必要最小限のイベント通知とフィードバックのみが行えるようになります。 このような仕組みが今後も拡張されることで、今後はユーザー補助サービスだけに頼らなくても他のアプリと協調して動作するアプリが安全に作れるようになることを期待しています。

まとめ

ユーザー補助サービス非常に楽しいのでぜひ遊びましょう。 限られたイベントとAccessibilityNodeInfoを通じてアプリと会話する経験をすることで、よりAndroid(OS)の気持ちになってアプリのことを考えることができ(ると思ってい)ます。 また、ユーザー補助サービスの何が危険でどうすれば安全なのかを理解する上でも、実際に自分でイベントの取得やフィードバックを行ってみてできることを確かめてみることが大事だと思います。

ヤドカリをハッキングするゲームが面白い

ここ最近、職場で勧められたヤドカリをハッキングできるゲームをやっている。

www.jp.playstation.com

主人公の名前は変更できなかったので、カニカマではない。

ロボヤドカリをハッキングできるという理由だけでろくに下調べもなく買ってしまったのだが、ハッキングして放置を繰り返すだけでも結構面白くてぐるぐるとマップを回ってしまう。 そろそろスキルも全部取れそうだしサブクエスト的なものもあらかた終わったのでこのゲームに関する感想をまとめておきたい。 なお、僕はアクションゲーム自体が苦手難易度イージーだけでやっているのでゲームのレビューとしては多分訳にたたないです。

ハッキング(オーバーライド)に関して

そもそも敵の種類がそこまで多くないこともあって、ストーリーボス的な一部の機械と最初から混乱状態?みたいな機械以外はすべてハッキング可能。 ハッキングした敵は他の敵に攻撃したりしなかったり、なんだか気まぐれな感じだが、そのうち同士討ちがはじまってどちらかが死ぬまで戦ってくれる。 ハッキングするためには敵と密着する必要があるが、ハッキングの最中には対象の敵は動かなくなるので、1匹ずつバレないようにハッキングしていけば僕のようなアクション下手でも簡単に敵グループを片付けることができる。とってもラクだった。

難点は敵の種類ごとに騎乗できたりできなかったり、好戦的だったりそうでもなかったりしてハッキングの結果に差がある事。 ロボヤドカリはそもそも騎乗できないし、自分に着いてきてくれることもない。これは本当に悲しかった。 エリアを切り替えてもどってくるとハッキングしたヤドカリは大抵いなくなっているので、購入時に描いていたヤドカリランド構想が完全に潰えてしまった。 ただしかなりハッキングしたヤドカリはとても好戦的で、ハッキングが終わってすぐ他のヤドカリに殴りかかったり放電したりして戦闘面では心強い。 戦闘力もめちゃくちゃ高くてヤドカリを2匹程度ハッキングできたらあとは何もしなくても他の敵が皆死んでしまう。

あとは 敵をすべて撃破 系のミッションをうけているとハッキングした機械も自分で破壊する必要があって、最初に強い敵をハッキングしてラクをしようとしていたのに結局相手をしないといけなくなって辛かった。 ハッキングした敵の自爆コマンド実装してほしい。

ゲームシステムに関して

ものを持てる量が限られていて、頻繁にものを売ったり捨てたりしないといけないのはなかなか面倒だった。 特にコイル(武器や防具の改造アイテム)に関しては、特定のレアリティ未満のものは自動的に捨てるオプションが欲しくなる。 持てる量を増やすためには特定の動物の皮とか骨とかが必要なのだが、なぜか皮も骨もレアアイテムになっていて動物を狩っても狩っても出ない場合があり苦痛だった。 終盤になるとお金は余っているのだがアイテムを持てる量が少ない状態になりがちな気がする。 動物系アイテム、かなり高額でもいいから店売りしてほしい…。

あとは時間をユーザー側で操作できないのが非常に辛い。 夜になると本当に暗くなってしまって先に進むのが困難な時もあった。 セーブポイント的なところで翌朝になるまで待機させてほしかった。

あとは収集アイテムの位置などもマップに表示されていて迷うことがほとんどなくて遊びやすかった。 なんというか、このゲームは全体的にすごく遊びやすい。最近は難しいゲームが多いなーと思っていたので、ちゃんと遊べている感があってこれは嬉しかった。

アクションに関して

途中何度もさせられる壁登りアクションが面倒だった。 次の足場がある方向にスティックを倒すだけなのだが、主人公が装備しているARデバイス的なものでは次の足場がどこなのかわからないし、普段黄色く表示されている足場も夜になると全然目立たないので夜の壁登りは本当に苦痛だった。 夜の壁登りは避けようと思っても時間スキップもできないので待つしか無い。辛い。 敵や人間の足跡は夜でもハイライトできるのに黄色で目立つ足場がハイライトできないARデバイスは本当にポンコツすぎる…

壁登り以外は特にアクション面での不満はなかった。難易度もかなり下げられてとても遊びやすい。

まとめ

残念なところはいっぱいあるけれど、ヤドカリをハッキングできるゲームはとても珍しいのでそれだけでも買う価値があります。 特になついてくれないところも甲殻類っぽいと思えばそれはそれで良いかもしれない。

良いかもしれないといったけどそんなリアルさはゲームに求めていないので、メーカーさんはヤドカリに騎乗できる、または自分についてきてくれるDLCをお願いします。 自分がヤドカリになる続編でもいいです。お願いします。

なぜプレイヤーキャラクターの名前がカニカマなのか

プレイヤーキャラクターの名前を自由入力させるゲームを遊ぶときはキャラクターの名前をカニカマにしています。

なぜ本名やハンドルネームではないのか? また、なぜカニではないのか? という点について嫁から突っ込まれたので、現時点での僕の考えを記録しておこうと思いました。

まず、なぜ本名ではないのか。

これは単純でプレイヤーキャラは僕ではないからです。 昔ラブプラスというゲームをやったときに律儀に自分の名前をプレイヤーキャラクターの名前にしていたのですが、 主人公が僕のようなコミュ障ではないので段々自分と乖離してきて感情移入できなくなってしまったからです。 そのうち自分と同姓同名のキャラクターとネネさんがイチャイチャしているのを観るのが辛くなってきたのでこのゲームを起動することはなくなりました。

なぜハンドルネームではないのか。

ハンドルネームは名前ではないからです。 エヌ・イー・アイ・エヌ・サン・ナナさんはすべての住民がIDで管理された一部のディストピア以外の世界観には馴染めません。 というか、そもそも長すぎて入力できない場合がほとんどです。 nein37 は日本語のシナリオ中に出てくると違和感があるので使っていません。

なぜカニではないのか。

僕がカニを好きで、ゲームキャラはカニではないからです。 カニという名前で呼ばれた時、ハサミもなく、歩脚が4対でなく、眼柄ももたないキャラクターでありたくないんです。 また、たとえ操作キャラクターがカニのゲームであっても理由なく残虐な行為に及ぶカニであれば「カニはそんなことしない」と思ってしまいそうな気がします。 もし理想のカニになってカニらしい暮らしができるゲームができたらカニという名前になるかもしれませんが、その機会はおそらくないでしょう。 カニに求めるものが多すぎて気軽にカニになれていません。

なぜカニカマなのか。

カニカマはカニではなく、誰からもカニの代用品として認知されていて、それでいて僕自身が深い興味を持っていないものだからです。 カニでなくカニカマだと思えばどんなキャラクターであっても、どんな性格でも受け入れられますし、 僕自信が「こうでなければ」という強迫観念から離れて自由に遊ぶことができます。 例えば、カニカマは時に理由なく残虐な行為に及ぶことがありますが、カニじゃなくてカニカマなのでしょうがない。 魚肉練り製品じゃあしょうがないなあ。という感じです。 今日もカニカマのおかげで現実とゲームの区別を付けて楽しく遊んでいられます。

TextAppearance のプレビュー画面を作る

AndroidのリソースXMLを読み書きできない人に TextAppearance の定義内容を共有するためには、わかりやすく定義内容を一覧できる仕組みが必要です。 できれば、以下のように実際のアプリ内の表示とあわせて見られるのが一番良さそうです。

f:id:nein37:20170328151636p:plain

このプレビュー画面を作るためには「TextAppearane の一覧を取得する」「TextAppearane の定義内容を取得する」という処理が必要になるので、それぞれ方法を紹介します。

TextAppearane の一覧を取得する

TextAppearance や style は R.style. 以下に id が定数として定義されているので、これを利用してリフレクションで一覧を作ります。

今回は AppCompat の TextAppearance を対象にするので、TextAppearance_ の prefix を持つ style を対象にしました。

final List<Field> textAppearanceList = new ArrayList<>();
for (Field field : R.style.class.getFields()) {
    String fieldName = field.getName();
    if (fieldName.startsWith("TextAppearance_")) {
        textAppearanceList.add(field);
    }
}

これで R.style.TextAppearance_* の定数のリストができました。 ここで取得したリストではもともとxml に定義していた名前の ._ に変換されているので注意しましょう。

idの値は以下のどちらかの方法で取り出すことができます。

Field から直接値を取り出す

int styleId = 0;
try {
    styleId = field.getInt(null);
} catch (IllegalAccessException e) {
}

もとの名前から id を検索する

String styleName = field.getName().replace("_", ".");
int styleId = context.getResources().getIdentifier(styleName, "style", context.getContext().getPackageName());

TextAppearance の定義内容を知る

id がわかれば style の定義内容を取得することができます。

TypedArray typedArray = context.getTheme().obtainStyledAttributes(styleId, R.styleable.TextAppearance);

あとは TypedArray から値を取得するだけ… と思っていたら、TextView などが参照している com.android.internal.R.styleable.TextAppearance_textColor は外からアクセスできず、カスタムViewでもないので package.R.styleable にもなくてどうしよう、という感じでした。

悩んだ末、今回は作っていたのが preview ツールだったので TextViewに一度適用して TextView の setter から各デザイン情報を得るという乱暴な方法で実現しました。 TypedArray から直接属性を取る方法知りたい…

// 新しいAPIだが TextViewCompat 経由で setTextAppearance を呼べる
TextViewCompat.setTextAppearance(textView, styleId);

// textColor は ColorStateList だったりするが getCurrentTextColor が初期表示の色を取るのに便利
int textColor = (0xFFFFFFFF & textView.getCurrentTextColor());

// textSize は pixel で取れるので sp に変換する
// style定義時の値が dp か sp かを実行時に知る方法はない
float textSize = textView.getTextSize();
int textSizeSp = Math.round(textSize / context.getResources().getDisplayMetrics().scaledDensity);

// 太字/イタリック
boolean isBold = false;
boolean isItalic = false;
if (textView.getTypeface() != null) {
    isBold = textView,getTypeface().isBold();
    isItalic = textView.getTypeface().isItalic();
}

// ALLCAPS(後述)
boolean isAllCaps = false;
if (textView.getTransformationMethod() != null) {
    if (TextUtils.equals(textView.getTransformationMethod().getClass().getSimpleName(), "AllCapsTransformationMethod")) {
        isAllCaps = true;
    }
}

ALLCAPS 属性は set した瞬間に AllCapsTransformationMethod を TransformationMethod に set という乱暴な処理で扱われていて、isAllCaps() のような getter が存在しません。 しかも互換性のために AllCapsTransformationMethod が2種類(SDKとsupport)用意されていて、両方 @hide なので instanceof させることもできませんでした。 仕方がないのでクラス名だけの比較にしていますが、かなり厳しいですね…。

まとめ

かなり無理やりな処理ですが、一応なんとかなったのでサンプルとして公開しました。 アプリ内で TextAppearance に共通する prefix や suffix が決められていれば同じような処理で TextAppearance のプレビュー画面が作れると思います。

github.com

スプレッドシートでよく使う関数メモ

意外とスプレッドシートを良く使うので、最近使って便利だった関数をメモしておきます。

JOIN

配列要素を結合するのに使う。 char(10) が改行文字なので、取ってきたデータを1セルの中で表示したい時は JOIN(char(10), 配列) みたいな感じにすることが多い。

https://support.google.com/docs/answer/3094077?hl=ja

QUERY

特定の範囲からデータを取ってくるときに便利。 QUERY(A2:H100,"select A where D like 'kani%'") のようにSQLっぽい記法でデータを抽出できる。

INDEX と MATCH でも似たようなことが出来るけど、QUERYだと簡単に書ける上に範囲指定が1回だけで良いので楽。 https://support.google.com/docs/answer/3093343?hl=ja

IMAGE

URLで指定した画像をセル内に描画できる。便利。 対象のURLに画像が存在するかどうかの分岐はできない(エラーにならない)のが残念。

https://support.google.com/docs/answer/3093333?hl=ja&ref_topic=3105411

DEC2HEX、HEX2DEC

10進数を16進数に変換するやつとその逆。

配列の結合

配列A,配列B,配列C,を結合したい時、{配列A;配列B;配列C} とやると配列の次元を保ったまま結合できる。 {配列A,配列B,配列C} だと3次元配列になり、データ件数が違うとエラーが出る。

応用

A列、B列、C列の中から空文字でない要素をひとつのセルの中で改行して並べる場合、以下のように書ける。

= JOIN(char(10),QUERY({A:A;B:B;C:C},"select Col1 where Col1 <>''"))

簡単。