ページ

2016年10月27日木曜日

Realm mobile platform アプリ作成 - Android -


前回、RealmサーバーにiOSで作成したアプリと同期が取れている事を確認しました。
今回はAndroidアプリを作成し、iOS->Realmサーバー->Androidで同期を取ってみたいと思います。
とりあえず今回はログインまでをやってみます。

Androidアプリ開発準備


開発環境
Android Studio 2.2.2
プロジェクト作成&Realmインストール

まずはプロジェクトを作成。minSdkVersionは19、targetSdkVersionは23
Activity追加ではEmpty Activityを選択しました。

早速Realmをインストールしていきます。
まずはトップにあるbuild.gradleのdependenciesに↓を追加。
dependencies {
    classpath "io.realm:realm-gradle-plugin:2.0.2"
}
次にapp/build.gradleに↓を追加します。
apply plugin: 'realm-android'

realm {
    syncEnabled = true
}
syncEnabled = trueにしないとObjectServer関連が使えないので注意!!
最後にbuild.gradleを修正した際に右上に表示されるSync Nowをクリック。
Realmがインストールされます。


ログイン画面作成


Realmサーバーにログインするまでを実装してみたいと思います。
  • Applicationクラス作成
Realm関係の初期化を行う為にApplicationクラスを継承した
クラスを作成します。今回はMyApplicationクラスにします。
作成したMyApplicationクラスのonCreateを以下のようにオーバーライドします。
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        Realm.init(this);
    }
}
次にAndroidManifest.xmlandroid:name=".MyApplication"を追加します。
<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:name=".MyApplication" // ☆ここ
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
      ・・・
    </activity>
</application>
とりあえず今回はMainActivityonCreateでログイン処理を実施します。
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // [1]
        Credentials creds = Credentials.usernamePassword("ユーザー名", "パスワード", false);

        String authUrl = "http://10.0.2.2:9080/auth"; // [2]
        User.Callback callback = new User.Callback() {
            @Override
            public void onSuccess(User user) {
                Log.i(TAG, "Login success.");
            }

            @Override
            public void onError(ObjectServerError error) {
                String errorMsg;
                switch (error.getErrorCode()) {
                    case UNKNOWN_ACCOUNT:
                        errorMsg = "Account does not exists.";
                        break;
                    case INVALID_CREDENTIALS:
                        errorMsg = "User name and password does not match";
                        break;
                    default:
                        errorMsg = error.toString();
                }
                Log.e(TAG, errorMsg);
            }
        };
        User.loginAsync(creds, authUrl, callback);
    }
}
[1]のusernamePasswordメソッド第三引数をtrueにするとユーザー新規作成
falseにするとログインになります。
[2]でhttp://10.0.2.2:9080/authとしてますが、
これはエミュレータ上でlocalhostにアクセスするには10.0.2.2
する必要がある為、このIPアドレスにしています。
この状態でRealm Object Serverを立ち上げて実行し、
ログに「Login success.」が表示されればOKです。

2016年10月23日日曜日

Docker for MacでプライベートなDockerHubを作る


DockerHubは沢山のimageが公開されていて便利ですが、
自分用や会社用のDockerHubを作りたい時があるかと思います。
そんな時はDockerを使ってDockerHubを作成できるので作ってみます。

環境構築


最近はLinuxに限らず、WindowsでもMacでもDockerが動きます。
今回はDocker for Macを使ってMacに環境を構築してみます。
まずは
ここ からdmgファイルをダウンロード。
インストールが完了するとステータスバーにDockerのアイコンが表示されます
最初アイコンをクリックすると↓のようなポップアップが表示され
Dockerの使用状況を改善の為に送るかどうか設定できます。
「Got it」をクリックし準備OKです。
ちゃんと動いているかターミナルから
$ docker --version
を実行し、バージョンが表示されればOKです。

Registryコンテナの取得


公式に配布されているRegistryコンテナを取得し、
プライベートなDockerHubを構築していきます。
まずはimageをpull
$ docker pull registry:2
ちゃんとpullできたかdocker imagesで確認します。
$ docker images
REPOSITORY  TAG   IMAGE ID         CREATED        SIZE
registry    2     XXXXXXXXXXXX     4 weeks ago    33.3 MB

起動&可視化


早速起動して使ってみたいと思います・・が、
その前にDockerHubみたいにブラウザで登録状況が確認できた方が
使いやすいので、可視化するコンテナの
を使います。
毎回コマンドで起動して〜停止して〜というのもきついので 以下のスクリプトを用意します。
  • run_registry.sh
