【Ionic3】Androidで通知をタップでファイルを開く

Androidアプリでよくみる、ダウンロード中に通知領域にプログレスバーを表示して、ダウンロード完了後に通知をタップすると該当ファイルが開くという動作をIonic3で実現しようと思います。

以前の記事では、cordova-plugin-progress-notificationを使用して通知領域にプログレスバーを表示しました。

しかし、使用したプラグインがIonic3が公式でサポートしておらず、機能も限定的でプログレスバーを表示する機能しかありませんでした。

Ionic3のリファレンスをよくよくみてみると、公式でサポートされている通知プラグインは、Local Notificationsというプラグインがありました。

ですので、今回はLocal Notificationsの使い方を紹介します。

今回やりたいことに必要なプラグインは、ファイル操作などを行う、File, File Transfer, File Opener, Android Permissionsが必要です。

プラグインのインストール

Fileプラグイン

Fileプラグインはローカルフォルダへのアクセスを行います。

$ ionic cordova plugin add cordova-plugin-file
$ npm install --save @ionic-native/file
引用元: Ionic Docs File

File Transferプラグイン

File Transferプラグインは外部からファイルをダウンロードするために使用します。

$ ionic cordova plugin add cordova-plugin-file-transfer
$ npm install --save @ionic-native/file-transfer
引用元: Ionic Docs File Transfer

File Openerプラグイン

File Openerプラグインはファイルをデフォルトのアプリケーションで開くことができます。 例えば、PDFファイルを開きたいときには、ユーザーが端末にインストールしているPDFビューアで開くことができます。

$ ionic cordova plugin add cordova-plugin-file-opener2
$ npm install --save @ionic-native/file-opener
引用元: Ionic Docs File Opener

Android Permissionsプラグイン

Android Permissionsプラグインは、アクセス許可を得るために必要です。 AndroidのDownloadフォルダは、各アプリ固有の領域ではなく、ルートディレクトリなので、アクセスするためにはユーザーの許可が必要です。

$ ionic cordova plugin add cordova-plugin-android-permissions
$ npm install --save @ionic-native/android-permissions
引用元: Ionic Docs Android Permissions

Local Notificationsプラグイン

Local NotificationsはAndroidの通知領域へアクセスするためのプラグインです。 今回はダウンロードボタンをタップした時に通知を使用しますが、日時を指定して通知を表示したり、通知タップや通知削除の動作にイベント登録ができたりと、多機能なプラグインです。

$ ionic cordova plugin add cordova-plugin-local-notification
$ npm install --save @ionic-native/local-notifications
引用元: Local Notifications

プラグインの使い方

下準備ができました。早速コードを書いてみます。

以下の流れを作成します。

「ダウンロード」ボタンタップ ダウンロード開始 通知領域にダウンロード進捗状況を表示 ダウンロード完了を通知領域に表示 通知タップでダウンロードしたファイルを開く

Viewのコード

<!-- home.html -->
<ion-content padding>
  <div padding>
    <button ion-button primary (click)="download(1)" tappable>PDF1ダウンロード</button>
  </div>
  <div padding>
    <button ion-button primary (click)="download(2)" tappable>PDF2ダウンロード</button>
  </div>
</ion-content>

Componentのコード

