Honmushi blog
2019/03/14

React Native + Expoによるアプリの雛形

React NativeとExpoを利用してクロスプラットフォームなアプリを作成しています。

とりあえず起動できるだけの雛形があるので、まとめておこうと思います。 この雛形を参考にして立ち上げればとりあえず動くので、ここから必要な機能を作っていくことができます。

同じようにアプリ作ってみようという人は参考にしてみてください。

最低限導入しているもの

この雛形では最低限の機能として以下が使えるようになっています。それぞれの詳細は各ドキュメントを確認してください。

  • Admob
    広告を表示するために取り入れています。 広告出す場合はプライバシーポリシーの記載が必須です。無いとストアから削除されるので気をつけましょう。

    Admobのアカウントを作成して、広告IDを取得することで利用できます。

  • React Navigation
    タブなどによる画面遷移をサポートしてくれます。なくてもアプリは作れますがあると便利です。

  • Style
    コンポーネントの見た目をまとめて定義するのに使います。こちらもなくてもアプリは作れますが、スタイルの管理がややこしくなるので、間違いなく使ったほうがいいです。
    とりあえず別ファイルに切り出して実装する方針にしています。

create-react-native-appを実行する

コマンドラインでcreate-react-native-appを実行します。コマンドがまだない場合はnpmでインストールしましょう。react-nativeやexpoも必要なのでinstallしておきます。

上記のコマンドを実行すると必要な雛形ができます。そこに今回紹介する雛形を取り込めば、とりあえず動くものになります。npm startを実行すればexpoによって実機での確認ができます。

実機にExpoというアプリをインストールしておく必要があります。ストアで検索して入れておくと良いです。

以下の記事で取り上げていますので参考にどうぞ
React NativeとExpoでアプリをリリース

雛形

app.js

React-Navigationを利用しています。コンポーネントとしてページを作成して、設定することになります。ソースを見れば直感的にわかるかなと思います。

スタイル定義、プライバシーポリシーページ、フッター広告枠を外部ファイルとして切り出して定義しています。

import React from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';
import { Constants } from 'expo';
import { createStackNavigator,createAppContainer } from 'react-navigation';

import styles from './common/style.js';
import Policy from './common/policy.js';
import FooterAdd from './common/add.js';


// メインコンポーネント
class Home extends React.Component {
  static navigationOptions = {
    title: 'タイトル',
    headerTinColor:'rgba(0, 0, 0, 0.6)',
  };

  constructor(props){
    super(props);
    this.state ={};
  }
  _keyExtractor = (item, index) => item.id.toString()

  render() {
    return (
      <View style={styles.container}>
        <Text 
          style={{paddingBottom:30}}
          onPress={() => {
            this.props.navigation.navigate('Policy');
          }}
        >
          プライバシーポリシーはこちら
        </Text>
        <FooterAdd/>
      </View>
    );
  }
}


const RootStack = createStackNavigator(
  {
    Home: { screen: Home },
    Policy: { screen: Policy },
  },
  {
    initialRouteName: 'Home',
  }
);

common/policy.js

アプリのプライバシーポリシーページです。ページへのリンクを貼るだけでもいいそうなのですが、アプリ内に設置するとして、このように実装しています。

Admobを利用しているので、その部分は明記しています。Firebaseは利用していないので書いてません。必要であれば追加しましょう。

import * as React from 'react';
import { StyleSheet, Text,View, ScrollView , Linking} from 'react-native';

class Policy extends React.Component {
  static navigationOptions = {
    title: 'プライバシーポリシー',
    headerStyle:{color: 'rgba(0, 0, 0, 0.6)'},
    headerTinColor:'white',
  };
  constructor(props){
    super(props);
  }