#!/usr/bin/env bash

DOCKER_HOME=$PWD

if [ -e $DOCKER_HOME/registry ]; then
  # 何もしない
else
  mkdir $DOCKER_HOME/registry
fi

docker run \
    -d \
    -p 5000:5000 \
    -v $DOCKER_HOME/registry:/var/lib/registry \
    --name docker_registry2 \
    registry:2

docker run \
    -d \
    -e ENV_DOCKER_REGISTRY_HOST=[ローカルPCのIPアドレス] \
    -e ENV_DOCKER_REGISTRY_PORT=5000 \
    -p 8080:80 \
    --name registry_browser \
    konradkleine/docker-registry-frontend:v2
-v $DOCKER_HOME/registry:/var/lib/registry \では
登録されたimageの内容はコンテナ内の/var/lib/registry
書き込まれます。永続化の為ホストの$DOCKER_HOME/registry
マウントさせています。
2番目のdocker runでは可視化の為のコンテナを走らせてます。
早速起動します。
$ ./run_registry.sh
初回はimageのダウンロードで遅いかもしれません。起動ができたら
http://localhost:8080にアクセスし以下の画面が出れば成功です。

push&pull


作成したプライベートなDockerHubにimageをpushする場合は、
まずpushしたいimageを特定の名前で作成します。
例えば、jenkins:latestのイメージから名前を帰る場合、
で作成します。
例)
$ docker tag jenkins:latest localhost:5000/slowhand/jenkins:latest
あとはpushすればOKです。
$ docker push localhost:5000/slowhand/jenkins:latest
http://localhost:8080上で登録されてると思います。

逆にpullする場合は
$ docker pull localhost:5000/slowhand/jenkins:latest
でOKです。

停止


停止用のスクリプトも書いておきます。
  • stop_registry.sh
#!/usr/bin/env bash

docker stop registry_browser
docker stop docker_registry2

docker rm registry_browser
docker rm docker_registry2
以上、色々便利になりましたw

2016年10月15日土曜日

Facebook製の新しいパッケージ管理ツールyarnを試してみる




Javascriptのパッケージ管理といえばnpmですが、
yarnはnpmに比べてどうなのか試してみました。
と言う訳で、早速試してみたいと思います。

環境準備 & インストール


環境としてはMacOS、Windows、Linuxで使用できます。
筆者はMacOSで試しました。
前提としてNode.jsのインストールが必要になります。
今回はHomebrewを使ってyarnをインストールしますが、
他にもスクリプトからや、tarballをダウンロードしてからもインストールできます。
$ brew update
$ brew install yarn


パッケージインストール


yarnはpackage.jsonを使ってインストールもできるので、
以前作成したReact開発用でのpackage.jsonを使ってみたいと思います。
  • package.json
{
  "name": "Template",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server --progress --colors",
    "lint": "eslint src --ext .js --ext .jsx"
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "babel-core": "^6.11.4",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.11.1",
    "eslint": "^3.3.0",
    "eslint-plugin-react": "^6.2.0",
    "react": "^15.3.0",
    "react-dom": "^15.3.0",
    "webpack": "^1.13.2",
    "webpack-dev-server": "^1.16.1"
  }
}
パッケージインストール
$ yarn install
yarn install v0.15.1
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 29.16s.
yarn install  14.32s user 5.98s system 68% cpu 29.814 total
※時間を計測する為にtimeコマンドを使用してます。
なんか絵文字があったりnpmよりシャレた感じですw
インストールされるとディレクトリ直下にyarn.lockが作成されます。
  • yarn.lock
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
abbrev@1:
  version "1.0.9"
  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25     f35dd6f63752a2f8776135"

accepts@~1.3.3:
  version "1.3.3"
  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3     e0d9c1e328dd68b622c284ca"
  dependencies:
    mime-types "~2.1.11"
    negotiator "0.6.1"

省略・・・
package.jsonより細かいパッケージの情報が書かれています。Gemfile.lockみたいな感じですね

ちなみにnpmで同様のパッケージをインストールしてみました。
$ npm install
...
npm install  33.22s user 8.36s system 95% cpu 43.549 total
インストール時間に関してはyarnが29.814s
npmが43.549sなのでyarnの方が早いです。

またパッケージの重複に関してもyarnの方が整理されています。
試しにisarrayパケージをnode_modules内で検索してみると
  • npm