// home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer';
import { File } from '@ionic-native/file';
import { AndroidPermissions } from '@ionic-native/android-permissions';
import { FileOpener } from '@ionic-native/file-opener';
import { LocalNotifications } from '@ionic-native/local-notifications';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor
  (
    public navCtrl: NavController,
    private transfer: FileTransfer,
    private file: File,
    private androidPermissions: AndroidPermissions,
    private fileOpener: FileOpener,
    private localNotifications: LocalNotifications
  ) {}

  download(id) {
    const fileName = 'sample' + id + '.pdf';
    const url = 'https://www.example/' + fileName;
    const fileTransfer: FileTransferObject = this.transfer.create();

    // アクセス許可を求める
    this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE)
    .then(status => {
      // 通知を表示
      this.localNotifications.schedule({
        id: id,
        title: fileName + 'をダウンロード中',
        text: '0%',
        progressBar: { value: 0 },
        sticky: true // ダウンロード中は通知を削除できないようにする
      });

      // ダウンロード処理
      fileTransfer.download(url, this.file.externalRootDirectory + 'Download/'+ fileName)
      .then((entry) => {
        // 通知領域に完了を伝える
        this.localNotifications.update({
          id: id,
          title: fileName + 'のダウンロード完了',
          text: '100%',
          progressBar: { value: 100 },
          sticky: false
        });

        // 通知領域をタップした時のイベントを登録
        this.localNotifications.on('click')
        .subscribe(
          (notification) => {
            // 複数の通知があると全てのclickが発火するので、idで判定
            if (notification.id === id) {
              // ダウンロードしたファイルを開く
              this.fileOpener.open(entry.nativeURL, 'application/pdf')
              .then(() => {
                // 通知を削除
                this.localNotifications.clear(id);
              })
              .catch(e => console.log('Error opening file', e));
            }
          }
        );
      })
      .catch((error) => {
        console.error('download error: ' + error);
        this.localNotifications.update({
          id: id,
          title: fileName + 'のダウンロード失敗',
          sticky: false
        });
      });

      // ダウンロード中、通知領域を更新する
      fileTransfer.onProgress(((e) => {
        const percentage = Math.floor(e.loaded / e.total * 100);
        // パフォーマンスを考慮し、1桁目が0か5の時だけ更新する
        if (percentage % 5 === 0 || percentage % 5 === 5) {
          this.localNotifications.update({
            id: id,
            text: percentage + '%',
            progressBar: { value: percentage }
          });
        }
      }));
    })
    .catch(err => this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE));
  }
}

fileTransfer.download()

fileTransfer.download()は外部ファイルを指定したディレクトリに保存することができます。 保存時のファイル名は自分で命名しますが、ダウンロード元のファイル名をそのまま使いたい場合は、正規表現などで元のファイル名を取得する処理を作成する必要があります。 今回はsample1.pdfといった仮の名前で保存しています。

localNotifications.schedule()

localNotifications.schedule() で通知の設定を行います。 scheduleというメソッド名から察しているかと思いますが、ここに通知を表示する日時を指定して、特定の日時に通知を表示することもできます。 今回は即時に表示させます。

localNotifications.update()

localNotifications.update()で通知の内容を更新します。 schedule()で、idを指定して複数の通知のスケジュールを登録することができるため、update()でもidを指定して更新したい通知を特定します。 今回はプログレスバーを更新するため、fileTransfer.onProgress()でダウンロードが進行するたびに呼び出しています。

localNotifications.on()

localNotifications.on()は通知を操作した時のイベント登録を行えます。 localNotifications.on('click')とすると通知をタップした時に発火します。 他にも、add, trigger, clear, cancel, update, clearall, cancelall といったイベントがあります。 今回はclickイベントに、ファイルを開く処理を登録しています。 私のやり方が間違っているのかもしれませんが、複数の通知スケジュールを登録してあると、全てのclickイベントが発火してしまうので、idを比較することで、該当の通知のみ処理を行うようにしてあります。

fileOpener.opne()

fileOpener.opne()はファイルを開いてくれます。 ファイルパスとMIME Typeを指定する必要があります。 今回はPDFファイル固定にしてあるので、MIME Typeはapplication/pdfを決め打ちしていますが、他のファイル形式を開く場合は、MIMETypeを可変にする仕組みを作る必要があります

最後に

Ionic公式がサポートしているプラグインだけあって、ローカル通知としての機能が充実していますね。

私は、Local Notificationsプラグインにたどり着くまでに、cordova-plugin-progress-notificationプラグインに行きついたり、少し遠回りをしてしましました。

「通知領域にプログレスバーを表示したい!」と思い、グーグルで検索した結果です。

Ionicのリファレンスをみれば、アプリ開発に必要なものは大体記載されています。

まず初めにIonicのリファレンスを調べることが一番の近道なんだと痛感しました。

人気記事すべて表示

ハイブリッドアプリすべて表示