Android向け画像ピッカー「Matisse」完全ガイド:導入・実装・注意点まで

概要 — Matisseとは何か

Matisseは、主にAndroidアプリで画像・動画の選択UIを簡単に提供するためのオープンソースライブラリです。もともとは中国のコミュニティサービス Zhihu(知乎)が公開したライブラリで、ユーザーに直感的でカスタマイズ可能なメディア選択画面を提供します。単純なギャラリー表示だけでなく、複数選択、カウント表示、カメラ起動(撮影)やサムネイルスケーリング、テーマ適用など、多くの実用機能を備えているのが特徴です。

主な特長と機能

  • 画像・動画の選択(MimeTypeによるフィルタ)
  • 複数選択(最大選択数や選択可能数の制御)および選択状態のカウント表示
  • サムネイルのスケールや列数(spanCount)などUI調整が可能
  • カメラ起動(撮影)を組み込み可能(FileProvider経由での保存)
  • 画像読み込みライブラリ(GlideやPicassoなど)を差し替えてサムネ表示を高速化
  • テーマ/スタイルのカスタマイズ、フィルター(サイズや拡張子による除外)

導入の基本手順

導入は大きく分けて以下のステップになります。

  • ライブラリをGradleに追加
  • 画像エンジン(Glide等)の実装を用意
  • AndroidManifest.xmlにFileProvider(撮影機能を使う場合)を設定
  • Activity/FragmentからMatisseを呼び出して結果を受け取る

代表的な使い方(旧来のstartActivityForResultを用いる例)は次の通りです(サンプル)。

// 呼び出し側
int REQUEST_CODE_CHOOSE = 23;
Matisse.from(this)
    .choose(MimeType.ofImage())
    .countable(true)
    .maxSelectable(9)
    .imageEngine(new GlideEngine())
    .forResult(REQUEST_CODE_CHOOSE);

// onActivityResult内
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
        List uris = Matisse.obtainResult(data);
        List paths = Matisse.obtainPathResult(data); // 利用可能な場合
        // 取得したUri/パスを利用してアップロードや表示を行う
    }
}

注意:上記コードはライブラリの典型的な利用例で、実際のAPIやメソッド名は利用するバージョンやフォークによって若干異なることがあります。最新版やAndroidX対応版は公式リポジトリ/フォークのREADMEを確認してください。

カメラ撮影(capture)を有効にする

Matisseはカメラ起動をオプションで組み込めます。AndroidのFileProviderを使って撮影ファイルを受け渡すため、AndroidManifest.xmlにproviderを設定し、Matisse呼び出し時にCaptureStrategy(または同等の設定)でauthorityを指定する必要があります。

  • ManifestにFileProviderを追加
  • res/xml/file_paths.xmlで保存先のパスを定義
  • Matisse設定でcapture(true)/captureStrategy(...)を指定

この部分はAndroidのバージョン(特にAndroid 7以降のURI共有制約)に強く依存するため、FileProviderの設定を正しく行うことが重要です。

Android 11(Scoped Storage)以降の注意点

Android 10/11以降で導入されたスコープストレージやパーミッション周りの挙動変化は、外部ストレージからファイルを列挙・読み取りする動作に影響します。Matisseのオリジナル実装は古いAPI(外部ストレージフルアクセス)に依存している箇所があるため、次の点に注意してください。

  • Android 11+ではMediaStoreやStorage Access Framework(SAF)、またはAndroid 13のPhoto Picker APIを検討する
  • Matisseの公式リポジトリが古い場合、フォーク版やAndroidX対応/Scoped Storage対応済みの派生ライブラリを利用する
  • 必要なパーミッション(READ_EXTERNAL_STORAGE、CAMERAなど)をランタイムで適切にリクエストする

最近の実装上のポイント(実務で押さえること)

  • ActivityResult API(registerForActivityResult)との併用:startActivityForResultは非推奨になっているため、Matisseの起動・結果受け取りをActivityResultContractでラップするか、既存のforResultを使う場合でも適切に移行計画を立てる
  • 画像ロードは専用ライブラリに任せる:Glide等のImageEngineを使うことで、スクロールやメモリ使用が改善される
  • UI/UXのカスタマイズ:spanCount(列数)、thumbnailScale、テーマカスタムで自アプリのデザインに合わせる
  • メモリ・パフォーマンス:大量の画像表示ではサムネイル読み込みの最適化やRecyclerViewの最適化が必要

Matisseのアーキテクチャ的理解(概念)

Matisseは主に以下のような責務で構成されています。

  • メディア列挙ロジック:端末内の画像/動画をMediaStore等から取得する
  • 表示レイヤ:RecyclerViewベースでサムネイルをグリッド表示し、選択状態を管理
  • 画像読み込みエンジンの抽象化:GlideやPicassoなど任意の実装を差し替え可能にしている
  • 結果の返却:選択結果をIntent経由で呼び出し元に返す仕組み

この分離により、アプリ側はデータ取得方法や表示ロジックを部分的に入れ替えたり、拡張したりできますが、同時にMediaStoreやファイル権限のOS側の変更に敏感になります。

よくあるトラブルと対処法

  • カメラ起動でクラッシュする:FileProviderのauthorityやres/xml/file_pathsの設定が正しいか確認する
  • Android 11で画像が表示されない:Scoped Storageの影響。フォークやアップデート版、またはMediaStoreを正しく使う実装に切り替える
  • 選択結果が取得できない:onActivityResultのrequestCodeやIntentデータの受け取りロジックを確認。Matisse.obtainResult(data)の戻り値をチェックする
  • サムネイルが重い/メモリ不足:Glide等の画像ライブラリを利用し、サムネイルのサイズを小さくする

代替ライブラリと比較

Matisseは歴史があり使いやすい一方で、メンテナンスが停滞している期間があるため、以下の代替も検討してください。

  • TedImagePicker:モダンで日本語ドキュメントも多く、APIが使いやすい
  • FishBun:カスタマイズ性の高い画像ピッカー
  • Android標準のPhoto Picker(Android 13以降):プライバシーに配慮したOS公式の選択UI

プロジェクト要件(対応OSレンジ、必須機能、保守性)に応じて最適な選択を検討しましょう。

実務での導入判断フロー(チェックリスト)

  • 対応OS範囲とScoped Storageへの対応状況を確認する
  • ライブラリのアクティブ度(最近のコミット/フォークの存在)を確認する
  • 必要な機能(動画対応、撮影、トリミングなど)が揃っているかをチェック
  • 画像表示はGlide等を使って高速化する方針を決める
  • パーミッション・FileProvider設定・ActivityResult API対応を設計に含める

まとめ

MatisseはAndroidアプリに迅速にメディア選択UIを導入するのに便利なライブラリです。ただし、Androidプラットフォームの権限モデルやストレージモデルの変化に伴い、オリジナルの実装がそのままでは期待通りに動作しないケースがあります。導入する際は、公式リポジトリおよびフォークの更新状況を確認し、場合によってはモダンな代替(Photo Picker、TedImagePicker等)を検討してください。必須となるFileProviderやランタイムパーミッションの扱い、ActivityResult APIへの対応はプロジェクトの品質と安定性に直結します。

参考文献