  render() {
    return (
      <View style={styles.container}>
        <ScrollView style={styles.mainView}>
          <View style={{paddingBottom:100}}>
            <Text style={styles.textTitle}>アプリケーション・プライバシーポリシー</Text>
            <Text style={styles.textDisc}>
              {`本アプリケーションを利用するにあたり、以下のプライバシーポリシーが適用されます。 お客様は、本アプリケーションを利用することにより、本アプリケーション・ポリシーに同意したものとみなされます。
          
本アプリケーション・ポリシーにおいて、個人情報とは、個人情報保護法により定義された個人情報及び特定の個人情報に結びついて使用される個人に関する属性情報(メールアドレス・利用履歴・利用料金等)を意味するものとします。`}
            </Text>
          
          <Text style={styles.textTitle}>個人情報の管理</Text>
          <Text style={styles.textDisc}>
本アプリではお客さまの個人情報を保持するにあたり、個人情報への不正アクセス・紛失・破損・改ざん・漏洩などを防止するために適切な措置を講じ、安全対策を実施し個人情報の管理を行ないます。
          </Text>
          
          <Text style={styles.textTitle}>個人情報の利用目的</Text>
          <Text style={styles.textDisc}>
本アプリでは、広告配信ツールとしてAdMob(Google Inc.)を使用しており、AdMobがご利用者の情報を自動取得する場合がございます。取得する情報、利用目的、第三者への提供等につきましては、以下の広告配信事業者のアプリケーション・プライバシーポリシーのリンクよりご確認ください。
          </Text>
          <Text style={styles.textDisc} 
            onPress={() => {
              this.props.navigation.navigate('SelectStop');
              const url = 'https://policies.google.com/technologies/ads?hl=ja'
              Linking.openURL(url).catch(err => console.error('An error occurred', err));
            }}
          >
          {`Google 広告に関するポリシー
https://policies.google.com/technologies/ads?hl=ja`}
          </Text>
          <Text style={styles.textTitle}>個人情報の第三者への開示・提供の禁止</Text>
          <Text style={styles.textDisc}>
          {`お客さまよりお預かりした個人情報を適切に管理し、次のいずれかに該当する場合を除き、個人情報を第三者に開示いたしません。
          
・お客さまの同意がある場合
・法令に基づき開示することが必要である場合
・司法または行政機関から開示を求められた場合`}
          </Text>
          <Text style={styles.textTitle}>個人情報の安全対策</Text>
          <Text style={styles.textDisc}>
個人情報の正確性及び安全性確保のために、十分なセキュリティに万全の対策を講じ、万が一、問題が発生した場合は、速やかに適当な是正対策をします。
          </Text>
          <Text style={styles.textTitle}>法令、規範の遵守と見直し</Text>
          <Text style={styles.textDisc}>
保有する個人情報に関して適用される日本の法令、その他規範を遵守するとともに、本ポリシーの内容を適宜見直し、その改善に努めます。
          </Text>
          </View>
        </ScrollView>
      </View>
    );
  }
}

export default Policy;

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  mainView: {
    backgroundColor: '#EEEEEE',
    paddingTop:10,
  },
  textTitle: {
    fontSize: 14,
    marginLeft:15,
    marginTop: 30,
  },
  textDisc: {
    fontSize: 18,
    marginLeft:30,
    marginRight:30,
    marginTop: 10,
    color: 'rgba(0, 0, 0, 0.6)',
  },
});

common/style.js

import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  list: {
    width:"100%",
    padding:20,
  },
  
  listItem: {
    flexDirection:"row",
    borderColor: "rgba(0,0,0,0.2)",
    borderBottomWidth: 1,
    paddingHorizontal: 10,
    paddingVertical:10,
    alignItems:"center",
  },
  
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    color: 'rgba(0,0,0,0.6)',
  },
});

export default styles;

このファイルでスタイルを定義して、利用します。コンポーネントの呼び出し時に指定することもできますが、このファイルにまとめておいたほうがラクなのではないかと思います。

複数のスタイルを併用する場合は配列にして渡すと、両方のスタイルがコンポーネントに反映されます。

<Text style={[styles.list,styles.listItem]}>テキスト</Text>

common/add.js

import React from 'react';
import { View } from 'react-native';
import { AdMobBanner } from 'expo';

class FooterAdd extends React.Component {
  render(){
    return (
      <View >
        <View >
          <AdMobBanner
            adUnitID="Admobで広告を作成してそのIDをここに設定します" // Test ID, Replace with your-admob-unit-id
          />
        </View>
      </View>
    )
  }
}

export default FooterAdd;

上記をimportしておけば、コンポーネントとして利用できます。限りなく簡潔になっています。とりあえずアプリの下部にAdmobを出すだけならこんな感じでしょう。

app.json

app.jsonは以下のようになります。バージョンなどは自身の環境で合わせてください。 slugなどの文字列も自身の使いたいものに変更します。

app.jsonを設置すればexpo-cli buildコマンドでビルドもできます。実際にストアにアップロードするAPKが生成できます。

とりあえずAndroid版についてはこんな感じでリリースまでできることを確認しました。iOSについても引き続き実験しようと考えています。

{
  "expo": {
    "name": "アプリの名前",
    "slug": "expoで表示されるslug",
    "privacy": "unlisted",
    "sdkVersion": "32.0.0",
    "platforms": [
      "ios",
      "android"
    ],
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "updates": {
      "fallbackToCacheTimeout": 0
    },
    "assetBundlePatterns": [
      "**/*"
    ],
    "android": {
      "package": "google play storeで表示されるID",
      "permissions": [],
      "versionCode": 1
    },
    "ios": {
      "supportsTablet": true
    }
  }
}

おわりに

React NativeとExpoを利用したアプリの雛形をまとめました。これを使えば、とりあえず動くものを見ながら開発できると思います。実際にはいろいろなコンポーネントを利用しながら開発することになると思います、よく使うものは別ファイルにして切り出すなどして再利用性を高めておくと良いです。

Expoを利用すると簡単に開発ができるのでとても便利です。ネイティブなコードを使った開発もやってみたいのですが、大変そうなのでしばらくはこの環境で進めようと思います。 React Nativeと比較される存在としてFlutterというものもあります。こちらも一度試してみます。

  • このエントリーをはてなブックマークに追加
HOMEPROFILEPRIVACY POLICY