react nativeでfirebaseのネイティブSDKを操作する

## 自己紹介

![](https://qiita-image-store.s3.amazonaws.com/0/7185/profile-images/1482825373)

- uryyyyyyy: しばたこ
- 本業はアドテクでScala/React/TypeScript
- 副業でReact Native

最近そこそこバズった記事→[ReduxでのMiddleware不要論](http://qiita.com/uryyyyyyy/items/d8bae6a7fca1c4732696)

---

## 話すこと

- React NativeでNative APIを扱ってみる
- Swift/Kotlinでやってみる

お題として今回はFirebase SDKとGoogle認証を扱ってみます。
Firebaseのイベントトラッキングの方ではNative Moduleを扱う話、
認証周りでは、もう少し拡張してView/ViewControllerを扱ってみる話をします。

完成形

- [iOS](https://github.com/uryyyyyyy/ReactNativeSample_iOS/tree/firebase-auth)
- [Android](https://github.com/uryyyyyyy/ReactNativeSample_android/tree/firebase-auth)

---

## ところで

FirebaseにはNativeのSDKとWebのSDKがあるのは大丈夫ですよね？
ちゃんと調べてないですが、違いはAnalyticsが弱いとかPush通知とかだと思います。

せっかくのReact Nativeなので、今回はNativeのSDKの話をします。

---

## ところで2

アプリで認証するときに、いちいちWebViewでグーグルにログインさせるのはダサいですね？
iOS/Androidともに、OS側で既にログインされていればそのまま連携できる仕組みがあります。

せっかくのReact Nativeなので、今回はNativeでの話をします。

---

## 準備

---

### iOS/Androidのライブラリ周りの準備

#### iOS

- Podsの設定をする。
- Podfileで依存ライブラリを書く

### Android

- デフォルトではパッケージ名が `com.<app name>` とかなので、直す
  - AndroidManifestのpackage
  - build.gradleのapplicationIdを直す
- build.gradleで依存ライブラリを書く

---

### コードをSwift/Kotlinへ変更する

- iOS
  - AppDelegateをswiftに書き直す
  - XX-Bridging-Header.hを用意する

```swift/AppDelegate.swift
import UIKit

@objc(AppDelegate)
class AppDelegate: UIResponder, UIApplicationDelegate {
  
  var window: UIWindow?
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow.init(frame: UIScreen.main.bounds)
    
    //----RCTRootView----
    let settings = RCTBundleURLProvider.sharedSettings()
    let jsCodeLocation: URL = settings!.jsBundleURL(forBundleRoot: "index.ios", fallbackResource: nil)
    let rootView = RCTRootView.init(bundleURL: jsCodeLocation as URL!, moduleName: "ReactNativeSample_ios", initialProperties: nil, launchOptions: launchOptions)
    rootView?.backgroundColor = UIColor.init(red: 1.0, green: 1.0, blue: 1.0, alpha: 1)
    //----RCTRootView----
    
    let rootViewController = UIViewController()
    rootViewController.view = rootView;
    self.window?.rootViewController = rootViewController;
    self.window?.makeKeyAndVisible()
    return true
  }

  ///色々
}
```

```objc:ReactNativeSample_ios-Bridging-Header.h
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTBridgeModule.h>
#import "AppDelegate.h"
```

- Android
  - 拡張子ktのファイルを書くと、AndroidStudioがbuild.gradleとか直してくれる。
  - `src/main/java` -> kotlinに直したり
  - MainActivity、MainApplicationをkotlin化する

```kotlin:MainActivity.kt
package com.github.uryyyyyyy.reactnative.android

import com.facebook.react.ReactActivity

class MainActivity : ReactActivity() {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    override fun getMainComponentName(): String? {
        return "ReactNativeSample_android"
    }
}
```

```kotlin:MainApplication.kt
package com.github.uryyyyyyy.reactnative.android

import android.app.Application

import com.facebook.react.ReactApplication
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.shell.MainReactPackage
import com.facebook.soloader.SoLoader
import com.github.uryyyyyyy.reactnative.android.myModules.MyPackage

import java.util.Arrays

class MainApplication : Application(), ReactApplication {

    private val mReactNativeHost = object : ReactNativeHost(this) {
        override fun getUseDeveloperSupport(): Boolean {
            return BuildConfig.DEBUG
        }

        override fun getPackages(): List<ReactPackage> {
            return Arrays.asList<ReactPackage>(
                    MainReactPackage(),
                    MyPackage()
            )
        }
    }

    override fun getReactNativeHost(): ReactNativeHost {
        return mReactNativeHost
    }

    override fun onCreate() {
        super.onCreate()
        SoLoader.init(this, /* native exopackage */ false)
    }
}
```

---

## Firebaseの導入

---

### Firebaseコンソール

- プロジェクト作り
- Appを追加し、
- 設定ファイルをダウンロードしてアプリに追加し、
- SDKを入れたりする。

---

### イベント飛ばしてみる

#### iOS

- objective-Cでヘッダを書く
- swiftでFirebaseの処理を書く
- JSでそれを呼び出す。

```swift:MyModule.swift
  @objc(callFunc:)
  func callFunc(num: NSInteger) {
    print("num");
    print(num);
    FIRAnalytics.setUserPropertyString("favorite", forName: "curry")
    
    FIRAnalytics.logEvent(withName: kFIREventSelectContent, parameters: [
      kFIRParameterContentType:"count" as NSObject,
      kFIRParameterItemID:"1" as NSObject
      ])
  }
```

#### Android

- ReactContextBaseJavaModuleを継承したクラスで処理を書く
- ReactPackageを継承したクラスを作り、上記クラスを追加する
- MainApplicationで上記クラスを追加する。
- JSでそれを呼び出す。

```kotlin:MyModule.kt
    @ReactMethod
    fun sendEvent() {
        val mFirebaseAnalytics = FirebaseAnalytics.getInstance(reactApplicationContext)
        val bundle = Bundle()
        bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "id")
        bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "name")
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "image")
        Log.i("myActivitysssss", mFirebaseAnalytics.toString())
        mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle)
    }
```

---

### Google認証してみる。

力尽きた。。。

デモだけお見せします。後で書きます。。。きっと。。。

---

## まとめ

- 普通にブリッジできるよ。
- SDKを触るだけなら言語詳しくなくてもなんとかなるよ。
- 「え、React Nativeなのにまだ Firebase Web SDK使ってるの？」