ReactNativeでAndroid対応する話

前提

ReactNativeでiOS版のアプリをリリースしていて、Android版をリリースする話

トラブルシューティング

Build.VERSION_CODES.Q が存在しないエラー

compileSdkVersionを29以上にすると解決

メモリー足りないエラー

Execution failed for task ':app:mergeExtDexDebug'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > java.lang.OutOfMemoryError (no error message)

コメントアウトを解除した

org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

64K問題?

Cannot fit requested classes in a single dex file (# methods: 154819 > 65536 ; # fields: 126457 > 65536)

multiDexEnabled trueを追加

facebook sdkのエラー

The SDK has not been initialized, make sure to call FacebookSdk.sdkInitialize() first.

確かにまだ設定してないからなー。

FirebaseのAuthentication使ってるからそこら変の設定がもろもろ足りない。

React Native Firebase

https://rnfirebase.io/

Twitterの設定

中で使ってるライブラリーはこれ
react-native0.62.2使ってるから、gradleの追加や、MainApplication.javaへの追加は不要

Appleでログイン

使っているライブラリーはこちら

iOS開発時は1.0.0。Android対応は2.0.0からので、バージョンを最新にする(2.1.0)

  const response = await appleAuthAndroid.signIn();

ドキュメント通り実装しても、responseで取得できるのはid_tokenだけ。

{nonce: "XXXXXXXXX", state: "XXXXXXXXXXXX", id_token: "XXXXXXXXX", code: "XXXXXXXXXXX"} 

id_tokenはJWTなので、decodeすると、(便利なサイト https://jwt.io/)

{

  "iss": "https://appleid.apple.com",

  "aud": "xxxxxxxxxxxxxxxxxxxxxx",

  "exp": 1607694557,

  "iat": 1607608157,

  "sub": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

  "nonce": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",

  "c_hash": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

  "email": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

  "email_verified": "true",

  "is_private_email": "true",

  "auth_time": 1607608157,

  "nonce_supported": true

}

こんな感じ

で?

Firebaseの本家の(ReactNativeじゃないほう)のAndroidのドキュメントをみてみる

https://firebase.google.com/docs/auth/android/apple

始めの方はSDK使えば簡単にできるようなことが書いてある。

「高度: 手動によるログインフローの処理」ここが参考になるかも

https://firebase.google.com/docs/auth/android/apple#advanced_handle_the_sign-in_flow_manually

AuthCredential credential =  OAuthProvider.newCredentialBuilder("apple.com")

    .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)

    .build();

mAuth.signInWithCredential(credential)

appleIdTokenとか書いてあるので、それ渡せば良い? appleIdTokenはAppAuthから取得する?んー。これも違うような。

Web版をみてみる。

https://firebase.google.com/docs/auth/web/apple


続きはまた明日・・・ 

 


DataStoreの辛いところ

Cloud Funcsionsを個別に呼び出す(リトライ処理)

# 概要

Cloud FunctionsをGCSに保存したタイミングで、画像データを変更してもう一度GCSにアップロードしたい。

## WebUIから実行

関数をテストから実行する










dataで必要なパラメータを指定。
今回はbucketとfileを使っていたのでその2つを指定する



以下は実際に読んでるコード

```
exports.helloWorld = (event, callback) => {
  const object = event.datat;
  console.log(`Bucket: ${object.bucket} File: ${object.name}`);
```

## コマンドラインからの実行

関数名、リージョンを指定して呼び出す

```
gcloud --project [PROJECT-NAME] beta functions call helloWorld --region asia-northeast1 --data '{"bucket":"hogehoge","name":foo.png"}'
```

Cloud Functionsを使ってImageMagickを使って画像変換してみる

JSからImageMagickを使う

nodeでImageMagickを使うライブラリがある

gm https://github.com/aheckmann/gm

こちらを使って行う

const gm = require("gm").subClass({ imageMagick: true });
gm('image.png')
  .colorspace("cmyk")
  .write('image.tif')


GCSからダウンロード

渡された引数にGCSのオブジェクトが渡されるのでそれを使ってダウンロードする

const object = event.data;
const file = storage.bucket(object.bucket).file(object.name);
const tempLocalPath = `/tmp/${path.parse(file.name).base}`;
file.download({ destination: tempLocalPath })
  .catch(err => {
    console.error("Failed to download file.", err);
    return Promise.reject(err);
  })
  .then(() => {
    console.log(`Image ${file.name} has been downloaded to ${tempLocalPath}.`);
  })

GCSへアップロード

ダウンロードの続きでbucketに対してuploadを行う

const newFileName = file.name.replace(".png", ".tif");
file.bucket
        .upload(tempLocalPath, {
          destination: newFileName,
          metadata: { contentType: "image/tiff" }
        })
        .catch(err => {
          console.error("Failed to upload cmyk image.", err);
          return Promise.reject(err);
        });

デプロイ

プロジェクトの指定

--project [PROJECT NAME]

regionの指定

--region asia-northeast1

デフォルトだとus-central1になる

実際のコマンドは以下

gcloud --project [PROJECT] beta functions deploy pngToCMYKConverter --region asia-northeast1 --trigger-resource sheet-yournail-staging --trigger-event google.storage.object.finalize


他のリージョンにDeployしてモジュールを削除

gcloud --project [PROJECT] beta functions deploy pngToCMYKConverter

参考
https://cloud.google.com/functions/docs/tutorials/imagemagick?hl=ja

.mitmproxyを使ってHTTPSの通信を確認

Firebase Functionsの登録

ReactNativeのリリース自動化、CodePush x CircleCI

iOSシミュレータでURLスキームで起動する方法

URLスキームの実行方法

simctlがXcode6から付属しているのでそれを実行する

$ xcrun simctl openurl booted hoge:/foo/bar

simctl

シミュレータをコントロールできる

$ xcrun simctl
usage: simctl [--noxpc] [--set ] [--profiles ] ...
       simctl help [subcommand]
Command line utility to control the Simulator

For subcommands that require a argument, you may specify a device UDID
or the special "booted" string which will cause simctl to pick a booted device.
If multiple devices are booted when the "booted" device is selected, simctl
will choose one of them.

Subcommands:
        create              Create a new device.
        clone               Clone an existing device.
        upgrade             Upgrade a device to a newer runtime.
        delete              Delete a device or all unavailable devices.
        pair                Create a new watch and phone pair.
        unpair              Unpair a watch and phone pair.
        pair_activate       Set a given pair as active.
        erase               Erase a device's contents and settings.
        boot                Boot a device.
        shutdown            Shutdown a device.
        rename              Rename a device.
        getenv              Print an environment variable from a running device.
        openurl             Open a URL in a device.
        addmedia            Add photos, live photos, or videos to the photo library of a device.
        install             Install an app on a device.
        uninstall           Uninstall an app from a device.
        get_app_container   Print the path of the installed app's container
        launch              Launch an application by identifier on a device.
        terminate           Terminate an application by identifier on a device.
        spawn               Spawn a process on a device.
        list                List available devices, device types, runtimes, or device pairs.
        icloud_sync         Trigger iCloud sync on a device.
        pbsync              Sync the pasteboard content from one pasteboard to another.
        pbcopy              Copy standard input onto the device pasteboard.
        pbpaste             Print the contents of the device's pasteboard to standard output.
        help                Prints the usage for a given subcommand.
        io                  Set up a device IO operation.
        diagnose            Collect diagnostic information and logs.
        logverbose          enable or disable verbose logging for a device

デバイス確認

$ xcrun simctl list
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
・・・
== Runtimes ==
iOS 9.3 (9.3 - 13E233) - com.apple.CoreSimulator.SimRuntime.iOS-9-3
iOS 10.3 (10.3.1 - 14E8301) - com.apple.CoreSimulator.SimRuntime.iOS-10-3
iOS 11.2 (11.2 - 15C107) - com.apple.CoreSimulator.SimRuntime.iOS-11-2
tvOS 11.2 (11.2 - 15K104) - com.apple.CoreSimulator.SimRuntime.tvOS-11-2
watchOS 4.2 (4.2 - 15S100) - com.apple.CoreSimulator.SimRuntime.watchOS-4-2
== Devices ==
-- iOS 9.3 --
    iPhone 4s (269EF856-87D0-41E1-B303-CE36A65E712E) (Shutdown)
    iPhone 5 (35804246-54E9-47BC-AFC2-83E639744F7B) (Shutdown)
    iPhone 5s (AFAA2A65-FB92-441B-820F-CE7C97BE6AF1) (Shutdown)
    iPhone 6 (98529E42-EE5A-404F-B476-27C61737AD12) (Shutdown)
・・・
-- iOS 11.2 --
    iPhone 5s (A698838A-704E-43C6-AE8B-1E81AB0E1311) (Shutdown)
    iPhone 6 (6412A351-97A7-49A1-B860-A51EDB631C48) (Booted)
    iPhone 6 Plus (8AD29BA9-06A5-4036-BA95-477D05FE30AB) (Shutdown)
    iPhone 6s (6048B53E-87FF-429C-A5A1-5BE62CB8C2F4) (Shutdown)

Open URL

$ xcrun simctl openurl
Usage: simctl openurl

deviceとURLを指定する

deviceは先ほどしらべたUUIDでも良いし、bootedと指定しても良い

react-navigationのバージョンアップ

react-navigationのバージョンをあげてもう一度ドキュメントをよみなおしてみる

Headerのボタンの挙動

https://reactnavigation.org/docs/header-buttons.html

navigationOptionがstaticメソッドのため、navigation.state.paramsを使ってやりとりを行う

static navigationOptions = ({ navigation }) => { const params = navigation.state.params || {}; return { headerTitle: <LogoTitle />, headerRight: ( <Button onPress={params.increaseCount} title="+1" color="#fff" /> ), }; }; componentWillMount() { this.props.navigation.setParams({ increaseCount: this._increaseCount }); } state = { count: 0, }; _increaseCount = () => { this.setState({ count: this.state.count + 1 }); };


didFocusイベントが取れる?



子のコンポーネントにnavigationを渡す方法

いちいちnavigationを渡さなくて良いので便利


import React from 'react'; import { Button } 'react-native'; import { withNavigation } from 'react-navigation'; class MyBackButton extends React.Component { render() { return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />; } } // withNavigation returns a component that wraps MyBackButton and passes in the // navigation prop export default withNavigation(MyBackButton);


DeepLink

前回のバージョンではTabNavigationを使うと動かなかったけど、今回は動くようになったのかな?あとで試す



ESLintとFlowができること

react nativeをやっていて、ESLintとFlowについて


ESLint


静的解析ツール。
括弧や、スペース、空行などスタイルの統一も可能。
ルールを個別で指定可能

airbnbの設定など公開されている

エディターとの連携次第で自動フォーマット可能


例えばこんな感じ

先頭に空行はダメ




後ろで定義している変数を使うのもダメ






Flow


静的型付けツール。
実行前にチェックが可能

Componentやメソッドの引数の型を定義する

type UserType = {
  name: string;
  age: number;
}

type Props = {
  user: UserType,
  text: string,
};


class Foo extends Component {
  componentDidMount() {

  }

  render() {
    const { user, text } = this.props;
    return (
     
        {user.name}
        {user.age}
        { user.age < 20 ? '未成年' : '成人' }
        {text}
     
    );
  }
}

ageがnumberではなく、文字列で指定した場合







ReactNativeでAndroid対応する話

前提 ReactNativeでiOS版のアプリをリリースしていて、Android版をリリースする話 トラブルシューティング Build.VERSION_CODES.Q が存在しないエラー compileSdkVersionを29以上にすると解決 メモリー足りないエラー Execu...