Monthly archives: 5月, 2015

Intellij community(無料版)でPlayFramework2.4を使う方法

Intellij使ってPlayつかいたいけど、予算がないので無料版で何とかするメモ!

お金のある方はultimateをお買い上げするのが一番良さそうですが・・・

新しいバージョンのPlayFrameworkではTypesafe Activatorを使うようになったので
以前のやり方
[Playframework][Scala][IntelliJ IDEA]Intellij IDEA/Scala/Playframework2.0 での環境構築に関するメモ #play_ja
とは少し変わりました。


公式にもTypeSafe Activatorを使えと書いてあります。
https://www.playframework.com/download


Typesafe Activatorをインストール

まずは公式でダウンロードしてくる
https://www.typesafe.com/get-started

適当な場所に解凍しておいてください。program filesとかスペースが入ってるとこはうまく動かない可能性があるので、cドライブの直下とか、何処かにおいてください。
そしたら、Activatorを設置した場所へパスを通しておいてください。
PATHに加えるとか、環境変数のpathに追記するとかのあれです。
macもlinuxもwindowsもやり方は違えど基本同じだとおもいます。
これで[activator]コマンド使えるようになったはずです。
コマンドラインから

>activator help

でヘルプが出ればOK!


playプロジェクト作成

もういきなりプロジェクト作成です。
プロジェクトを作る場所を決めたら、そこにディレクトリを移動してください。
コンソールや、コマンドプロンプトから

mydocuments> activator new my-play-app play-scala

これで“play-scala”テンプレートで“my-play-app”を作成します。
Javaで作る場合は“play-java”にしてください。

次に

mydocuments> cd my-play-app
mydocuments/my-play-app> activator run

暫し待つ。
newもrunも依存ライブラリなんかをダウンロードするので結構時間かかりました。

(Server started, use Ctrl+D to stop and go back to the console...)
----
[info] - play.api.Play$ - Application started (Dev)

がでたら起動成功。
ブラウザでhttp://localhost:9000/にアクセスしてみましょう。

こんなかんじになってたらplayのインストールと起動は成功!
終了はCtrl+D


intellijのインストールとプラグイン

intellijは公式ページから無料のCommunity Editionをダウンロードしてきましょう。https://www.jetbrains.com/idea/download/
(ultimateもお試し期間があるようですが、、、)

インストーラーで入るので難しいことはないと思います。
普通に立ち上げて、次はプラグインをインストールしましょう。

必要なのは
・Scala
・SBT

です。あとは
・Batch Scripts Support
を入れておくと起動ボタンから起動するようにできます。
プラグインのインストールの仕方は難しく無いとは思いますが、色々なサイトにやり方が書いてあるとおもいます。
プラグインを入れたら、intellij再起動。


playプロジェクト取り込み

intellijから
[import project]
先ほどのプロジェクトフォルダを選択
[SBT]としてインポートを選択

必要なものにチェックをつけて、Finishボタン
またちょっと時間かかります。結構色々待たされます。


intellijから起動

インポートが終わったら、intellijのターミナルから

mydocuments/my-play-app> activator run

してみてください。

先ほどと同じようにplay framework が立ち上がると思います。
ブラウザでhttp://localhost:9000/にアクセスしてみましょう。
終了はCtrl+D


起動設定をしてRunボタンから立ち上げできるようにする

Batch Scripts Supportプラグインを入れていれば、Runボタンから立ち上げの設定ができます。
ここから

+ ボタンから Batchを選択して
名前とScript,ScriptParameter WorkingDirectryを設定してください。

こんな感じ。

これで、起動ボタンから起動出来て簡単!?


デバッグできるようにする。

まずデバッグモードでサーバーの起動ボタンを作成します
デバッグモードでのサーバー起動はポート9999で起動する場合

mydocuments/my-play-app> activator -jvm-debug 9999 run

という形になります。
これを先ほどと同じように

+ ボタンから Batchを選択して
以下のように入力!

つぎに、デバッガーをつなげるために
+ ボタンから Remoteを選択して
portを9999に設定

これで設定はOK


デバッグする

まずデバッグモードでサーバー(batchで設定した方)を起動させます。
起動したら、次にデバッガを起動させます。(Remoteで設定した方)
これで適当にブレイクポイント設定して、http://localhost:9000/にアクセスすれば、ブレイクポイントでとまると思います。

雑な説明なのでどこか抜けてるかもしれませんが以上


参考にしたサイト
http://d.hatena.ne.jp/kamekoopa/20130427/1367042044
http://d.hatena.ne.jp/yuheiomori0718/20120623/1340464997



この記事のトラックバック用URL - http://mashi.exciton.jp/archives/144/trackback


ゴミ収集日

アプリ、リリースしました!

ゴミ収集日

https://play.google.com/store/apps/details?id=jp.exciton.gomiapp

