Angular1系のhtml5Modeでルーティングする

初めにアクセスされたページがトップページではない時のルーティングでAngularの設定で迷ったのでメモしておきます。

初めにアクセスされたページが http://localhost/ の場合は / がベースになることが分かるのですが、初めに http://localhost/item/1 にアクセスされるとベースがそこになってしまい item/1 にアクセスしたい場合は http://localhost/item/1/item/1 にしないといけなくなります。

色々試してみたのですが、結果としてAngularの設定はこんな感じになりました。

class AppController {
    constructor(private $router: AppScope) {
        $router.config([
            { path: '/item/:id', component: 'item' },
            { path: '/**', component: 'home' }
        ]);
    }
}

angular.module('app', ['ngNewRouter', 'app.home', 'app.item'])
    .config(['$locationProvider', ($locationProvider) => {
        $locationProvider.html5Mode({enabled: true, requireBase: true});
    })
    .controller('AppController', ['$router', AppController]);

*1

ポイントとしては html5ModeのrequireBase: trueの部分です。この設定をすることでルートのhtmlにベースパスを指定することができます。以下のように設定することで、http://localhost/item/1 にアクセスしても http://localhost/ をベースとして解釈して適切に処理してくれます。

<head>
    <base href="/">
    ...
</head>

これでサーバはどのURLでアクセスがきてもルートのhtmlを返すように設定しておけば、Angularがうまく処理してくれるはずです。

*1:ルーティングのモジュールであるngNewRouterにはotherwiseがないようで、{ path: '/**', component: 'home' } こう書くことで同じように動作させるみたいです。 https://github.com/angular/router/issues/110

TypeScriptでAngular1.5を書けるようにする

Webアプリを作ることになったので、Angularフレームワークを使ってTypeScriptで書くことにしました。そこでこの組み合わせでさくっとセットアップできなかったので方法を残しておきます。

セットアップ

AngularとTypeScript、Typingsをインストールする。

$ bower install --save angular
$ npm install -g typescript
$ npm install -g typings

TypingsはTypeScriptの型定義ファイルを管理するツールで、TypeScript標準で存在しない型の補助をしてくれます。 今回はAngularと依存しているjQueryの型定義をインストールする。

$ typings install --save --global dt~angular
$ typings install --save --global dt~jquery

Webアプリの設定

HTMLでAngularを読み込む。

<head>
  <script src="./bower_components/angular/angular.min.js"></script>
  <script src="todo.js"></script>
</head>

TypeScriptファイルの先頭で型定義ファイルを指定する。これでTypeScript内でangularなどの変数を使ってもエラーが出なくなります。

/// <reference path="./typings/index.d.ts" />

var app = angular.module('todoApp', [])
...

これでTypeScriptファイルをコンパイルできるようになり、JavaScriptファイルが正常に出力されます!

https://gist.github.com/t-kashima/24d97cddca0ba5e9b14b9e86c2ba81c4

Mac + RC-S380でSuicaを読み込む

MacとRC-S380を使ってSuicaを読み込んでみました。

SONY 非接触ICカードリーダー/ライター PaSoRi(パソリ) USB対応 RC-S380

SONY 非接触ICカードリーダー/ライター PaSoRi(パソリ) USB対応 RC-S380

Suicaを読み込んでデータを表示するためにpythonライブラリnfcpyを使いました。nfcpyを使うために色々インストールしたのでメモしておきます。

$ brew install libusb
$ brew install libusb-compat
$ brew install bzr
$ sudo pip install pyusb
$ sudo pip install libusb1
$ sudo pip install pyserial

これでnfcpyを使うための準備が整いました。さっそくBazaarを使ってnfcpyを取得します。

$ bzr branch lp:nfcpy

nfcpyのサンプルにタグを表示するスクリプトが入っているので実行してみます。

$ python examples/tagtool.py show
Type3Tag 'FeliCa Standard (RC-S???)' ID=0000000000000000 PMM=0000000000000000 SYS=0000

無事にSuicaのタグが表示されました!

Instrumentation TestでNo Testsになる

Gradleプラグイン1.5.0 + multidexの組み合わせでInstrumentation Testが動かなくてはまりました。Issueが上がっていて解決策ものっています。

Issue 194609 - android - Android Gradle Plugin 1.5.0: Multi-Dex on pre-Lollipop devices gives java.lang.IllegalAccessError during the connectedAndroidTest task (dalvik is loading different MultiDexApplication). - Android Open Source Project - Issue Tracker - Google Project Hosting

multidexを有効にすると追加されるライブラリをダミーライブラリに差し替えることで直るようです。次のバージョンで修正が入っているようでGradleプラグインのバージョンを上げても直りました。