[Flutter] スクリーンショットや画面録画による情報漏洩対策をする

![スクリーンショット 2023-11-15 16.15.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/3090fbdc-6fd7-cc34-c21f-2175e33fb782.png)


Amazon PrimeやDAZNなどのアプリを使用していて、スクリーンショットや画面録画をした時に、真っ黒くなることを確認した方はいらっしゃいますでしょうか？？

動画系のアプリは画面録画を容認してしまうと、Youtubeや別のサイトに違法アップロードされてしまい、サービスとして成り立たないですよね。
また、クレジットカード系や個人情報が入力されている画面はできるだけ他の人に知られないようにするためな対策はあった方が良さそうだなと考えています。

てっきり、Flutterはまだ対応できていないと思っていましたが、会社の雑談会の中で教えていただいたので共有させていください！

# `screen_protector`について

https://pub.dev/packages/screen_protector

↑こちらから引用させていただいてます。

 `screen_protector`は、iOS/Androidのアプリケーションのバックグラウンドのスクリーンショットとフォアグラウンドのスクリーンショットの防止を防ぐPackageです。

 また、このPackageを使用すると、アプリの一部やアプリ全体画面を隠すことができます。


# `screen_protector`にあるメソッド一覧とOSの対応について

|  | iOS | Android |
| ---- | ---- | ---- |
| `preventScreenshotOn()` | ⭕️ | ⭕️ |
| `preventScreenshotOff()` | ⭕️ | ⭕️ |
| `protectDataLeakageWithImage()` | ⭕️ | ❌ |
| `protectDataLeakageWithColor()` | ⭕️ | ❌ |
| `protectDataLeakageWithColorOff()` | ⭕️ |❌ |
| `protectDataLeakageWithBlur()` | ⭕️ |❌ |
| `protectDataLeakageWithBlurOff()` | ⭕️ |❌ |
| `protectDataLeakageOff()` | ❌ |⭕️ |
| `protectDataLeakageOn();` | ❌ |⭕️ |


## 両OSでできること

### スクリーンショットをすると真っ黒になる

```dart
await ScreenProtector.preventScreenshotOn();
```

| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/321f789e-9ca6-2a4f-17df-231895332f59.jpeg"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/a5ed68c4-2bfc-e788-94c0-e2ba3b9a5fdf.png">| 



### スクリーンショット無効をオフにする

```dart
await ScreenProtector.preventScreenshotOff();
```
| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/6eea091c-5391-cc38-d6df-09d84c2bc97c.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/49b78e9e-af5f-fc15-d2fd-53a4aecbd0ee.png">| 


## iOSのみでできること

### スクリーンショット無効をオフ＋マルチタスク画面で赤色になる

```dart
// 色は自由に選択できる
await ScreenProtector.protectDataLeakageWithColor(Colors.red);
```

| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/ca0ef2b5-dcb6-8e07-a18e-d6861edad34d.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/1cf55a4e-0dad-4d29-828c-cde35c68105f.png">| 


### スクリーンショットもマルチタスク画面どちらも普段通り

```dart
await ScreenProtector.protectDataLeakageWithColorOff();
```

| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/2fa740e9-2d1a-b401-1b49-dab840c1d2f2.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/3b2078ba-ccf5-7824-fd7c-9dea5539ba4a.png">| 


### スクリーンショット無効をオフにし、マルチタスク画面で、モザイクっぽくなる

```dart
await ScreenProtector.protectDataLeakageWithBlur();
```
| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/b554f500-fea6-568d-43ea-b437b1398119.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/b44e71e7-b520-0a0e-9d40-532d7f970e89.png">| 



### スクリーンショットもマルチタスク画面どちらも普段通り

```dart
await ScreenProtector.protectDataLeakageWithBlurOff();
```

| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/fb734681-4dce-4a59-bd9b-fe6072715a23.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/960cc197-f2ba-fc55-1212-394dbd11b7ab.png">| 


### その他


```dart
await ScreenProtector.protectDataLeakageWithImage('splash');
```
使用方法がわかりませんでした🙇
`assets`の画像を入れてみましたが、変わらなかったため、どういった実装かがわかりませんでした💦

もう少しコードを見てみて、わかりましたら更新します。


## Androidのみでできること


### スクリーンショットをすると黒くなる　＋　マルチタスク画面で黒くなる

```dart
await ScreenProtector.protectDataLeakageOn();
```

| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/2cf707ac-9d79-d669-9ba8-786aee561343.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/ec240af5-ad11-03d8-3452-cb06a9176c5a.png">| 


### スクリーンショット無効をオフにする

```dart
await ScreenProtector.protectDataLeakageOff();
```


| スクリーンショット | マルチタスク画面 |
| ---- | ---- | 
| <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/428440ef-ecb7-0045-56bc-02f70abe08b6.png"> | <img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/b4ec5722-5ce2-53c5-bc30-eaf9ea7ce731.png">| 



 # 記載の例 

 ```
 flutter pub add screen_protector
 ```
```yaml:pubspec.yaml
dependencies:
  screen_protector: ^1.4.1
```

 ```dart:main.dart
 import 'package:flutter/material.dart';
import 'package:screen_protector/screen_protector.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const PreventScreenshotScreen(),
    );
  }
}

class PreventScreenshotScreen extends StatefulWidget {
  const PreventScreenshotScreen({Key? key}) : super(key: key);

  @override
  PreventScreenshotScreenState createState() => PreventScreenshotScreenState();
}

class PreventScreenshotScreenState extends State<PreventScreenshotScreen> {
  @override
  void initState() {
    _preventScreenshotOn();
    super.initState();
  }

  @override
  void dispose() {
    _removeListenerPreventScreenshot();
    _preventScreenshotOff();
    super.dispose();
  }

  void _preventScreenshotOn() async =>
      await ScreenProtector.preventScreenshotOn();

  void _preventScreenshotOff() async =>
      await ScreenProtector.preventScreenshotOff();

  void _removeListenerPreventScreenshot() async {
    ScreenProtector.removeListener();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: const Center(
        child: Text('この画面はスクリーンショットしたくない'),
      ),
    );
  }
}

 ```



# 開発メモ
- 実機じゃないと確認ができなさそうでした。
- スクリーンショットの防止＋マルチタスク画面の防止の２つをすることが望ましい。


# 最後に

触ってみましたが、情報漏洩対策はできるとはいえ、まだまだネイティブにしかできなさそうなこともあることを知れました。

メソッドチャンネルも使用して開発をしているっぽいのでもう少しじっくりみて学んでいきたいなと思います！