今回もマテリアルデザイン意識してみました。
意識しただけなので細かいところは許してください!

これ作りながら、ちょっと気になったものを記事にしてたりしたので、
AndroidのUIスレッドTimerとか
PendingIntentとAlermManagerとか
あと今回ユニットテストもやったので、AndroidをUnitTestする
の内容も!

とくに、アラート系のアプリなので、開発の中でAlertManagerの特性についてはわかったことも多いです。
AlertManagerの説明に関しては
TechBoosterさんのところにわかりやすくまとまってます。

AlertManagerで時刻を予約してから、時計の設定を先に進めると一気にアラート来るんですね、
知らなかった。

このアプリではいくつかの予約(2,3個)をしているので、デバッグのために時計進めてみると、
いっきにIntentが飛んでくるんです。
なので、ほんとに今実行すべきか(アラートを出すか)をIntent受け取ってから判断する必要があります。
細かいけど、こういう細かいことをやってるアプリとそうじゃないアプリがあるってことが、時刻ずらしてみるとわかるのがおもしろい。

あとCrashlytics入れました。なので、クラッシュでてもご報告不要です!!!
ただしUIとか動きがおかしいのはCrashlyticsしてくれないのでご報告いただけたら嬉しいです!
Crashlyticsの方もそのうちレポートしたいなーとおもってます。



この記事のトラックバック用URL - http://mashi.exciton.jp/archives/124/trackback


カスタムビューとレイアウトエディタ

アンドロイドでカスタムビューを作るときのお話

カスタムビューを作った時にレイアウトエディタでの表示がカッコよくならなくて
諦めたりしてませんかー?

isInEditMode()

http://developer.android.com/reference/android/view/View.html

これが便利!


Viewを継承してなんかのCustomViewを作るんですが、
ActivityのonCreateなんかで

public void onCreate() {
   new MyCustomView(this, param1, param2);
}

とか

myview = findViewById(R.id.my_custom_view);
myview.setMyParameter("hoge");

とかって処理をして、表示内容を変えたりすると思うんです。
何も渡さない時のデフォルトをコンストラクタで用意してもいいんですが、
その処理がそれなりに重いものだったりすると無駄がおおい、、、、

isInEditMode()

そんなときisInEditMode()で判断して、レイアウトエディタで表示するときにだけの処理なんかが書けるようになります!

myview = findViewById(R.id.my_custom_view);
if( isInEditMode() ){
   myview.setMyParameter("レイアウトエディタ表示");
}else{
   myview.setMyParameter(message);
}

みたいな?
こういうのちゃんとやっとくとプログラマとUIデザイナーとの分業もやりやすいです!?

参考:
http://www.united-bears.co.jp/blog/archives/402
http://to40.blog55.fc2.com/tb.php/29-4af5d637


この記事のトラックバック用URL - http://mashi.exciton.jp/archives/117/trackback


AndroidをUnitTestする

Androidのテスト環境について

Unitテストをやりたい場合。
JUnitテストを行うやり方についてのメモ。
AndroidStudioを使ってることを前提とします。

まず、build.gradleのdependenciesですが、
これまでだとEspressoなどを使う必要があったのですが、
androidのsupport packageに追加されているtesting-support-libに統合されたようです。

Testing Support Library

support packageに追加されたtesting-support-libを使ってAndroidのテストをJUnit4で書く

ということなのでdependenciesには
androidTestCompile ‘com.android.support.test:testing-support-lib:0.+’
のみ追加。

それとdefaultConfig
testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner”
を追加してください。
これはJUnit4を動かすには必要なようです。
もしJUnit3だけであればなくても動くのですが、今回はJUnit4を使ってみるので入れておきます。

 

この状態で実行してみると、つぎのようなエラーが出るかもしれません。

Error:duplicate files during packaging of APK /Users/…/build/apk/app-debug-androidTest-unaligned.apk
Path in archive: LICENSE.txt

