プログラム関係の備忘録。技術系記事1000記事以上を目指すブログ

react-nativeでアプリ内データのCSV出力機能の実装方法

react-nativeでアプリ内データをCSV出力

私が勉強がてら作っているアプリはRealmを使っているため、データのエクスポート機能が欲しいところ。
そこで今回はアプリ内データをCSVファイルでデバイスのストレージに出力する機能を追加してみました。
Androidでの実機確認済み。

react-nativeでアプリ内データをCSV出力するために必要なこと

必要なことは大きく3つ

  • rn-fetch-blobを使う
  • PermissionsAndroid APIを利用する
  • CSV出力処理を実装する

以下で順番に解説をしていきます。

rn-fetch-blobを使う

参考にした記事内ではreact-native-fetch-blobとなっていますが、現在はrn-fetch-blobにフォークされているとのことなので後者を使います。
https://github.com/joltup/rn-fetch-blob

まずはお決まりのパッケージのインストール

npm install --save rn-fetch-blob

ネイティブモジュールとのリンクを行う

react-native link rn-fetch-blob

参考記事
https://stackoverflow.com/questions/45660768/how-to-create-and-save-csv-files-in-react-native

PermissionsAndroid APIを利用する

アプリケーションでファイル出力の権限を付与する機能を実装するために使用します。

Android5.0以下のデバイスの場合は「アプリ起動時に権限を付与する」のでAndroidManifest.xmlに設定値を加えるのですが、Android6.0以降は「アプリ実行中に権限を付与する」仕組みに変わっているようです。

そのためAndroid6.0以降はAndroidManifest.xmlに書いても意味がなく、PermissionsAndroid APIを利用する必要があります。

この記事ではAndroid6.0以降に対応させるためPermissionsAndroid APIでの実装をしていきます。
5.0以下の場合のAndroidManifest.xmlの設定方法はrn-fetch-blobのdocに書いてあります。
https://github.com/wkh237/react-native-fetch-blob

PermissionsAndroid APIの利用サンプル

import { PermissionsAndroid } from 'react-native';

const requestWriteStragePermission = async () => {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
        {
          title: "外部ストレージへのアクセス権限",
          message: " CSVファイルを出力するためには外部ストレージへの書き込み権限を許可する必要があります。",
          buttonNeutral: "Ask Me Later",
          buttonNegative: "Cancel",
          buttonPositive: "OK"
        }
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        writeCSV()
      } else {
        console.log("Camera permission denied");
      }
    } catch (err) {
      console.warn(err);
    }
};

外部ストレージの書き込み権限に限らず様々な権限付与の実装が行えます。

  • READ_CALENDAR: ‘android.permission.READ_CALENDAR’
  • WRITE_CALENDAR: ‘android.permission.WRITE_CALENDAR’
  • CAMERA: ‘android.permission.CAMERA’
  • READ_CONTACTS: ‘android.permission.READ_CONTACTS’
  • WRITE_CONTACTS: ‘android.permission.WRITE_CONTACTS’
  • GET_ACCOUNTS: ‘android.permission.GET_ACCOUNTS’
  • ACCESS_FINE_LOCATION: ‘android.permission.ACCESS_FINE_LOCATION’
  • ACCESS_COARSE_LOCATION: ‘android.permission.ACCESS_COARSE_LOCATION’
  • RECORD_AUDIO: ‘android.permission.RECORD_AUDIO’
  • READ_PHONE_STATE: ‘android.permission.READ_PHONE_STATE’
  • CALL_PHONE: ‘android.permission.CALL_PHONE’
  • READ_CALL_LOG: ‘android.permission.READ_CALL_LOG’
  • WRITE_CALL_LOG: ‘android.permission.WRITE_CALL_LOG’
  • ADD_VOICEMAIL: ‘com.android.voicemail.permission.ADD_VOICEMAIL’
  • USE_SIP: ‘android.permission.USE_SIP’
  • PROCESS_OUTGOING_CALLS: ‘android.permission.PROCESS_OUTGOING_CALLS’
  • BODY_SENSORS: ‘android.permission.BODY_SENSORS’
  • SEND_SMS: ‘android.permission.SEND_SMS’
  • RECEIVE_SMS: ‘android.permission.RECEIVE_SMS’
  • READ_SMS: ‘android.permission.READ_SMS’
  • RECEIVE_WAP_PUSH: ‘android.permission.RECEIVE_WAP_PUSH’
  • RECEIVE_MMS: ‘android.permission.RECEIVE_MMS’
  • READ_EXTERNAL_STORAGE: ‘android.permission.READ_EXTERNAL_STORAGE’
  • WRITE_EXTERNAL_STORAGE: ‘android.permission.WRITE_EXTERNAL_STORAGE’

詳しくは以下。
https://reactnative.dev/docs/permissionsandroid

CSV出力処理を実装する

外部ファイルにrequestWriteStragePermissionの関数を作りました。
そのなかでwriteCSV()を呼ぶようにしていますので、最後にCSVの出力処理を作ります。

import RNFetchBlob from 'rn-fetch-blob'

const writeCSV = () => {
    try {
        const headerString = 'event,timestamp\n';
        const rowData = "テスト,テストA\nテスト,テストB"
        const pathToWrite = `${RNFetchBlob.fs.dirs.DownloadDir}/data.csv`;
        console.log(pathToWrite)
        const csvString = `${headerString}${rowData}`;
        RNFetchBlob.fs
            .writeFile(pathToWrite, csvString, "utf8")
            .then(() => {
                alert("File updated succesfully");

            })
            .catch(error => alert(error));

    } catch (error) {
        // Error retrieving data
    }
}

検証のためcsvは固定値で適当に入れてますが、実際にはwriteCSV()の引数でデータを受け渡しし、必要であればJSON→CSVに変換して書き込む処理を追加する形になります。

最後にrequestWriteStragePermissionを任意のコンポーネントに仕込めば完成