この記事の最終更新日: 2026年6月13日

Flutterでアプリを作っていると、カメラ、位置情報、通知などの権限を扱う場面があります。
たとえば、次のような機能です。
カメラで写真を撮る
現在地を取得する
目的地に近づいたら通知する
リマインダー通知を送る
QRコードを読み取る
近くの店舗や施設を表示する
Flutterでは permission_handler などのパッケージを使うことで、権限の確認やリクエストを共通的に扱えます。
しかし、ここで注意したいのは、Flutterのコードだけ書けば終わりではない ということです。
カメラ、位置情報、通知は、iOSとAndroidのネイティブ仕様に強く依存します。
そのため、Dart側の実装だけでなく、Info.plist や AndroidManifest.xml の設定、権限を求めるタイミング、拒否された後の導線まで考える必要があります。
この記事では、Flutterでカメラ・位置情報・通知権限を扱うときの注意点を、初心者向けにわかりやすく整理します。
- Flutterでも権限まわりはネイティブ知識が必要
- まず押さえるべき基本方針
- 権限リクエストの基本コード
- iOSでは NSCameraUsageDescription が必要
- Androidでは CAMERA 権限を宣言する
- カメラ権限でよくある失敗
- 位置情報は「いつ使うか」で権限が変わる
- iOSでは「使用中」と「常に」を分けて考える
- Androidではフォアグラウンド・バックグラウンド・精度に注意
- 位置情報権限でよくある失敗
- 通知は「あとで価値が出る機能」なので説明が重要
- iOSでは通知許可リクエストが必要
- Android 13以降では通知権限が必要
- Androidでは通知チャンネルも重要
- 通知権限でよくある失敗
- 拒否された後の導線を用意する
- 権限リクエスト前に説明画面を挟む
- カメラ権限
- 位置情報権限
- 通知権限
- まとめ
Flutterでも権限まわりはネイティブ知識が必要
Flutterはクロスプラットフォーム開発に便利ですが、権限まわりはOSのルールに従う必要があります。
permission_handler は、iOS・Androidの権限リクエストや状態確認を扱えるFlutterパッケージですが、実行時に権限を求めるだけでなく、OS固有の設定ファイルにも権限情報を追加する必要があります。公式READMEでも、ランタイムで権限を求める場合でも、Android・iOS固有ファイルへの設定が必要だと説明されています。(Dart packages)
つまり、Flutterで権限を扱うときは、次の3層で考える必要があります。
1. Dart側の実装
2. iOS / Androidの設定ファイル
3. ユーザーにどう説明して許可してもらうか
初心者がハマりやすいのは、Dart側だけ実装して、Info.plist や AndroidManifest.xml の設定を忘れるパターンです。
まず押さえるべき基本方針
権限機能を実装するときは、いきなりコードを書き始める前に、次の点を整理しておくとよいです。
| 観点 | 考えること |
|---|---|
| 何に使うか | カメラ、位置情報、通知を何の機能で使うのか |
| いつ必要か | アプリ起動直後か、機能を使う瞬間か |
| 必須か任意か | 許可しないと使えない機能か、一部制限で済むか |
| 拒否されたらどうするか | 再説明するか、設定画面へ誘導するか |
| OS差分はあるか | iOSとAndroidで許可の出方や制限が違うか |
特に重要なのは、必要になったタイミングで権限を求めることです。
アプリ起動直後に、カメラ・位置情報・通知の許可をまとめて求めると、ユーザーは「なぜ必要なのか」がわからず拒否しやすくなります。
Android公式ドキュメントでも、必要な権限だけを宣言し、ユーザーに明確なメリットがあること、そして要求がユーザーにとって自然な形で行われることが重要だと説明されています。(Android Developers)
権限リクエストの基本コード
Flutterでは、permission_handler を使うと権限の状態確認やリクエストを比較的簡単に書けます。
たとえば、カメラ権限を求める場合は、次のようなイメージです。
import 'package:permission_handler/permission_handler.dart';
Future<void> requestCameraPermission() async {
final status = await Permission.camera.request();
if (status.isGranted) {
// カメラ機能を利用する
} else if (status.isDenied) {
// ユーザーが拒否した場合の説明を表示する
} else if (status.isPermanentlyDenied) {
// アプリ設定画面への誘導を検討する
await openAppSettings();
}
}
permission_handler は、権限のリクエストや状態確認だけでなく、ユーザーが端末設定で権限を変更できるようにアプリ設定画面を開く機能も提供しています。また、Androidでは権限を求める理由、いわゆるrationaleを表示する判断にも対応しています。(Dart packages)
ただし、これだけでは不十分です。
iOSなら Info.plist、Androidなら AndroidManifest.xml の設定が必要になります。
カメラ権限の注意点
iOSでは NSCameraUsageDescription が必要
iOSでカメラを使う場合、ios/Runner/Info.plist に NSCameraUsageDescription を追加する必要があります。
Apple公式ドキュメントでは、NSCameraUsageDescription は、アプリがデバイスのカメラへのアクセスを求める理由をユーザーに伝えるメッセージだと説明されています。(Apple Developer)
例としては、次のように書きます。
<key>NSCameraUsageDescription</key>
<string>プロフィール画像を撮影するためにカメラを使用します。</string>
この文言は、ユーザーに表示される可能性があります。
そのため、開発者向けの説明ではなく、ユーザーが見て理解できる言葉にする必要があります。
悪い例は次のようなものです。
カメラを使います。
これでは、なぜ必要なのかがわかりません。
良い例は次のようなものです。
プロフィール画像を撮影するためにカメラを使用します。
QRコードを読み取るためにカメラを使用します。
「何のために使うのか」を具体的に書くのがポイントです。
Androidでは CAMERA 権限を宣言する
Androidでカメラを使う場合は、android/app/src/main/AndroidManifest.xml に CAMERA 権限を宣言します。
Android公式ドキュメントでは、カメラにアクセスするアプリは、AndroidManifest.xml に android.permission.CAMERA を宣言する例が示されています。(Android Developers)
<uses-permission android:name="android.permission.CAMERA" />
また、Androidではカメラ機能を必須扱いにするかどうかにも注意が必要です。
公式ドキュメントでは、カメラのようなハードウェア関連の権限を宣言する場合、そのハードウェアがなくてもアプリを実行できるなら、uses-feature で android:required="false" を設定することが推奨されています。設定しない場合、Androidはそのハードウェアを必須とみなし、一部端末でアプリをインストールできなくなる可能性があります。(Android Developers)
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
たとえば、プロフィール画像を「カメラ撮影」でも「写真選択」でも設定できるアプリなら、カメラ必須にしない方が自然です。
カメラ権限でよくある失敗
カメラ権限でよくある失敗は次の通りです。
Info.plistにNSCameraUsageDescriptionを書いていない
AndroidManifest.xmlにCAMERA権限を書いていない
カメラがない端末への考慮をしていない
権限拒否後の画面を用意していない
エミュレーターだけで確認して実機確認していない
特にカメラは、シミュレーターやエミュレーターでは確認しにくい場面があります。
QRコード読み取り、写真撮影、ピント、画質、端末ごとのカメラ挙動は、実機で確認するのがおすすめです。
位置情報権限の注意点
位置情報は「いつ使うか」で権限が変わる
位置情報権限は、カメラよりもさらに慎重に設計する必要があります。
理由は、位置情報がプライバシーに強く関わる情報だからです。
Android公式ドキュメントでは、位置情報権限はユースケースによって必要な権限が変わり、フォアグラウンド位置情報・バックグラウンド位置情報・正確な位置情報・概略位置情報などの種類があると説明されています。(Android Developers)
つまり、位置情報を使うときは、まず次のように整理する必要があります。
アプリを開いている間だけ必要なのか
アプリを閉じている間も必要なのか
正確な位置情報が必要なのか
おおよその位置で十分なのか
たとえば、地図上に現在地を表示するだけなら、基本的にはアプリ使用中の位置情報で十分なことが多いです。
一方、目的地に近づいたら通知するアプリや、移動記録アプリなどでは、バックグラウンド位置情報が必要になる可能性があります。
ただし、バックグラウンド位置情報はOS制限やストア審査の観点でも厳しくなりやすいため、本当に必要かを慎重に判断するべきです。
iOSでは「使用中」と「常に」を分けて考える
iOSの位置情報権限では、「アプリの使用中のみ」と「常に許可」の違いを意識する必要があります。
Apple公式ドキュメントでは、When In Use authorizationはアプリ使用中のみ位置情報更新を利用可能にし、Always authorizationはアプリが使用中でない場合も含めて位置情報更新を利用可能にすると説明されています。(Apple Developer)
iOSの Info.plist では、利用内容に応じて次のようなキーを設定します。
<key>NSLocationWhenInUseUsageDescription</key>
<string>現在地周辺の情報を表示するために位置情報を使用します。</string>
バックグラウンドでの利用が必要な場合は、さらにAlways系の説明も必要になります。
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>目的地に近づいたタイミングで通知するため、アプリを閉じている間も位置情報を使用します。</string>
位置情報の説明文は、かなり具体的に書くべきです。
悪い例は次のようなものです。
位置情報を使用します。
良い例は次のようなものです。
目的地に近づいたタイミングで通知するために位置情報を使用します。
現在地周辺の店舗を表示するために位置情報を使用します。
ユーザーが「それなら必要だ」と納得できる説明にすることが大切です。
Androidではフォアグラウンド・バックグラウンド・精度に注意
Androidでは、位置情報権限に複数の種類があります。
Android公式ドキュメントでは、位置情報アクセスにはフォアグラウンドとバックグラウンドの区別があり、精度についても正確な位置情報と概略位置情報があると説明されています。(Android Developers)
代表的には、次のような権限を使います。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
バックグラウンドで位置情報が必要な場合は、条件に応じて次の権限も検討します。
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
ただし、バックグラウンド位置情報は慎重に扱うべきです。
Android公式ドキュメントでは、Google Playのポリシーにより、バックグラウンド位置情報アクセスは、アプリの中核機能に必要で、関連するポリシー要件を満たすアプリに制限されると説明されています。また、Android 8.0以降ではバックグラウンド時の位置情報更新頻度にも制限があります。(Android Developers)
つまり、「なんとなく便利だからバックグラウンド位置情報を使う」は危険です。
ユーザーにとって本当に必要な機能か、ストア審査で説明できるかを先に考えましょう。
位置情報権限でよくある失敗
位置情報権限でよくある失敗は次の通りです。
アプリ起動直後にいきなり位置情報を求める
なぜ必要なのかを説明しない
使用中のみで十分なのに常に許可を求める
バックグラウンド位置情報の必要性を説明できない
iOSとAndroidの許可レベルの違いを理解していない
正確な位置情報と概略位置情報の違いを考慮していない
拒否された後の導線がない
位置情報は、ユーザーにとってかなり敏感な権限です。
アプリの価値が伝わる前に求めると、拒否されやすくなります。
おすすめは、位置情報が必要な機能をユーザーが使おうとしたタイミングで、先に説明画面を出してから権限を求める流れです。
地図機能を開く
↓
「現在地周辺を表示するために位置情報を使います」と説明
↓
権限ダイアログを表示
このように、文脈のあるタイミングで求める方が自然です。
通知権限の注意点
通知は「あとで価値が出る機能」なので説明が重要
通知権限は、カメラや位置情報とは少し性質が違います。
カメラは、撮影ボタンを押した瞬間に必要性がわかります。
位置情報も、地図や目的地通知を使う流れなら必要性を説明しやすいです。
一方、通知は「今すぐ使う」よりも、「あとで知らせる」ための機能です。
そのため、ユーザーからすると、
なぜ今、通知の許可が必要なの?
どんな通知が来るの?
頻繁に通知されるのでは?
と感じやすいです。
通知権限は、何の通知が届くのかを説明したうえで求めることが大切です。
iOSでは通知許可リクエストが必要
iOSで通知を表示するには、ユーザーの許可が必要です。
Apple公式ドキュメントでは、通知の許可を求めるには UNUserNotificationCenter の requestAuthorization(options:completionHandler:) を呼び出し、アラート、サウンド、バッジなど必要なオプションを指定すると説明されています。(Apple Developer)
Flutterでローカル通知やプッシュ通知のパッケージを使う場合も、iOS側では通知許可の取得を意識する必要があります。
通知の説明としては、たとえば次のような文言が考えられます。
目的地に近づいたときにお知らせするため、通知を使用します。
予約時間や大切な予定をお知らせするため、通知を使用します。
通知は、ユーザーが「受け取る意味がある」と感じるタイミングで許可を求めるのが重要です。
Android 13以降では通知権限が必要
Androidでは、以前は通知権限の扱いがiOSと大きく異なっていました。
しかし、Android 13、APIレベル33以降では、通常の通知を送るために POST_NOTIFICATIONS というランタイム権限が導入されています。Android公式ドキュメントでは、Android 13以降で非免除の通知を送るには POST_NOTIFICATIONS が必要だと説明されています。(Android Developers)
AndroidManifest.xml には次のように追加します。
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
また、Android公式ドキュメントでは、Android 13以降では新規インストール時に通知はデフォルトでオフになり、アプリは通知を送る前に権限を求め、ユーザーが許可するまで待つ必要があると説明されています。(Android Developers)
つまり、Androidでも「通知は自動で出せる」と考えるのは危険です。
対象SDKや端末OSバージョンによって挙動が変わるため、実機で確認しましょう。
Androidでは通知チャンネルも重要
Androidの通知では、通知チャンネルも重要です。
通知チャンネルは、ユーザーが通知の種類ごとに管理できる仕組みです。
たとえば、次のように分けられます。
目的地到着通知
リマインダー通知
キャンペーン通知
システム通知
ユーザーにとって重要な通知と、マーケティング通知を同じチャンネルにまとめると、通知を一括でオフにされる可能性があります。
通知の目的に応じてチャンネルを分ける設計が大切です。
通知権限でよくある失敗
通知権限でよくある失敗は次の通りです。
アプリ初回起動直後に通知許可を求める
何の通知が届くのか説明しない
Android 13以降のPOST_NOTIFICATIONSを忘れる
通知チャンネルを適切に作っていない
ユーザーが拒否した後の導線がない
重要通知と宣伝通知を分けていない
iOS実機で通知を確認していない
通知は、ユーザー体験を良くすることもあれば、嫌われる原因にもなります。
「通知を許可してください」ではなく、「この通知があると何が便利なのか」を伝えることが重要です。
3つの権限をまとめて扱うときの設計
カメラ、位置情報、通知をすべて使うアプリもあります。
たとえば、次のようなアプリです。
旅行アプリ
配送アプリ
位置情報通知アプリ
SNSアプリ
QRコード読み取りアプリ
店舗検索アプリ
防犯・見守りアプリ
このような場合にやってはいけないのは、アプリ起動直後に全部の権限をまとめて求めることです。
カメラを許可してください
位置情報を許可してください
通知を許可してください
と連続で出すと、ユーザーは不安になります。
おすすめは、機能ごとに必要なタイミングで求めることです。
QRコードを読み取るとき → カメラ権限
現在地周辺を表示するとき → 位置情報権限
目的地に近づいたら知らせる設定をするとき → 通知権限
この方が、ユーザーは権限の必要性を理解しやすくなります。
拒否された後の導線を用意する
権限は、必ず許可されるとは限りません。
ユーザーが拒否することもあります。
そのときにアプリが何も説明しないと、ユーザーは機能が使えずに離脱してしまいます。
拒否された場合は、次のような導線を用意しましょう。
この機能を使うにはカメラの許可が必要です。
設定アプリからカメラの利用を許可してください。
目的地付近で通知するには、位置情報と通知の許可が必要です。
設定を変更すると、この機能を利用できます。
permission_handler では、端末のアプリ設定画面を開くための openAppSettings() も提供されています。(Dart packages)
ただし、設定画面へ誘導する前に、なぜ必要なのかをアプリ内で説明する方が親切です。
権限リクエスト前に説明画面を挟む
権限ダイアログは、OSが表示するため、文言や見た目を自由に作り込めません。
そのため、権限ダイアログを出す前に、アプリ側で説明画面を挟むのがおすすめです。
たとえば、通知権限なら次のような説明です。
目的地に近づいたタイミングでお知らせするため、通知を使用します。
通知はいつでも設定から変更できます。
位置情報なら次のように説明できます。
目的地に近づいたことを判定するため、位置情報を使用します。
移動中の通知機能を使う場合に必要です。
カメラなら次のように説明できます。
QRコードを読み取るためにカメラを使用します。
撮影した画像を勝手に保存・送信することはありません。
このように、OSダイアログの前に「なぜ必要か」を伝えることで、許可されやすくなります。
Flutter実装時のチェックリスト
Flutterでカメラ・位置情報・通知権限を扱うときは、次のチェックリストを使うと安全です。
カメラ権限
iOSのInfo.plistにNSCameraUsageDescriptionを書いたか
AndroidManifest.xmlにCAMERA権限を書いたか
カメラがない端末でもアプリを使える設計か
uses-featureでrequired=falseを検討したか
権限拒否時の表示を用意したか
実機でカメラ動作を確認したか
位置情報権限
使用中のみで足りるか、常に許可が必要か整理したか
iOSのInfo.plistに位置情報の説明文を書いたか
AndroidManifest.xmlに必要な位置情報権限を書いたか
正確な位置情報が必要か、概略でよいか考えたか
バックグラウンド位置情報が本当に必要か検討したか
拒否された場合の導線を用意したか
ストア審査で説明できる理由があるか
通知権限
通知の目的をユーザーに説明しているか
iOSで通知許可を求める処理を入れたか
Android 13以降のPOST_NOTIFICATIONSに対応したか
Androidの通知チャンネルを設計したか
初回起動直後にいきなり許可を求めていないか
拒否された場合の案内を用意したか
実機で通知表示を確認したか
まとめ
Flutterでカメラ・位置情報・通知権限を扱うときは、Dartのコードだけでなく、iOSとAndroidのネイティブ仕様を理解する必要があります。
permission_handler を使えば、権限のリクエストや状態確認は共通化しやすくなります。
しかし、実際には次のような設定が必要です。
iOS: Info.plistへの説明文追加
Android: AndroidManifest.xmlへの権限追加
通知: iOSの許可リクエスト、Android 13以降のPOST_NOTIFICATIONS対応
位置情報: 使用中・常に許可・バックグラウンド利用の整理
カメラ: 端末にカメラがない場合の考慮
特に注意したいのは、権限を求めるタイミングです。
アプリ起動直後にまとめて求めるのではなく、ユーザーがその機能を使おうとしたタイミングで、必要性を説明してからリクエストするのがおすすめです。
権限まわりは、アプリの信頼感に直結します。
「とりあえず許可を求める」のではなく、ユーザーが納得できる理由を用意し、拒否された場合の導線まで含めて設計しましょう。

大阪のエンジニアが書いているブログ。



コメント