$ find . -name isarray -type d
./node_modules/fsevents/node_modules/isarray
./node_modules/isarray
./node_modules/node-libs-browser/node_modules/isarray
./node_modules/stream-browserify/node_modules/isarray
  • yarn
$ find . -name isarray -type d
./node_modules/isarray
./node_modules/readable-stream/node_modules/isarray
yarnの方が整理されています。

その他


yarnはnpm同様に以下コマンドが使えます。
  • package.json作成
$ yarn init
  • 依存パッケージ追加
$ yarn add [package]
$ yarn add [package]@version
$ yarn add [package]@tag
  • 依存パッケージ更新
$ yarn upgrade [package]
$ yarn upgrade [package]@version
$ yarn upgrade [package]@tag
  • 依存パッケージ削除
$ yarn remove [package]
こうなるとyarnの方が便利そうですが、、
しばらくnpmの代わりに使ってみたいと思います。

2016年10月13日木曜日

Realm mobile platform アプリ作成1 - iOS -


以前デモアプリを試して、サーバーと同期が取れている事を試してみました。 今回は実際にiOSアプリに組み込んでみたいと思います。

プロジェクト作成

今回はXcode8でプロジェクトを作成していきます。
Create a new Xcode project > iOS > 
Application > Single View Applicationを選択。
Product NameOrganization Name等はお好みで。
LanguegeはSwift、DevicesはiPhoneを選択します。

Keychainを使用する為、Keychain SharingをONにします。
※「Capabilities」タブにあります

次に「General」タブのEmbedded Binariesに前回ダウンロードした
realm-mobile-platformフォルダ内の「SDKs」>「realm_cocoa_XXX」> 
「ios」>「swift-3.0」にある「Realm.framework」と「RealmSwift.framework」を
ドラッグ&ドロップします。

その際に「Copy Items if Needed」にチェックを入れます。

コピー後


モデルの作成

次に簡単なモデルを作成します。
ViewController.swiftに以下を追加します。
import RealmSwift

final class Item : Object {
    dynamic var id = 0
    dynamic var name = ""
}
モデルの作成はObjectクラスを継承したクラスを作成し、
メンバはdynamic varで宣言します。

ユーザーログイン

アプリ起動時にサーバーにログインする処理を追加します。
var realm: Realm!

func login() {
    // サーバーURLを指定
    let url = URL(string: "http://localhost:9080")
    // 登録済みのユーザーで認証します
    let credential = Credential.usernamePassword(
      username: "user@example.com", password: "xxxxxx", actions: [.useExistingAccount])
    User.authenticate(with: credential, server: url!, onCompletion: {user, error in
        if let _ = user {
            // ログイン成功時
            // sample/database : DBで言うスキーマみたいなもの
            let realmURL = URL(string: "realm://localhost:9080/sample/database")!
            let configuration = Realm.Configuration(syncConfiguration: (user!, realmURL))
            Realm.Configuration.defaultConfiguration = configuration
            // realmオブジェクトを取得
            self.realm = try! Realm()

        } else if let _ = error {
            // ログイン失敗
            print("login error \(error)")
        }
    })
}

override func viewDidLoad() {
    super.viewDidLoad()
    login()
}
ログイン成功時に取得したRealmオブジェクトを使って処理を行います。

アイテム追加

ストーリーボードでButtonTextFieldを追加します。

Button押下時のアクションをonPushAddとしてViewController.swift
イベント追加します。また、TextFieldnameFieldとして追加します。

追加したonPushAddを以下のように修正します。
var count: Int = 0

@IBAction func onPushAdd(_ sender: AnyObject) {
    // TextFieldから現在入力されているテキストを取得
    let name = self.nameField.text
    try! self.realm?.write {
        // RealmオブジェクトにてItemを追加
        count = count + 1
        let item = Item()
        item.id = count
        item.name = name!
        self.realm.add(item)
    }
}
ここまで出来たらサーバー側で反映されているか確認します。
Realm Object Serverを起動し、Realm Browser.appを立ち上げます。
サーバー接続後、Openできるスキーマが増えているかと思います。

ログイン時に設定したスキーマになります。
※スキーマという名前であってるか分かりませんが、便宜上そう読んでます。
接続後に起動したアプリ上でTextFieldに文字列を入力しAddを押すと
データが追加されてればOKです。
gif
今回修正したViewController.swiftここで見れます。