下記のようにbuild.gradleにのandroid{ のなかに追加してください
エラーに出てるファイル、もしくはパス名を下記のように付け加えればOK

android {
    ~~  
    packagingOptions {
        exclude 'LICENSE.txt'
    }

環境によっては’META-INF/LICENSE.txt’になるかも。

そうするとこんなかんじになります。↓

 android {
    ~~

    defaultConfig {
           ~~

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }


    packagingOptions {
        exclude 'LICENSE.txt'
    }
}

dependencies {
    ~~

    androidTestCompile 'com.android.support.test:testing-support-lib:0.+'
}

 

UnitTestの書き方

AndroidStudioがいろいろと手伝ってくれます。
テストしたいクラスにカーソルをあわせた状態で[ALT+Enter](デフォルト設定の場合)
ここではScheduleListItemという適当なクラスをテストしてみることにします。ただのプレインオブジェクトです。
キャプチャ
そのままCreate Test

 

ダイアログが出て、ここで好きなテストフレームワークをとオプションが選べます。
testing-support-libで、JUnit4が使えるようになったということでJUnit4にしてみましょう。
JUnit4の場合、クラスの継承はしないのでSuperClassが空になりますが、ご心配なく。
setUptearDownはテストの最初と最後に実行される関数です。
とりあえず作ってもらったら楽なのでチェック。
下のメンバー関数は特にチェックしなくてもよいかも。
キャプチャ2

保存先を聞かれるけどそのままでOKでしょう。
src/androidTest/java/~~/**Test.javaが作られます。

public class ScheduleListItemTest {
	@Before
	public void setUp() throws Exception {

	}

	@After
	public void tearDown() throws Exception {

	}
}

テストを書く

テストを追加したい場合はメンバ関数を以下のように追加して
assert文を書けばOK

	@Test
	public void foo() throws Exception {
             assertEquals("31", day);
	}

JUnit4の使い方についてはここでは詳しく説明しませんが他のサイトで勉強してみてください。
参考:http://d.hatena.ne.jp/megascus/20130622/1371879646

 

assert文を書く場合、static importで
import static junit.framework.Assert.assertEquals;
を追加するといいです。これがないとAssert.assertEquals()のように書かないといけないので。

 

 

かんたんなテストのサンプルを書いてみます。
あんまり良いサンプルではないですが許してください。

import static junit.framework.Assert.assertEquals;

public class ScheduleListItemTest {

	private ScheduleListItem item;
	@Before
	public void setUp() throws Exception {
		item = new ScheduleListItem();
	}

	@After
	public void tearDown() throws Exception {
		//最後になんかする場合はここで。
	}

	@Test
	public void foo(){
		item.set(5, 8, "5/8日のすけじゅーる");
		
		assertEquals(5, item.getMonth());
		assertEquals(8, item.getDay());
		assertEquals("5/8日のすけじゅーる", item.getTitle());
	}
}

最初にsetUp()が実行され、itemがnewされます。
次にfoo()が実行され、各assert文が実行されます。
itemにセットした値が正しく入ってるかチェックしてるって感じです。

 

実行の設定

テストの実行に当たっての設定です。
まず実行ボタンの左のメニューよりEditConfigurationsを選んでください。
キャプチャ3

 

次に+ボタンからAndroid Testsを選択!
キャプチャ4

 

新しいテストの実行の設定が作られました。
キャプチャ5
名前がUnnamedになっているので、好きな名前に変えてOKです。
Moduleになってるので、テストするモジュールを選択してください。

テスト範囲が選べます
[All in Module]AndroidTestに入ってるモジュール全部。実行
[All in Package]パッケージを指定して、実行
[Class]クラスをひとつ指定して実行
[Method]メソッドを指定して実行

ここでは全部ということでAll in Moduleを選択しました。

 

TargetDevice
テストを実行するのにも、Androidデバイスが必要なので、
それぞれ実機を使うか、エミュレーターを使うか、ダイアログでその都度選ぶかするか、
などの選択肢です。
いつも実行するときに選択しているものにしておけばよいでしょう。

設定が終わったらOK

テスト実行!

今作成した実行設定を選んで、RUN!!!
キャプチャ6

こんなかんじでテストが実行されます。
オールグリーン!
キャプチャ7

コンテキストが必要な場合は・・・?

例えばActivityをテストしたい場合や、ファイルの読み書きのテストをしたい場合、
androidのAPIにアクセスするためにcontextを渡さなければいけないので、今回のようにはできません。
ActivityInstrumentationTestCase2というクラスなどを継承して作らなければいけないのですが、
それはまた次回に・・・・



この記事のトラックバック用URL - http://mashi.exciton.jp/archives/69/trackback


洗濯表示アプリ

洗濯表示が変わるそうですね。
そんなニュースを見たので、ちょっと簡単なアプリ作ってみました。

対し他アプリではないんだけど、
マテリアルデザインっぽくしてみよう~ということで
あんまりデザインはやらないんですが、
デザインとアニメーション少し頑張ってみました。

一番力はいってるのは新洗濯表示と旧洗濯表示の切り替えの部分で、
Meaningful transitionsで紹介されてるHierarchical timingを実装してみました。
意外にめんどくさかった!!!

グーグルのHierarchical timing

グーグルのHierarchical timing

GridViewで並べたアイコンの左上から順に切り替わっていくような形になってます。
これが実装されてるものあんまりないかもしんないから珍しいかもしれないです。
良かったらチェックしてみてください~

洗濯表示のHierarchical timing

洗濯表示のHierarchical timing

洗濯表示アプリ

洗濯表示アプリ



洗濯表示 – https://play.google.com/store/apps/details?id=exciton.jp.laundrysymbol



この記事のトラックバック用URL - http://mashi.exciton.jp/archives/61/trackback


PendingIntentとAlermManager

ActivityやServiceを時刻指定で起動させたいときは、PendingIntentを作成し、Alermマネージャーに登録する
この2つのクラスをなんとなくセットで使っていると動作がよくわからず、複数のタイマーをセットした時におかしなことになります。

この2つのクラスはどう働いているか、別々に考えるとわかりやすいです。

まず、よくあるサンプルコード


public foobarTimer(Context context, Calendar when, String message){
  //起動させたいActivity, ServiceなどのIntentを指定
  Intent intent = new Intent(context, MainActivity.class);
  intent.putExtra("tag_name", "hello");//起動時に渡したい値をセット

  //intentを指定してPendingIntentを作成する。
  PendingIntent pIntent = PendingIntent.getService(context, 0, intent, 0);

  //AlermManagerをコンテキストより取得
  AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

  //AlermManagerに起動する時間と起動したいIntentをセットしたpIntentを指定
  am.set(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), pIntent);
}

よくあるサンプルだし、通常のタイマーとしてはこれで問題なく動くんだけど、

PendingIntent pIntent = PendingIntent.getService(context, 0, intent, 0);

よくわかんないから0でいいや!ってなってしまいがち


Android ReferenceのPendingIntentをみると
getActivity(Context context, int requestCode, Intent intent, int flags)
第2と第4引数はそれぞれrequestCodeとflagsとやらを指定しろということになってる。

まず第2引数のrequestCodeは、そのアプリケーション内でPendingIntentを区別するためにユニークな値を入れる必要がある
たとえば幾つかのタイマーをセットできるアプリを考える。
先ほどのfoobarTimer関数を利用してこのように3つのタイマーを同時にセットした場合、これらはすべてrequestCode=0と指定されている

Calendar after10 = Calendar.getInstance().add(Calendar.SECOND, 10);
Calendar after20 = Calendar.getInstance().add(Calendar.SECOND, 20);
Calendar after30 = Calendar.getInstance().add(Calendar.SECOND, 30);
foobarTimer(this, after10, "10秒後です");
foobarTimer(this, after20, "20秒後です");
foobarTimer(this, after30, "30秒後です");

この場合、同じrequestCodeであることが原因で、3つが正しくセットされない。
結果としては30秒後に「10秒後です」と表示される。
というとんでもない事になります。


なぜこのようなことが起きるか掘り下げてみると、まずこの関数
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
必ず新しくPendingIntentを作り出すわけではありません。
登録されているPendingIntentを再び返したり、なければ新しく作成したり、などをしているようです。
それを判断するのが requestCodeflagsなわけです。

PendingIntentのFlagsの説明をみると

FLAG_CANCEL_CURRENT Flag indicating that if the described PendingIntent already exists, the current one should be canceled before generating a new one.
FLAG_NO_CREATE Flag indicating that if the described PendingIntent does not already exist, then simply return null instead of creating it.
FLAG_ONE_SHOT Flag indicating that this PendingIntent can be used only once.
FLAG_UPDATE_CURRENT Flag indicating that if the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent.

4つのFLAGが表記されてます。

詳しく説明すると

FLAG_CANCEL_CURRENT: 同じrequestCodeのPendingIntentが存在したら、それをキャンセルして新しく作ります。
FLAG_NO_CREATE: 同じrequestCodeのPendingIntentが存在すればそれを返します。そうでなければNullを返します。
strong>FLAG_ONE_SHOT: 一度特定のrequestCodeを持つPendingIntentが作られたら、それ以降で同じrequestCodeを指定された場合は最初に作られたPendingIntentを返し続けます。
FLAG_UPDATE_CURRENT: 同じrequestCodeのPendingIntentが存在するばあい、それをつかうが、putExtraの値は新しく更新します。

という指定になっています。
flagsに0を指定した場合にどうなるか、見つけられなかったのですが、FLAG_ONE_SHOTと同じ動きをしているとおもわれます。


そしてAlermManager.set()ですがこれは単純に、指定された時間にPendingIntentを実行する。
ただし、すでに同じrequestCodeのPendingIntentがセットされていたら、それを更新する。と考えればよいです。

30秒後に「10秒後です」と表示されたのは、2回めのPendingIntent.getActivity()で同じrequestCodeが指定されたため、
1回めに作成された「10秒後です」がセットされたPendingIntentが返されて、それが30秒後の指定でAlermManager.set()されてしまったために起きた現象です。


PendingIntentとAlermManagerを使う場合は
requestCodeを意識して、書き換えなのか、新規登録なのかを考えながら書く必要があります。

以下のサイト参考にさせていただきました。
http://d.hatena.ne.jp/yujimny/20110303/1299115905



この記事のトラックバック用URL - http://mashi.exciton.jp/archives/45/trackback