SnapchatログインができるSDK, Snap Kitでデモアプリ作ってみた

先日、Snapchatから開発者向けSDK,[**Snap Kit**](https://kit.snapchat.com/)が出たことをご存知でしょうか？

![Snapchat-Snap-Kit-1024x544.jpg](https://qiita-image-store.s3.amazonaws.com/0/111366/187d455a-0acd-f0e4-9859-f6112f64d885.jpeg)


Facebookログインと同じように、このSnap Kitを使って**Snapchatログイン**ができるようになります。また、Snapchatへの写真や動画のシェアが簡単になったり、Bitmojiが使えるなど、Snapchatのコンテンツを他のアプリからも使うことができるようになります。

ということで、今回[iOS](https://github.com/kboy-silvergym/SnapKitSample-iOS)と[Android](https://github.com/kboy-silvergym/SnapKitSample-Android)でDemoアプリを作ってみました。
実はiOSアプリは先日リリースしてます。[Pemoji](https://itunes.apple.com/app/pemoji/id1410639096)というアプリです。

<img src="https://user-images.githubusercontent.com/17683316/42438970-8c02222c-839c-11e8-8ccb-5b0d266aa02a.gif" width="250">

僕はiOSの方が得意ですので、今記事では、iOSを中心に解説していきたいと思います。

基本的には[公式ドキュメント](https://kit.snapchat.com/)通りですが、いくつか補足情報も載せていきたいと思います。

# SDKのインストール

`SnapSDK` としてcocoapodsでインストールできます。

```ruby
pod 'SnapSDK', :subspecs => ['SCSDKLoginKit', 'SCSDKCreativeKit', 'SCSDKBitmojiKit']
```

# Login Kit
<img src="https://user-images.githubusercontent.com/17683316/42131965-12afd184-7d49-11e8-931b-0ef5578157df.png" width="100">

公式ドキュメントは以下を参照
https://docs.snapchat.com/docs/login-kit/

このログインにより、`displayName`と`avatar (bitmoji avatar)`を取得することができます。

また後述するBitmoji Kitにおいて、SDKを使ってログインすることが必須です。

以下は僕のデモアプリの動きです。

<img src="https://user-images.githubusercontent.com/17683316/42132023-729a370a-7d4a-11e8-9fff-c93cd4940e69.gif" width="250">

では、簡単に実装の流れを解説します。事前にドキュメントにしたがって、url schemeやAppDelegateの設定は済ました前提で進めていきます。

## 1.ボタンをタップしたら、`SCSDKLoginClient.login`を呼ぶ

Snapchatに飛べるように、AppDelegateで以下のように設定しておきます。

```swift
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    return SCSDKLoginClient.application(app, open: url, options: options)
}
```

その上で、ボタンを押したら、`SCSDKLoginClient.login` を呼び、成功したら次はユーザー情報を取得していきましょう。

```swift
@IBAction func loginButtonTapped(_ sender: Any) {
    SCSDKLoginClient.login(from: self, completion: { success, error in
        
        if let error = error {
            print(error.localizedDescription)
            return
        }
        
        if success {
            self.fetchSnapUserInfo()
        }
    })
}
```


## 2.ユーザー情報取得。

Snapchatのユーザー情報のリクエストはRestAPIではなくGraphQLであるということが面白いですね。

以下のコードではDecodableに準拠したUserEntityというのを作成して、JSONをparseしています。もちろん、userInfoをそのままdictionaryとして扱ってparseしてもよいと思います。

```swift
private func fetchSnapUserInfo(){
    let graphQLQuery = "{me{displayName, bitmoji{avatar}}}"
    
    SCSDKLoginClient
        .fetchUserData(
            withQuery: graphQLQuery,
            variables: nil,
            success: { userInfo in
                
                if let userInfo = userInfo,
                    let data = try? JSONSerialization.data(withJSONObject: userInfo, options: .prettyPrinted),
                    let userEntity = try? JSONDecoder().decode(UserEntity.self, from: data) {
                    
                    DispatchQueue.main.async {
                        self.goToLoginConfirm(userEntity)
                    }
                }
        }) { (error, isUserLoggedOut) in
            print(error?.localizedDescription ?? "")
    }
}
```

displayNameとavatarを取得することができました。

## 3.注意点

### Info.plist'の`SCSDKRedirectUrl`を[SnapChat Developer Portal](https://kit.snapchat.com/portal/)の`Redirect URLs`と一致させること

これを一致させないとSnapchatアプリでエラーになります。

### ハイフン `-` をurl schemeで使わないこと

現在、[SnapChat Developer Portal](https://kit.snapchat.com/portal/)の仕様で、`-` がurl schemeで使えないようです。

以上がLogin Kit

## Creative Kit
<img src="https://user-images.githubusercontent.com/17683316/42131997-9b7b3b8e-7d49-11e8-9651-092cf14fed1e.png" width="100">

ドキュメントは以下
https://docs.snapchat.com/docs/creative-kit/ 

とても簡単に画像や動画をSnapChatにシェアできます。これは先程のLogin KitでログインしていなくてもSnapchatアプリを持っていれば使えます。

画像と動画にstickerやurl、captionをくっつけることもできます。

<img src="https://user-images.githubusercontent.com/17683316/42210546-402b855a-7eec-11e8-91f1-4c04e3242113.gif" width="250">

コードはとても簡単です。

```swift
import SCSDKCreativeKit

let snapshot = sceneView.snapshot() // Any image is OK. In this codes, SceneView's snapshot is passed.
let photo = SCSDKSnapPhoto(image: snapshot)
let snap = SCSDKPhotoSnapContent(snapPhoto: photo)

// Sticker
let sticker = SCSDKSnapSticker(stickerImage: #imageLiteral(resourceName: "snap-ghost"))
snap.sticker = sticker
        
// Caption
snap.caption = "Snap on Snapchat!"
        
// URL
snap.attachmentUrl = "https://www.snapchat.com"
        
let api = SCSDKSnapAPI(content: snap)
api.startSnapping { error in
            
    if let error = error {
        print(error.localizedDescription)
    } else {
        // success
    
    }
}
```

以上がCreative Kit

# Bitmoji Kit
<img src="https://user-images.githubusercontent.com/17683316/42131995-9914d864-7d49-11e8-95de-f8c053b2f706.png" width="100">

最後にBitmoji Kit。これでBitmojiのアバターとスタンプ一覧を取得することができます。

デモアプリでは、選択したBitmojiをAR空間上に貼ってみました。

<img src="https://user-images.githubusercontent.com/17683316/42438970-8c02222c-839c-11e8-8ccb-5b0d266aa02a.gif" width="250">

## Avatar画像の取得

以下のようにログインしているユーザーのavatar画像のurlを取得することができます。

```swift
import SCSDKBitmojiKit

// fetch your avatar image.
SCSDKBitmojiClient.fetchAvatarURL { (avatarURL: String?, error: Error?) in
    DispatchQueue.main.async {
        if let avatarURL = avatarURL {
            self.iconView.load(from: avatarURL)
        }
    }
}
```

## Bitmojiスタンプ一覧の取得

`SCSDKBitmojiStickerPickerViewController` というViewControllerがBitmoji Kitに用意されているので、これをUIViewのChildViewControllerとして簡単に呼び出すことができます。

```swift
@IBAction func bitmojiButtonTapped(_ sender: Any) {
    // Make bitmoji background view
    let viewHeight: CGFloat = 300
    let screen: CGRect = UIScreen.main.bounds
    let backgroundView = UIView(
        frame: CGRect(
            x: 0,
            y: screen.height - viewHeight,
            width: screen.width,
            height: viewHeight
        )
    )
    view.addSubview(backgroundView)
    bitmojiSelectionView = backgroundView
    
    // add child ViewController
    let stickerPickerVC = SCSDKBitmojiStickerPickerViewController()
    stickerPickerVC.delegate = self
    addChildViewController(stickerPickerVC)
    backgroundView.addSubview(stickerPickerVC.view)
    stickerPickerVC.didMove(toParentViewController: self)
}
```

## SCSDKBitmojiStickerPickerViewControllerDelegateに準拠する

準拠することで、一覧からスタンプが選択されたイベント、searchBarにフォーカスが当たったイベントを取得することができます。

デモアプリでは、選択したBitmojiをAR空間上に貼ってみました。

```swift
extension CameraViewController: SCSDKBitmojiStickerPickerViewControllerDelegate {
    
    func bitmojiStickerPickerViewController(_ stickerPickerViewController: SCSDKBitmojiStickerPickerViewController, didSelectBitmojiWithURL bitmojiURL: String) {
        
        bitmojiSelectionView?.removeFromSuperview()
        
        if let image = UIImage.load(from: bitmojiURL) {
            DispatchQueue.main.async {
                self.setImageToScene(image: image)
            }
        }
    }
    
    func bitmojiStickerPickerViewController(_ stickerPickerViewController: SCSDKBitmojiStickerPickerViewController, searchFieldFocusDidChangeWithFocus hasFocus: Bool) {
        
    }
}
```

以上がBitmoji Kit

# サンプルをGithubに公開してます

- [SnapKitSample-iOS](https://github.com/kboy-silvergym/SnapKitSample-iOS)
- [SnapKitSample-Android](https://github.com/kboy-silvergym/SnapKitSample-Android)

# iOSはアプリをリリースしました

<a href="https://itunes.apple.com/app/pemoji/id1410639096"><img src="https://qiita-image-store.s3.amazonaws.com/0/111366/96cbe426-bfa7-617a-5852-09ab4b32d29a.jpeg" width=300></a>

[Pemoji〜ぺっとBitmojiを空間に置けるアプリ〜](https://itunes.apple.com/app/pemoji/id1410639096)

GRAFFITYでは優秀なiOS, Androidエンジニア募集中です！
ぜひTwitterのDMでお声がけください！
https://twitter.com/kboy_silvergym

# 参考文献
- https://kit.snapchat.com/