2012年12月25日火曜日

Play文字化け対策

WindowsのcmdでPlayをコンパイルなどしていじる際発生する"文字化け".
こいつを回避するには先に

set _JAVA_OPTIONS="-Dfile.encoding=SJIS"

と打っておいてやるといいらしい.







ぶっちゃけよくわからないけど('A`)

参考 

2012年12月18日火曜日

Play! ~チュートリアルをやってみた後編

前回からのさらに続き. いい加減終わりたい(;ω;`)

7. Taskフォームの作成

今回はTaskクラスなのでTaskフォーム. UserクラスならUserフォーム. まんまですね(・ω・`)
イメージは中身のクラスを運ぶコンテナ的な何か.
準備としてはTaskクラスの方に
import play.data.*
が必要とのこと. しかし例ではいきなり必要な部分だけimportしてるし('A`)
準備ができたら今度はコントローラの方に,
 Form<Task> taskForm = form(Task.class);
を宣言. これにより, ビューとコントローラの間でのデータのやり取りができるほか, 制約を簡単に加えることができる.
制約に関しては, 例えばTaskでは必須入力項目としてタスクのラベルに制約をかけたいなら, Taskクラスの方で
@Required
public String label;
としてやるだけで, やれデータが入っているかー, なんてif文とか書かなくて済むのである.

8. トップページ描画

Taskフォームを用いて実際にページを見てみる. Application.java のtasks()の戻り値を,
return ok(views.html.index.render(Task.all(), taskForm));
Task.all()はstaticな関数, Taskのリストを返す. これとFormを投げて準備完了.
これでここまできちんとコピペしてきていたら, 適当にブラウザを立ち上げ 「localhost:9000」で見られるはず. (ちゃんと play run していれば)
ただしこの時点ではTaskのCreate機能を積んでいないので, 次の項目で作る.

9. Createボタンの実装

もう訳とかどうでもよくnこの項目でタスクの新規作成処理を積み込む.
Application.javaのnewTask(), この内容を作成する.
public static Result newTask() {
  Form<Task> filledForm = taskForm.bindFromRequest();
  if(filledForm.hasErrors()) {
    return badRequest(views.html.index.render(Task.all(), filledForm));
  } else {
    Task.create(filledForm.get());
    return redirect(routes.Application.task());
  }
}
さらっと書かれていてコピペしてスルーしてしまいそうなところだが, 実はイロイロ大事な部分が含まれているという罠. チュートリアル汚い.

2行目 bindFromRequest() これはリクエストからFormを取り出すメソッド. これをしないといつまでもこのクラスの最初に作成した空のtaskFormを参照してしまい, なにも表示されないことに折れるまで首を傾げるハメになる. もちろんリクエストが無いときは取れません.

3行目 filledForm.hasErrors() 2行目で取得したものにエラーが無いかチェックするメソッド. エラーがあったらtrueが返り, 4行目のようにバッドリクエストを返すようにする大事な処理.

6行目 filledForm.get() これでFormの中に含まれるTaskを取り出す. Formのまま投げないように. この6行目でTaskクラスから新規タスクを作成する.


10. データベースによるTaskの保存

正直わかんないorz なんでいきなりH2DBが絡んでくるのよ…('A`) 前に使ってH2DBの準備してたからいいけど, これ準備無かったらどうなるんだろう…
超簡単に.
conf/application.conf, ここまでずっと横をスルーされてきたこいつをいじる. 中身はいろいろ必要なことが書かれているので下手にいじると爆死します. "#" がその行のコメントアウト. チュートリアルではaddと言っているが, 既に書かれた上でコメントアウトされているので, 混乱を避けるためにも#を外して対処しましょう. ちなみにその下にパスワード設定なんかもありますがいじって無いので省略.  このちょっと下に次の設定もコメントアウトされているのでこちらも対処.
その後Taskクラスをチュートリアルのように書き換えると, 見事タスクが増えるようになりました.
うん, よくわからんorz.

11. タスクの削除

これ逆に章分ける必要あるのか?
DBへの接続の設定は済んでいるので, 削除部分をApplication.javaへ書き込む.
以上.


デプロイはやっていないので今回は省略. なのでここで終了.
こっちを見るとより詳しく見ることができる.





最後グダグダだぁ…('A`)



2012年12月17日月曜日

Play! ~チュートリアルをやってみた中編②

はたしてここで終われるのか…終われなかった…orz
前回からの続き.


3. 開発ワークフロー

直訳でも気にしない. 要は app/controll/Application.java をいじるとこうなるよ! ってお話. 前回の1. でやっちゃった気がしなくも無い(・з・)
1. では他のViewを呼び出していたけど, Stringを直に放り込むことも可能. この場合Content-Typeは text/plain となりなんとも味気ないページがでてきます.
また, コードを変えたときにコンパイルとサーバ再起動を自動でやってくれるのはPlayの利点の一つ. 特にエラーが起きたときや構文エラーがあったときは, ブラウザ上にその箇所を表示してくれる親切設計. ただそのことを,
「As you can see, errors are beautifully displayed directly in your browser.(ご覧の通り, エラーはあなたのブラウザ上に直接美しく表示されます)」
美しくって…. しかもエラーによっては文字化けするし('A`)

4. アプリケーションの準備

直訳でも(ry. conf/routesを編集することで, アクションの振り分けができるよー, ってお話.
また最終行の,
POST    /tasks/:id/delete       controllers.Application.deleteTask(id: Long)
ここで, アクションに引数が持たせられる他,  URL部分に「:id」と入れると, 引数に使ったidをURLに埋め込むことができるよ!(・∀・)といったことも.
当然このconf/routesだけをいじってもアクションのほうを書かないとエラー吐かれるよ, ってことをわざわざ3. で出たブラウザ表示を用いて例示している. 当然ですね('A`)
なのでapp/controller/Application.javaにアクションを書いていきましょう. この時, まだ内容が決まっていないなら,
return TODO
としておくことで, とりあえずコンパイルは通るようになるよ, ということらしい.
ちなみにこのまま走らせると 「501 Not Implemented(未実装)」 が返ります. 便利.
最後はリダイレクトのお話. Viewを通さず, 別のアクションを呼びたいときは,
return redirect(routes.Application.tasks());
と書くことで, 直接conf/routesに飛び, アクションの振り分けから再開できるよ!(・∀・)ってこと.
このときのステータスはちゃんと 「303 See Other(他参照)」 でリダイレクトされる. これまた便利.

5. Taskモデルの準備

直(ry. ようやっとModelの登場. しかしデフォルトではディレクトリは作ってくれないので, まずは app/models ディレクトリを作る必要がある.
ディレクトリを作ったら中に Task.javaを作成. それだけ. ( ゚д゚ )
このあたりで今回では終わらないことを悟り 中編②とか妙なタイトルに変更. どうしてこうなったorz.


6. アプリケーションテンプレート

逆に訳すに訳せない('A`) Todoリストを表示するためのHTMLを作成する…のだが.
なんかやたらすっきりしてる. 2. でもちょっと書いたが, @~というのはPlay!フレームワークが関数のように扱ってくれて, 自動でHTML文を生成してくれる便利なツールとの事. ただし使うためには,
@import helper._
を宣言しておく必要がある.
中でも, @form は重要. この宣言だけで<form>タグを生成してくれる. マジ便利. もちろん例のように引数を放り込むことも可能.
また, 他にもテキストボックスなど<input>タグシリーズを生成する@input等もある. これもまた便利.
チュートリアルにある最後の数行,
@form(routes.Application.newTask()){
  @inputText(taskForm("label"))
<input type="submit" value="Create">
}

この宣言で,
<form action="/tasks" method="POST">
  <dl class=" " id="label_field">
    <dt><label for="label">label</label></dt>
    <dd><input type="text" id="label" name="label" value=""></dd>
  </dl><input type="submit" value="Create">
</form>
とこれくらい作ってくれる. idなんかを追加で指定してやることも可能.
ちなみに生成するHTMLをカスタムすることもできるらしい.
@inputは他にも@inputPasswordなんてのもあるが, ボタンに関してはまだ見つかっていない.
無いのかな…(・ω・`)






次だ…次で終わらせる…('A`)


2012年12月13日木曜日

Play! ~チュートリアルをやってみた中編

前回に引き続きPlay!チュートリアル.
ついにコードをいじり始める


Playちゅーとりある後編


0. 準備いろいろ

とりあえず前回の3. でサーバが run している状態から続き.
run していなければとりあえず run.
そしてもうひとつ必要なことが, MVCモデルの理解.
理解といっても詳細に説明できるほど, なんてことはなく, 
「まぁ役割に応じてそれぞれ管理するところを分けてんだへぇー('A`)」
くらいの認識があれば十分.(なはず(・ω・`)大丈夫かな)
詳しくはグーグル先生あたりに聞くといろいろ教えてくれるはず.
まぁMVCが
「M(モデル), V(ビュー), C(コントローラ)」
を表現してることだけ知ってれば自分はどうにかなってる('A`)たぶん

1. アクションとコントローラ

まずはアクションとそれをまとめるコントローラのお話らしい. もう少し構造について話してからでも遅くない気がするんだけどなぁ…(・д・`)
conf/routesファイルをテキストエディタあたりで開くとチュートリアルにあるような文が見られるはず.
GET /       controllers.Application.index()
いきなりなんじゃいorz特に右のお前.
これだけだとらちが明かないのでapp/controllers/Application.javaも隣に開いてみる.
すると中にはjavaコード. よく見てみるとなにやらメソッドが入ってる.
  public static Result index() {
    return ok(index.render("Your new application is ready."));
  }
このindex(), これがちょうど先ほどroutesファイルに入ってた右のあいつにあたる.
なのでApplication.javaではなく, Hoge.javaのindex()を呼びたいなら,
GET /       controllers.Hoge.index()
になるはず.
そして左はリクエストの情報. なのでチュートリアルのほうで和訳すると,
「GETメソッドで localhost:9000 でアクセスしてきた時, controller.Application.javaのindex()を呼び出すよ!(・∀・)」
という設定を書いてることになる.

そしてApplication.index(), こちらが返すResult型がresponseとして扱われる, との事.
return しているものも簡単に和訳すると,
「index に"Your new application is ready."というStringを与えて, ステータス200 OK で返すよヽ(・ω・)/」
って事らしい, ok の部分を badrequest などに変えるとステータスを変えてreturnできます, index.render()についてはもうちょっと後に出てきます.

簡単にまとめると,
 conf/routes -> リクエストに対するアクションの振り分けをします.
  app/controllers/ -> アクションを内包するコントローラクラスを入れます.
ってことらしい.
ちなみに今更だけど, ここではアクションとはindex()なんかのメソッドにあたります. たぶん(・з・)

2. ビュー

別にチュートリアルでは分かれて無いけど. だいぶ冗長なので.
こんどはapp/views/index.scala.htmlをテキストエディタで開いてみましょう. ファイル名気持ちわる('A`)
ちなみにこいつが1. ででてきた index.render() のindexにあたる.
なので main.render() にするとすぐしたの main.scala.html を指定することになる.
さてindex.scala.html の中身はというと…
@(message: String)

@main("Welcome to Play 2.0") {
    
    @play20.welcome(message)
    
}
これだけ.
これまた @ だらけで良くわからん.
少しずつ見ていくと, まず最初の
@(message: String)
いきなりわけがわからないが, なにやら変数の宣言にも見えなくは無いか.
しかしこれはどちらかというと引数の宣言に当たる.
すなわち, 1. のApplication.index() で与えられたString「"Your new application is ready."」はここで message に格納される.
ここで引き受けたら後は5行目のように, コード内で使えるようになる.
そして
@main("Welcome to Play 2.0") {
    
    @play20.welcome(message)
    
}
mainはちょうどmain.scala.htmlにあたる, 後ろの2つは引数. 
 @play20.welcome(message)
こいつは良くわからない('A`)が働きとしては message を引数にデフォルトのページのhtmlを返すメソッドとして働く.
ということは@main以下は,
「main.scala.htmlに, String型 と Html型 2つの引数を投げてここに貼るよ!(・з・)」といったところ.
なのでmain.scala.htmlも開いて確認してみる.
@(title: String)(content: Html)

<!DOCTYPE html>

<html>
    <head>
        <title>@title</title>
        <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
        <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
        <script src="@routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
    </head>
    <body>
        @content
    </body>
</html>

はい, 一番上にStringとhtmlを受け取る準備ができていました.

これが大体の流れ. チュートリアルの内容にだいぶいろいろ足したけど('A`)
おかげで終わらなかったorz

続きはまた次回にでも.







次で…終わらない気がするーヽ(;´Д`)ノ

2012年12月12日水曜日

Play! ~チュートリアルをやってみた前編

最近Unity, Playをいじり始めました.
おまけにいじり始めたBlenderに泣かされてます.
インタフェースが実に変態的です. でもすごい.


いろいろごちゃごちゃになってきたのでPlayから少しメモメモφ(・ω・ )


Playちゅーとりある


Playとは要するにWebアプリを簡単に作るためのフレームワークらしい. 実にわかっていない感想.
とりあえずここのチュートリアルをやってみる.


1. 下準備

とりあえずDownloadからPlayを貰ってくる. 現時点ではplay-2.0.4.zip. 地味に時間がかかる…(・ω・`)
もらえたら展開しつつ適当な場所に丸ごと移動. 自分はC:\の下にPlayディレクトリを作ってそこに.
さらに展開した中に入っているplay.bat. これを使うためにこのディレクトリにパスを通しておく.

ここまできたら下準備は完了.

2. アプリケーションの作成

C:\あたりでコマンドプロンプトを開いて, とりあえず

play help

とでも打ってパスが通っていることを確認. 確認できたらAndroidでいうプロジェクトを作成する.
コマンドは
play new アプリケーション名
名前はお好きに. これでコマンドプロンプトを開いた場所にディレクトリを作成する準備が整う. なので別の場所で作りたいならそこでコマンドプロンプトを開きましょう.

上記コマンドではアプリケーション作成の準備が整っただけ. コマンドプロンプトはこんな感じかと
AAには若干無理を感じる(・ω・`)
とりあえずアプリケーション名, そしてテンプレートにどの言語を用いるかを聞いてくる.
言語はscala or java



…scalaわからないからjavaで作る('A`)
これで最低限必要なものは一通りそろった!

3. デフォルトページを見る

とりあえずデフォルトはどんなものか見に行きましょう. できたディレクトリの中には結構イロイロ入ってます.
一通り眺めたら今度はブラウザで表示するやり方をデフォルトページで練習.
上で開きっぱなしのコマンドプロンプトで
cd 作ったディレクトリ名
で移動. 移動できたらとりあえず
play
と入力
するとまたAAのようなplayの文字が. 無事出現したら最後のコマンド
run
これでPlayがサーバの役割も果たしてくれる(らしい)

落ち着いたら今度は適当なブラウザを起動. アドレスに「localhost:9000」と打ってみると…

でました.+(・ω・0)*
このデフォルトページはそのままチュートリアルっぽい内容にもなってます.

4. サーバを切る

終わったからっていきなりコマンドプロンプトを消すのはちょっと危険. サーバを止めるときは
ctrl + d
これで止まったら今度はplayを終了する.
exit
これでPlayも終了できる.
なお, 3. においてplayと打ったところを
play run
と打つと直接サーバがrunします. サーバを止めるときも一緒にPlayも止まります.
消し忘れ防止にいいかも?






これでチュートリアル前半終了.
次からコードを見ていく…いつになるかわからないけどヽ(;´Д`)ノ






画像に変なもの写ってないよな…('A`)

2012年11月28日水曜日

ViewFlipperでページめくり ~おまけ編

ここからはおまけ.

前回の続きでフリックでページをめくる処理を実装する.
要するにフリックイベントを取りに行くわけでもはやViewFlipperほとんど関係ない気がする('A`)

OnGestureListenerをもちいたフリックイベントの取得

ついにタイトルすらViewFlipperから遠のいたけど気にしない.
実装するのはActivity. ここに

implements OnGestureListener

してやる. 当然 eclipse「メソッドのオーバーライド足りてねぇぞゴルァ(゚Д゚#)」と怒られるので言われるままに作成.
ただし今回使うメソッドは2つのみ.

① onFling
② dispatchTouchEvent

特に②が忘れられがちなので注意

① onFling

実際に受け取ったフリックイベントから処理を行なうクラス. 

@Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) {
    float dx = Math.abs(e1.getX() - e2.getX());
    float dy = Math.abs(e1.getY() - e2.getY());
    if (dx > dy) {
      if (velocityX > 0) {
        flipper.setInAnimation(slideInFromLeft);
        flipper.setOutAnimation(slideOutToRight);
        flipper.showPrevious();
      } else {
        flipper.setInAnimation(slideInFromRight);
        flipper.setOutAnimation(slideOutToLeft);
        flipper.showNext();
      }
      return true;
    }
    return false;
}

たまにはsyntaxhighlighterの色を変えてみたかった(言い訳)ので参考サイトをほぼコピペを更にコピペというだめっぷりorz
3行目, 4行目でフリックのX方向, Y方向の移動距離をそれぞれ取得,
5行目で比較してX方向のほうが大きい=横にフリックする気でフリックした 時のみ処理を行なう.
6行目でフリックのベクトルが右方向か左方向かを判定, 右なら1ページ戻る, 左なら1ページ進む, を処理させる. 処理の内容は前回参照.
それだけ. これでイベントが飛んでくれば処理してくれる.

②dispatchTouchEvent

一度ここを設定し忘れて「あっれーうごかないぞー(゜д゜;三;゜д゜)」とか言ってたことがあるのでorz
まずonCreateあたりで

GestureDetector gestureDetector = new GestureDetector(this, this);

を取得.
そして問題のdispatchTouchEvent
@Override
public boolean dispatchTouchEvent(final MotionEvent event) {
  return gestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event);
}

eclipseの自動生成に出てこない引っ掛けっぷり. ひどすぎる('A`)
コイツを作っておかないとそもそもイベントを取ってくれませんorz


これらを設定してやると, おめでとう!ボタンで動いていた画面がフリックで移動するようになったぞ!
となる.

onFlingの3行目, 4行目でとったように, e1.getX()でとった座標で条件分岐してやれば, 特定の範囲でフリックしたときのみイベントを取るなんてのもできそう. やってないけど(・ω・`)





長かった…('A`)

ViewFlipperでページめくり ~動作編


前回からの続き. ようやくページめくりのお話.

B. コード上で動きを指定

とりあえず

ViewFlipper flipper = (ViewFlipper) findViewById(R.id.flipper)

で ViewFlipperを取得.
ページを送る/戻す処理は

flipper.showNext()/flipper.showPrevious()

これだけ.
これをボタンのクリックイベントだったり画面のフリックイベントだったりに呼ぶようにしてやれば, それだけで次の/前の子ビューを表示してくれる.便利!

ただこれだけだと一瞬でページが切り替わる非常に味気ないページめくりに…
なので折角だしアニメーションを仕込んでみる.

手順は
① アニメーションの情報を仕込んだxmlを作成
② ①を基にflipperにアニメーションをセット
の2本立てでお送りします

①xmlを作成

まずはres/animを作成. 基本自動生成はされていないので自作のはず.
ここにAndroid XML File を作成します. RootElementは「translate」.
内容は,

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="-100%p"
    android:toXDelta="0%p"
    android:fromYDelta="0%p"
    android:toYDelta="0%p">
</translate>

ためしに左からページが画面に入ってくるアニメーション.

android:durationがアニメーションに書ける時間(ミリ秒)
XDelta, YDeltaはそれぞれViewの左上の座標の位置を指定. 0%pで今写っている画面の左上を指す.
fromがアニメーション開始時の位置, toがアニメーション終了時の位置を指す.
のでこのアニメーションは,
画面外ちょうど画面1枚分左から, 500ミリ秒かけて画面ぴったりに収まるように入ってくる
アニメーションとなる.
ちょっと指定を変えれば出ていく, 逆方向の動きはもちろん, 斜めからスライドイン/アウトだって指定できちゃう(゚∀゚)ラクチン!

これを,
1. 左から入ってくる
2. 右へ出て行く
3. 左へ出て行く
4. 右から入ってくる
の4タイプ分用意します.

②flipperにアニメーションをセット

xmlを用意できたらいざセット

Animation slideInFromLeft = AnimationUtils.loadAnimation(this, R.anim.slide_in_from_left);
Animation slideOutToRight = AnimationUtils.loadAnimation(this, R.anim.slide_out_to_right);
flipper.setInAnimation(slideInFromLeft);
flipper.setOutAnimation(slideOutToRight);

slide_in_from_leftがちょうど①に挙げたxml. 同様にAnimation を作成し, InとOutそれぞれflipperにセットしてやる.
新しいページの入り方と古いページの出方…のはず(・ω・`)
これでOK.
ただしIn, Outそれぞれアニメーションは1個ずつしか登録できないため, 上記のコード全部で右にページを送る処理ひとつ.
左にページを送る逆向きの処理を同じ flipperにセットしたい場合, 処理を呼び出すごとにセットしてやらないと, 最後にセットしたアニメーションのみ実行することになります.
なので1ページ戻るアニメーションを実現するなら,

 flipper.setInAnimation(slideInFromLeft);
 flipper.setOutAnimation(slideOutToRight);
 flipper.showPrevious();

これ全部を「戻る」ボタンあたりのonClickで呼んでやる必要がある.逆もまた然り.


これで一応アニメーションしながらページめくりはできる. できるけど…なんか違う.
やっぱりフリックでページをめくりたい!


なのでさらに続けてみます.







あともうちょっとだけ続くんじゃ('A`)

ViewFlipperでページめくり ~ページ作成編

ホーム画面やらiPhoneやらでおなじみ横フリックでページめくり.
これを利用して, 数ページに分割したランキングを作りたい! と調べてみたら, ViewFlipperなんて便利そうなViewを見つけたヽ(・ω・)/.

ViewFlipperで簡単ページめくり


必要なものは
A. <ViewFlipper>タグを用意
B. コード上で動きを指定

まずはxml

A. <ViewFlipper>タグを用意

使いたいActivityのレイアウトに

<ViewFlipper
       android:id="@+id/flipper"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
</ViewFlipper>

これだけ. 実に簡単. ちなみにこの外にボタンやらなにやら置いてもOK. Layout内で<ViewFlipper>タグが陣取ったエリアだけでページめくりしてくれます.

ただしこのままだとめくる「ページ」が無いので, 中に子ビューを入れる.
入れる方法は2通り.

①. このままxmlに突っ込むぜ!
② いやコード上で動的に作りたいんで

①はまた楽. <ListView>なんかと同じようにタグの間に宣言するだけ.
例えば…

<ViewFlipper
       android:id="@+id/flipper"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
       <include android:id="@+id/flipper_child" layout="@layout/flipper_child"/>
</ViewFlipper>

<include>を使うと見やすくまとまってよろしいかと.flipper_child.xmlはまた別にLayoutを作って用意しておけばOK. ただ<include>は2個以上入れないとページめくりになりません. まぁ当たり前だけど('A`)
ページ数が決まっているならばこっちがオススメ.

②はちょっとめんどい. 追加自体は

ViewFlipper flipper = (ViewFlipper) findViewById(R.id.flipper);
flipper.addView(childLayout)

問題はこのchildLayout.すでにLayout自体ができているならひたすらViewを作成→addViewで良いのだが, それなら<include>使ったほうが誤爆は少ない.
また今回は順位表のように決まったLayoutを使いまわして作りたかったうえに, 何ページになるかが決まっていない始末.仕方が無いので子ビューのLayout.xmlを一枚テンプレート的に用意して動的に内容を作って addしていく.


View childLayout = this.getLayoutInflater().inflate(FLIPPER_CHILD_LAYOUT_ID, null);
ListView list = (ListView) childLayout.findViewById(R.id.list);
list.setAdapter(listAdapter);
list.setScrollingCacheEnabled(false);
list.setOnItemClickListener(itemListener);


完璧今回使ったもののコピペ. 手抜きではありません. ええ決して.
1行目で子ビューを新規生成. FLIPPER_CHILD_LAYOUT_IDは子ビューのLayout.xmlのid. 第二引数は今回は特に親のViewGroupをとらないのでnull…で良いのかな(・ω・`)
2行目は子ビューのLayout.xml内に自分で設置したListViewを取得. childLayoutからfindViewByIdしている点には注意.
3行目はそのListに値をぶち込む処理. Adapterに関しては今回はノータッチ. ただ何ページも作る際はAdapterを毎回新しく作るなどちゃんとしておかないと同じ内容のデータが延々と並ぶ苦行のFlipperが完成するので注意.
4行目は完全にListViewの設定. これをしておくとListViewスクロール時, 背景の色が変わるアレを無くすことができます. 背景色を指定しているときなんかに合わせてどうぞ. Flipper関係ねー.
5行目もListの OnItemClickListener のセット. ここで毎回ちゃんとしておくとどのページのListViewもイベントが取れるようになります. ただListenerの中でgetitemする際は,

ListView list = (ListView) parent;
Object item = (Object) list.getItemAtPosition(position);


しておかないとうまく取れないかも…
ともあれこれでFlipperにページを収められたはず.

…長くなっちゃったのでページを動かす処理は次回


2012年11月13日火曜日

selectorを用いた表現

androidに標準に入っているButton
押したら青く?反応するこの反応の色なんかを自分で設定できるらしいのでやってみた.


selectorの利用


例えばこんなボタン
いつものボタンを用いず, 背景色で色付けしたものだが, 当然このままでは押しても視覚的に変化は無し.
希望としては, ボタンをタップしたら,

例えばこんな風
に色が変わって反応して欲しいもの. だからといって押されるたびに

setBackgroundColor(int Color)

とかいってセットしては指が離れたらまたセットしなおすとかとてもじゃないけどめんどくさい('A`)

そこで登場 selector 

1. selector.xmlの用意

前回のグラデーションのお話でも用いた, res/drawableディレクトリを使用.やっぱり色は先に作っておくのが吉. またボタンに表示するテキストは drawableではいじれないので, res/colorディレクトリへ内容がほぼ同じものを, テキスト用 selector.xmlとして作って使いましょう.

わかりやすい名前で.xmlを作成.この時, ボタンを押されたとき, 押されていないとき両方の色の指定をこの.xmlでやるので, わざわざそれぞれ.xmlを作ったりしないように.

xmlを作成する際, selector を先に Root Element: から選んでおくと楽…かな(・ω・`)
どうせ中で宣言できるけど.


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_pressed="true"  android:drawable="@color/押されたときの色"/>
    <item android:state_pressed="false"  android:drawable="@color/普段の色"/>
</selector>

よくある話で <selector> がデフォルトの <animation-list> になっているまま作成→動かねえぞこれ
(゜д゜;三;゜д゜)
なんてこともあるので注意. …ないか('A`)
<selector>の中に2つの<item>を入れ子にして宣言. <item>にはそれぞれ"状態"がtrueのとき, falseのとき, それぞれ使う色を指定できる.
また"状態"にあたるのが

android:state_pressed


これが"ボタンが押されている状態"を表す. なのでこの場合はボタンが押されていれば上, 指が離れたら下の<item>を参照するぞ, というselectorになる.

ちなみにこの"状態", ラジオボタンに用いたいときは,

android:state_checked

を用いる必要がある. でないと押した瞬間だけ色が変わるラジオボタンの出来上がりである.orz
なおテキスト用は

android:drawable

のところを

android:color

に書き換えてやるだけ. ってゆーかdrawableが無い.

2. 実装

用意ができたらいざ実装. selectorを使いたいボタンに対して,

 android:background="@drawable/背景用selector"
 android:textColor="@color/テキスト用セレクター"

と指定してやるだけ. これで後は何もせずとも勝手に色を変えてくれます.

またしてもちなみにラジオボタンで使う場合.

android:button="@null"

してやらないと, ラジオボタンの
こいつ('A`)
が居座り続けるという大惨事に.


画像が使いにくい…(・ω・`)

2012年11月8日木曜日

Androidでアプリの背景色にグラデーションを使用する

私用アプリの作成中ふと思う

「背景寂しいなぁ…」

とか呟いていたら割と予想外の出会いを果たしたのでメモメモ


グラデーションを利用する


1. 始めの色, 終わりの色の作成

グラデーションというからには ある色 から ある色 へと変化するので, その始めの色と終わりの色を作成する. 
場所は res/values/color.xml にでもまとめておくといいかと. 無ければ作れば良い.


2. グラデーションの指定

色が決まったらいよいよグラデーションの指定.
res/drawable ディレクトリにお好きな名前で.xmlを作成する

<?xml version="1.0" encoding="utf-8"?>
<shape  xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient android:startcolor="@color/color_back_gradient_start"
        android:endcolor="@color/color_back_gradient_end"
        android:angle="315">
    </gradient>
</shape>

colorは自作の色.
<shape>では背景に関していじることができる模様

android:shape="rectangle"

で形状を指定. この場合は長方形になる
ちなみに oval を指定すると楕円形になります.

そして<gradient>でそのグラデーションの内容の指定を行なう.

android:startcolor="@color/color_back_gradient_start"
android:endcolor="@color/color_back_gradient_end"
android:angle="315"

このあたりは見たとおり. 上から グラデーションの始まりの色, 終わりの色, グラデーションをかける角度 を指定している.
注意は3つ目の角度. この角度はの基準は 左→右 である点に注意. なので 0 を指定すると左から右へのグラデーション. ここから角度を増やすと反時計回りにぐるぐる回りだす.
またこの角度, 指定できるのは 45 * n である数値のみである点にも注意. 負の値を入力すると逆回転します.

3. グラデーションの配置

作った.xmlを書くwidgetの android:background に指定してやればOK.
ね?簡単でしょう?



ちなみに<shape>には他にも 角をいじる<corners>や, 枠線をつける<stroke>等があるらしいけど, 今回はいじってないのでまたの機会に





顔文字使ってねぇ!Σ(・д・)

2012年11月1日木曜日

androidのアプリケーション名の落とし穴

「アプリケーション名がStrings.xmlのapp_nameで出てこない」
こんなことを言われたのが先日.

「そんなんManifestの<application>にandroid:labelタグで設定されてるやん」
とか調子こいていたのもつかの間


「app_nameが出てこない…( ゚д゚ )」



ということで今回のお題

ランチャーに表示するアプリケーション名の設定場所


結論から言うと原因はManifestの<intent-filter>
ただしこいつは悪さをしていたわけではなく, むしろ一生懸命仕事をした結果が原因らしい.

通常アプリを開いて最初に開きたいActivityには, Manifestにて

<intent-filter>
    <action android:name="android.intent.action.MAIN"/>

    <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>


と宣言するはず.
すると, この<intent-filter>, こいつがランチャーに表示する名前を探し出す.
問題はこの時, <application>へ探しに行ってくれれば良いのに,

まず自分
  ↓
無ければ自分を含むActivity

の順に探そうとする.
結果, 名前を指定してやらなかったことが災いして, Activityにつけた名前を
「これがアプリケーション名だ!+(゚∀゚ 0)*」
とうれしそうに表示するわけですよ.
それじゃない…それじゃないんだ…!

なので

<intent-filter
    android:label="@string/app_name">
    <action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

といった形で, <intent-filter>のlabelで教えてやると, 望んだとおりのお仕事をしてくれます.





ちなみに  自分を含むActivity にすらlabelが無かった場合, 表示するのは
そのActivityのパッケージ名 + Activity名
…そりゃねぇよorz
<application>さん使ってやれよ…

11/19訂正: ちゃんと<application>から取ってきてくれるみたいですorz
もうやだこのIS03

2012年10月29日月曜日

SQL小ネタ

本当に小ネタ

SQLiteで
データベースからデータを取り出す際ランダムに並べ替えて取り出す


SELECT * FROM table ORDER BY random()

これだけ.
これでわざわざ取り出してから並べ替えるなんて手間がかからない!

ちなみにMySQLでは


SELECT * FROM table ORDER BY rand()

らしい(未確認).


だってMySQL使わないし…(・ω・`)

なので
「ORDER BY句にrandom()とか放りこんどきゃいいのかー」
なんていって別のSQLで動かないとか言われても困る
って言う逃げ口上

Androidで設定を参照, 操作するあれこれ -画面の輝度編-

忙しかった…余計な仕事は背負い込むもんじゃないね('A`)


だいぶ間が開いてしまったけど
久々にAndroidさんに怒られたので書いてみる.


画面の輝度の操作


簡単に言ってしまえば「画面の明るさ変えるよ(゚∀゚)」ってだけなこと.
一昔前にこれ利用したライトアプリなんかあったとか無かったとか.

いつもどおりAndroidさんの設定に手を加えるべく.お邪魔するのは

import android.provider.Settings.System;

Androidの設定は基本ここにお願いなことはいい加減わかってきた.

1. 設定の変更


値が入っているのは

System.SCREEN_BRIGHTNESS

今回はここ.
ここの値をputしてやれば良いのだが値に注意.

まず値は
0 ~ 255
であり, また機種によっては
0 = ブラックアウト
と認識して何も見えなくなってしまうらしい点.
なので値は
1 ~ 255
にしておくといろいろ安心.

また0% ~ 100% で表記したいなら自分で計算してやるよろし.
というわけで


System.putInt(ContentResolver, System.SCREEN_BRIGHTNESS, "値");

当然値はint型でok.

2. 画面の明るさの変更


お前1. でやったじゃん と言う無かれ.
1. はあくまで 設定の変更 だけで, すぐにその設定が反映されるかといえば答えはNO.
なのですぐに反映してやりたいとき, また1. を利用する際, デモンストレーション的に明るさを変えたいときにはこちら.

ただしここで怒られた.
実は1. も2. もAsyncTask使ってUIスレッドの裏で処理をさせようとしたところ

おまUIスレッド以外からUIイジってんじゃねーよ ゴルァ!!щ(・Д・´#щ) =3

と怒られましてorz
1. はともかくこれからいじる2. に関してはUIスレッド上でやりましょう, ってお話.

ひとまずソース

LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.screenBrightness = "値";
getWindow().setAttributes(layoutParams);

やってることは割りと単純.
1行目で現在の画面の情報を取得.
2行目でその情報のうち 画面の輝度 に好きな値を投入(ただしfloat型かつ0.0 ~ 1.0の間という統一感の無さ)
3行目で反映…のはずなんだけど…なぜか無くても変わる!不思議!

…なんでだろ(・ω・`)

まぁとりあえずそのActivityくらいしか明るさは保たないので一時的なしのぎにでも.
最初に述べたライトアプリなんかにはむしろ都合が良いとか何とか.



まただらだらと書いてしまった…('A`)



2012年10月15日月曜日

Androidで設定を参照, 操作するあれこれ -バッテリーwithService編-

以前のバッテリー情報取得のその後.
Activityの内部クラスにしとけばいいや, 参照しやすいし.
などと考えていたら

Serviceに乗せなさい



orz

通達が来ましたとさ.


Serviceを用いてBattery情報を得る

当初は
「ServiceからActivityを書き換えるってどうやるんだ…?Binder?ServiceConnection?Messengerを使えば値を渡せるのか!」
などと迷走を続けていたところ

sendBroadcastでえぇやん(意訳
でないと汎用性下がるし

と2度目のorz
ほぼ一日かけてたどり着いたMessengerは無に返り, 晴れてsendBroadcastによる実装が残りましたとさorz

という愚痴を書きたかっただけ.

1. Service側

まずはService側. いたって単純で, Intent.ACTION_BATTERY_CHANGEDを受け取ったらオリジナルのIntentに必要な情報を載せて発信するだけのもの.


public class BatteryService extends Service {


    public static final String ORIGN_ACTION = "orignbatteryaction";

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
                int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                // オリジナルのActionでintentを作成
                Intent sendIntent = new Intent(BatteryService.ORIGN_ACTION);
                // levelを載せる
                sendIntent.putExtra("level", level);
                sendBroadcast(sendIntent);
            }        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(mReceiver, filter);
    }

    @Override
    public void onStart(final Intent intent, final int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
        Log.i("hogeBatteryService", "unregisterReceiver");
    }

    @Override
    public IBinder onBind(final Intent arg0) {
        return null;
    }
}

たまにはまるっと載せてみる.mReceiverの中, コメントにある通りACTIONの部分を自作してやるだけ. 名前はユニークになるように. 万一被ると大変なことになる…かも?('A`)
後はintentを送る際,

startActivity(sendIntent)

ではなく
sendBroadcast(sendIntent)

を用いれば, 行き先を指定しないIntentの出来上がり.

2. Activity側


こちらもほぼ同様.


public class ResidureBatteryCheckerActivity extends Activity {

    private static TextView textView;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_residure_battery_checker);
        textView = ((TextView) findViewById(R.id.hoge_battery_check));
    }

    @Override
    public void onResume() {
        super.onResume();
        // バッテリー情報更新のサービスを開始する
        Intent batteryIntent = new Intent(this, BatteryService.class);
        if (startService(batteryIntent) == null) {
            Log.e("hogeMakeFirstSetting", "cannot Start Service");
        } else {
            Log.i("hogeMakeFirstSetting", "Service is Start!");

            // ServiceからのBroadcastを受け取るReceiverを立てる
            IntentFilter filter = new IntentFilter();
            filter.addAction(BatteryService.ORIGN_ACTION);
            registerReceiver(orignReceiver, filter);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(orignReceiver);
        stopService(new Intent(this, BatteryService.class));
    }

    public static void changeText(final String message) {
        if (textView != null) {
            textView.setText(message);
        }
    }

    // オリジナルのIntentを受け取るReceiver
    private final BroadcastReceiver orignReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (intent.getAction().equals(BatteryService.ORIGN_ACTION)) {
                int level = intent.getIntExtra("level", 0);
                String message = "level is " + level;
                changeText(message);
            }
        }
    };
}

なんてことは無く, ただReceiverを立て, ただオリジナルIntentを拾い, 情報を取り出して好きに使うだけ.
なおReceiverはonDestroyなどできちんとunregisterReceiverしましょう. でないとちゃんと休ませろって警告が来ます. 主にLogに.Serviceはお好みで. ただ止める手段がないと走り続けてバッテリーがマッハ.ヽ(;´Д`)ノ








…Messengerを使ったものはこの倍はコードがあったわけで, 結果としては良かった…のかな.
Handlerとか良くわかんなかったしorz

2012年10月14日日曜日

Androidで設定を参照, 操作するあれこれ -Wi-fiの小ネタ編-

DeveloperのSettings.Systemのあたりを漁っていたら見つけたので


Wi-fiのスリープ設定

正直こんなことも無ければ知らなかったであろう機能.
簡単に言ってしまえば「本体がスリープしたときWi-fiもスリープする?」という設定ができる機能が本体の設定の中にあったわけで…


一生懸命画面のOffのIntentとってなんとかしようとか考えてたのは一体…orz


ちなみに設定までの行き方は
「Wi-fi設定」でメニューを開き「詳細設定」へ…

メニューて…('A`)

とまぁなかなかエキセントリック遠い所に設定があるのでボタン一発で書き換えてやろう, と考えた次第.


とりあえずコード.まずは設定の取得から.


android.provider.Settings.System.getInt(contentresolver,android.provider.Settings.System.WIFI_SLEEP_POLICY,-1);

長い…
画面の設定編でもやった通り,

import android.provider.Settings.System;
しておくと楽かと
parmissionも WRITE_SETTINGS だけでOK(なはず).
内容もいたって簡単.WIFI_SLEEP_POLICYの今の設定をintで返すだけ.
設定は3種類.


0 = WIFI_SLEEP_POLICY_DEFAULT : 画面のスリープと一緒にスリープする
2 = WIFI_SLEEP_POLICY_NEVER : スリープしない
1 = WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED : 電源につながっていればスリープしない

の3つ.

設定の書き換えも
android.provider.Settings.System.putInt(contentresolver,android.provider.Settings.System.WIFI_SLEEP_POLICY,values)

のvaluesに0から2の好きな値を入れてやればOK.
boolean型が返ってくるので, ifで囲って書き込み成功/失敗をとってやればより安全にできるかと.



…parmissionあってるかな…(・ω・`)

2012年10月10日水曜日

Androidで設定を参照, 操作するあれこれ -画面の設定編-

今回はいったいいつ使うのかわからないネタ


android端末の画面の設定を操作


うん…普通に設定開けば良いじゃんとか言わない.アーアー<'(;´Д`)>キコエナイー
見つけて使ってみたから書く…うん


0. 下準備

まず始めに準備するのが.ManifestのUse-Parmission.
ここに

android.permission.WRITE_SETTINGS

これを許可してやる.
許可しないと基本設定を書き込めません.
一部読むだけなら要らないのもあるけれど…

そして


import android.provider.Settings.System;

をimportしておくことをお勧めする.
でないとSystemと一口に言っても, System.out.printlnでおなじみのjava.langや, android.osなどにもSystemがある.
そのため, 以降別のSystemを眺めながら「そんなメソッド見つからない!」とかIDEさんに理不尽に怒られる可能性があります.('A`)コレハヒドイ

1. 画面の点灯時間の設定

いわゆるオートスリープまでの時間の設定.
まずは, 今の設定を呼び出すメソッド.

System.getInt(getContentResolver(),System.SCREEN_OFF_TIMEOUT)

これだけ.
もしくは,
System.getInt(getContentResolver(),System.SCREEN_OFF_TIMEOUT, -1)

これだけ.
最初の引数はContentRe
最後の引数の-1は今回は特に関係ないようです.getIntによくあるデフォルト値?
ちなみに-1は「消灯しない」の設定みたい
第一引数のContentResolverはともかく
第二引数のSystem.SCREEN_OFF_TIMEOUT, これでどの情報にアクセスするかを設定しているみたい.

これで現在の設定が取得可能. 取得はミリ秒単位.

取得したら今度は設定.


System.putInt(getContentResolver(), System.SCREEN_OFF_TIMEOUT, 設定したい時間(ミリ秒));

これだけ.
設定したい時間に好きな値を放り込めばOK.
本体の設定アプリにない値も設定できます.



だれか一年とか設定してみた人いないのかな|・ω・`)チラッ


2. 画面の回転の設定

Notification Barを引っ張れば良いとか言わない.
Widget出せば良いとか言わない.

System.getInt(getContentResolver(),System.ACCELEROMETER_ROTATION)

まずは設定の取得. 既視感?少し上を見れば解決するかと.
基本Settings.Systemはこのメソッドで何とかなりそう.
返ってくる値は0(ロック状態), 1(ロック解除状態)の2種類.
表示するなら一工夫必要.

そして設定.

System.putInt(getContentResolver(),System.ACCELEROMETER_ROTATION, 0 or 1);

大方の予想通りでございます. はい.
0 or 1 でロック or アンロック を指定できます.

非常にシンプルなのでボタン一個で設定できるのもうなずけます.

とりあえずはこのあたり.











コード少ないなぁ…(・ω・`)

2012年10月9日火曜日

Androidで設定を参照, 操作するあれこれ -バッテリー編-

久々のAndroidキター
ただいまjava!私は帰ってきた!+(・ω・0)*




まあメモるのは初めてなんですがね(;´Д`)


内容は

androidの設定を操作するアプリの作成

ということでそのパーツ毎にちらほらとメモしていく予定


まずはバッテリー編からφ(・ω・`)

android端末のバッテリー情報を取得


端末のバッテリー情報を取るならIntent.ACTION_BATTERY_CHANGEDのお世話になるのが楽.
…他にも方法あるのかな

このIntentは, システムが「バッテリーの残量や状態が変更された時」, その情報を載せてIntentを発行していてくれている(らしい)

なのでこれを受信する受信機を用意してやればいい, とのこと

そこで登場するのがBroadcastReceiverクラス
ブロードキャスト化されたIntentを拾えるこのクラスを継承して, BatteryReceiverなるクラスを作ります

1. Receiverの作成


public static final class BatteryReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(final Context context, final Intent intent) {
                        // actionの取得
   String action = intent.getAction();
                        // actionの確認. Intent.ACTION_BATTERY_CHANGED以外のintentは排除する
   if (!action.equals(Intent.ACTION_BATTERY_CHANGED)) {
    Log.d("BatteryReceiver ", "action is " + action);
    return;
   }

   // 状態, 「充電中」等の状態がintで取れる
   int status = intent.getIntExtra("status", 0);
   // 電池残量, デフォルトは0.
   int level = intent.getIntExtra("level", 0);

   Log.d("level", level + "%");
  }
 }

とりあえずシンプルにバッテリーの状態と残量(%)だけを取得するクラス.
このレシーバーを立てておく. 立て方は後々
Intent.ACTION_BATTERY_CHANGEDを受け取るとonReceiveが呼ばれて処理スタート.
まずはコメントにあるとおり, 余計なIntentはreturnで排除.
・・・余計なIntentって入ってくるのかな.
その後はもうお好きに.
Intentからお好みの情報を引き出して操作するだけ.
Intentに含まれる値に関しては参考を参照.

参考:http://www.adakoda.com/android/000140.html

また, このonReceiveはオーバーライドメソッドなので, ココ以外に値を持ち出すときは一工夫必要.
上記をまるっと内部クラスにしてやるのが一番扱いやすい・・・?

ほかにもServiceクラスに乗せるなどの使い方も.
ここで得られる値もWidget向きだったりするのでServiceで使うのもアリ・・・?

疑問系ばかりであるorz

2. Filterの登録


BatteryReceiver receiver = new BatteryReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, filter);

Receiverが出来たら, 今度はIntentFilterをかけてやる. こちらはActivityならonCreateやonResumeなどで宣言してやるといい.
1,2行目で作ったReceiverとIntentFilterをインスタンス化.
3行目の addAction メソッドで件の Intent.ACTION_BATTERY_CHANGED をfilterが受け取ることを宣言.
4行目でそのfilterとreceiverを関連付けて宣言は終了.
あとはこのメソッドを通るように起動させればReceiver起動.


IntentがくるたびにReceiverが動いてくれる.

3. Receiverの破棄

unregisterReceiver(receiver);
これだけ.
これをonDestoryなど, もう要らないと判断される時に呼べばいい.
ただonPauseがいいのかonDestoryがいいのかは微妙….
もっと他にいいとこあるかも…?

これで必要なパーツはそろい踏み.

Widgetなんかにしてバッテリー残量によってアクションが変わるアプリなんかが作りやすいかも.








…アプリ自体がバッテリー食うのは内緒( ´д)ヒソ(´д`)ヒソ(д` )

2012年9月25日火曜日

TaskScheduler注意メモ


batファイルをTaskSchedulerで起動する場合,
開始[]ボックスに
batファイルのあるディレクトリを指定してやらないとうまく走ってくれない


画像を使ってみたかっただけかもしれない(・ω・`)

ClosureLinterによる静的解析

前回の続き.

コーディング規約どうしよう, というお話.
CheckStyleをjavascript用に作り直したりと, 手が無いこともないわけだが何より

時間がない

OTL

なので, 割と軽めに導入できるものを所望.
するとそこに現れたのが表題の, Closure Linter.
どうやらこいつは, Google先生が決めた規約にのっとったチェックをしてくれるツールらしい.
from GoogleDevelopers

条件反射で飛びついた自分の前に現れたのは, コマンドラインから起動されるClosureLinter.

ま た . b a t か よ ( ゚д゚ )



と反射的に考えてしまった自分はだいぶ.batに染まっているようですorz

何はともあれ使い方まとめ.


Ⅰ. Closure linter使い方 -準備編

1. Pythonで動きます. Python2.7.3.exeでPythonをインストールします.(Ver.2.7の理由は2. で)以降はデフォのディレクトリにインストールしたとします.
Python:http://python.org/download/ 自分のマシンに合ったものをどうぞ.
2. easy_installするためにsetuptools-0.6c11.win32-py2.7.exeを使用します.このsetuptools(ryが2.7を最後に更新されていないため, それ以降のPythonでは使えません.(1. の理由)
setuptools:http://pypi.python.org/pypi/setuptools Downloadsから
3. easy_installします. C:\Python27\Scriptsでcmdを起動します.パスを通しておくと楽かも.てゆうかbat使いたいなら通しておこう
4. easy_install http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz と入力します. インストールが始まり, つらつらとメッセージが出てきます.
5. 準備完了

Ⅱ. Closure linter使い方 -実行編

1. パスは通しておきましょう. 環境変数のpathの末尾に;C:\Python27\Scriptsを追加します.(cmdでpathと打ってみてちゃんと出てくることを確認しましょう.)
2. 早速解析しましょう. cmdを開き, gjslint 解析したい.jsのパス と入力します.
3. 成功していれば結果がコンソールに出ます.
4. パスのファイル名の部分を *.jsと置くと, そのディレクトリの.jsを順に全て解析してくれます.日本語にはならないみたいです(・ω・`)
5. 特別な.jsは他においておきましょう.一生懸命解析してダメだししてくれます. 正直鬱陶しいです. よけてくれる設定もあるらしいけど…

Ⅲ. Closure linter使い方 -.bat利用編


A. とりあえず修正するところを出力してくれるbat.
gjslint 解析したい.jsのパス > 結果を出力したい.txtなどへのパス
"解析したい.jsのパス"ディレクトリにある.jsを全てチェックし, その様子を"結果を出力したい.txtなどへのパス"に書き出してくれる. あくまで結果を教えてくれるだけ.直すのは自分で.(・д・`)
このままだと上書きするので, 過去ログ残したい!とか思うなら > を >> に置き換える. ファイル容量には注意. あくまで自己責任で.
ちなみに > はcmdのコマンド. Closure Linter とは関係ないので > 以下は無くてもOK. ただし結果がcmd上にしか出ないので出力してもらったほうが何かと便利.


B. コマンドで直せるものは直してもらうbat
copy  解析したい.jsのパス  C:\js_copy\ 
gjslint  解析したい.jsのパス  > 結果を出力したい.txtなどへのパス 
fixjsstyle 解析したい.jsのパス

1行目 とりあえず退避. "解析したい.jsのパス"にある全ての.jsをC:\js_copyにコピーする.
2行目 これは同じ. 解析結果の書き出し.
3行目 fixjsstyleのコマンドで, 直せるものは全部直してくれる. ただ改行とか空白とかは直してくれない. ; の打ち忘れなんかはやってくれる. あまり当てにしてはいけない.

なんかⅡとⅢを分ける必要なかった気がしたけど







まぁいっか+(・ω・0)*


Ⅳ. Closure linter使い方 -おまけ

→Closure linterがツッコミを入れる内容について書いてある. なにが突っ込まれるかチェックしたり, 突っ込まれた内容の確認にどうぞ

sinonを使ったjavascriptのテスト

前回でjavascriptの開発環境もできたので, いざコーディング!


・・・まではよかったのだが・・・
ここで課題が2つ.

1. テスト(特に通信系)どう書くの?
2. コーディング規約は?

とりあえず普通のテストはいいとして…通信…Mock?
とか調べてたら出てきたのが Sinon.js
ライブラリのように使え, いろいろと内蔵しているじゃじゃ馬
いろいろありすぎて手に負えませんorz

とりあえずjQuery.ajaxが使いたかったので, 有効そうな2つをピックアップ.

A. FakeServer
名前の通り偽者のサーバを立てる. 

var sinonTestCase = sinon.testCase({
    setUp : function() {
        this.server = sinon.fakeServer.create();
    },
    tearDown : function() {
        this.server.restore();
    },
    "test server":function () {
        this.server.respondWith("GET", "/some/article/comments.json",
                                [200, { "Content-Type": "application/json" },
                                 '[{ "id": 12, "comment": "Hey there" }]']);
        var callback = sinon.spy();
        jQuery.getJSON("/some/article/comments.json", callback);
        this.server.respond();
        sinon.assert.calledWith(callback, [{ id: 12, comment: "Hey there" }]);
    },
});

TestCase("Fakeserver test case", sinonTestCase); 

これで "Fakeserver test case" という名前のテストクラスが出来上がる.
setUp でfakeServerを立ち上げ
tearDown でその偽サーバを破棄している.
偽者とはいえ通信系, 破棄しておかないと特に通しのテストの時に…
"test server" がテストクラス名. 名前は test から始めないとテストとして認識されないので注意.
sinon.fakeServer.responsedWith で偽サーバのresponseの内容を決める.
sinon.spyは仮のcallback関数. これをテストしたい関数に組み込むことで, 後々sinon.assertが使えたりする. 詳しくはAPIで
server.respond() を呼ぶことでfakeServerが応答し, 先に設定したresponseを返す.

これにより, callbackにfakeServerからの応答が入る.

あとはsinon.assertを用いてきちんと応答が受け取れたことを確認する.


…すっごい不安だ('A`)

B. Stub
あるクラスの ある関数を 一時的に置き換える
stubのよるテスト例
var sinonTestCase = sinon.testCase({

    "test with stub" : function() {
        var json = [{"hoge":"hoge","foo":"foo","bar":"bar"},
        {"hoge2":"hoge2","foo2":"foo2","bar2":"bar2"},
        {"hoge3":"hoge3","foo3":"foo3","bar3":"bar3"}];

        var stub = sinon.stub(jQuery, "ajax");
      stub.yieldsTo("success", json);
  
        jQuery.ajax({
            success: function (data) {
                assertEquals(json, data);
            }
        });
       stub.restore();
    }
});

TestCase("Stub test case", sinonTestCase);

こちらは"Stub test case"クラス.
8行目にてstubを作成, 9行目にてjQuery.ajaxというメソッドの返り値を指定している.
11行目から実際にテストしたいメソッドを呼び, 値をチェックする.

こっちのほうが使いやすい気はした(・`ω・´) (キリッ
restore()は忘れずに.(setUp&tearDownに入れたほうがいい気がした(^ω^;).

参考:SinonAPI

明らかにAPIのが正しいのでそちらを参考に…


コーディング規約についてはまた後日…(・ω・)ノシ

2012年9月20日木曜日

aptana ~導入編~

ついにコーディング!javascript!щ(゚Д゚щ)


…java…script?('A`)


orz


まぁ嘆いていても仕方ないので. javascript開発のIDEにEclipseの弟?のAptanaを導入することに.
一緒にjavascriptのテストを行なう"JS Test Driver"を導入. 若干めんどくさいのでメモメモφ(・ω・ )




1. aptanaをインストール
2. eclipse同様help→Install New Softwareを選択
3. http://js-test-driver.googlecode.com/svn/update/から JS Test Driverインストール. JS Test Driver Plugin for Eclipse ひとつを選択. 複数選択するとNG(同じ名前をインストールしようとしてぶつかる?)

3. インストールが終わったら, 同様にWindow→Preferencesで設定を開く
4. JS Test Driverの項でブラウザ名にあわせて使うブラウザの.exeのパスを設定する.
5. Port to start server on のボックスに使用していないポートが設定してあることを確認する.

6. js(or src)ディレクトリにソースコードの.jsを置く
7. testディレクトリを作成, テストコードの.jsを置く
8. test(or conf)ディレクトリにテストの設定を書いた.confを置く

9. Run→Run Configurationsから実行の構成を開く
10. JS Test Driver Testの項をダブルクリックして新しい構成を作成
11. Projectに用いるプロジェクト名, Conf Fileに8. で置いた.confのパスを設定する
12. Run on Every Save にチェックを入れておくと保存するたびにテストが走ってくれるようになる
13. Commonは特にいじらなくていい

14. Window→ShowViewからJS Test DriverのViewを出しておく(無ければotherから選択)
15. View右上のStart Serverをクリックし, サーバを開始する.
16. Viewのグレーのアイコンの中から使いたいブラウザのアイコンをクリックし, 色がつくのを眺める. 色がつかない場合, 4. か15. をしていない/出来ていない恐れあり
17. 15. →16. の間でhttp://127.0.0.1:(ポート番号. デフォは42442)/captureが赤→黄→緑に変化するのを眺める

18. eclipse同様Run→JS Test Driver Test を選択する
19. +(・ω・0)*


6. 7. 8. については自由に構成できる…が, ソースコードに関してはjsディレクトリに置いておいたほうが, 他のツールを使う際に楽…かもしれない.

12. は便利そうで意外と鬱陶しいので注意. 自分は入れて数回で外した(・д・`)

また, 8. にある.confはテストを行なうポートやテスト対象の宣言, 使うプラグインの宣言を行なうファイル. これを読み込んでテストを実行する重要なファイル.


ex>
server: http://localhost:42442

load:
  - js/vendor/jquery-1.7.2.js
  - js/*.js

test:
  - js/vendor/sinon-1.4.2.js
  - js/vendor/sinolog.js
  - test/*.js



a. server: http://localhost:42442
テスト時に使うポートの指定. 上でちょくちょく出てくるテストの設定と同じにすること

b. load: - ソースのパス
ワンセットっぽい. ファイル名を指定してやるとそれだけを見に行ってくれる.
ディレクトリ分けを行い, *(ワイルドカード)を使うとはかどる

c. test: - テストのパス
テスト対象らしい. ここに名前を連ねておくとテストしてくれる
ディレクトリ分けを(ry



タグ(load:など)の前にはスペースを入れると読み込みがうまくいきません('A`)



これで準備は完了. あとはTestCaseを書けばおk.

TestCaseの書き方参考: http://news.mynavi.jp/column/tool/013/index.html



…これでスタート地点に立ったわけだ…( ´_ゝ`) =3

2012年9月19日水曜日

時刻とともに入力メッセージのログをとるbat

syntaxhighlighterとの戦いも終えたので投稿再開.
でもjavaじゃない(・ω・`)


とあるミッションで
「行動のログを時間つきでとっとけ」
ということがあったので, 早速そんなbatをつくってみた.


@ECHO OFF
For /F "eol=;tokens=1,2,3,4*delims=/, " %%i in ('date /t') DO SET YYYYMMDD=%%i%%j%%k
For /F "eol=;tokens=1,2,3*delims=:, " %%i in ('time /t') DO SET HHMM=%%i%%j
set YYYYMMDDHHMM=%YYYYMMDD%%HHMM%

echo 終了するときは"fin"と入力してください
setlocal enabledelayedexpansion
For /L %%o in (0,0,5) do (
 set /p INP="メッセージを入力してください>"
 if !INP!==fin (
  echo !INP!により終了!
  exit
 )
 set message=!date! !time! !INP!
 echo !message! >>record/%YYYYMMDDHHMM%.txt
)


正直2,3行目は参考サイト参照. ほぼコピペ('A`)
やってることは, ファイル名に日付 + 時刻を用いるための処理. これでうまく出てくれた.
6行目からが本体.
7行目はお決まりの宣言(らしい). これを宣言すると, 変数の値の上書きが出来るようになる(詳しい話があった気がする).
8行目からループ開始. /Lは前にも書いた単純ループ. 変数"o"が0から5の間0刻みで進む(=進まない)
9行目でメッセージを入力待ち.

10行目の"!INP!"が肝. 通常"%INP%"で読み込むところを"!"でくくることで, "INP"の内容をループの間上書きして読み込んでくれる. ここで"fin"と書き込まれたらif内へ. "exit"で終了する.

12,13行目はメッセージの設定. 書き込まれた内容に日付と時刻を足してファイルに出力している.


これを繰り返した出力結果の例


2012/09/19 19:14:15.33 test
2012/09/19 19:14:18.13 (・ω・`)
2012/09/19 19:14:34.85 20120919


入力がコマンドプロンプトでちょっと使いにくいのが難点(´-`). でもミッションでは有効だったから満足.



参考サイト:http://d.hatena.ne.jp/orangeclover/20101203/1291387934

javaなんて無かった.
((( ⊂⌒~⊃。Д。)⊃

2012年9月6日木曜日

batでファイルの削除と, テスト用ダミーファイルの作成

bakファイルをばんばん作るようになったので, 今度は作りすぎたファイルを削除する.batと, その動作をテストする用のダミーファイルを作る.batを, FOR文を用いて作成する.

まずは削除.bat本体


for /f  "skip="任意の整数"" %%"変数名" in ('dir/b /O-D "対象ファイル名"') do del %%"変数名"


削除の命令の本体は

del %%"変数名"

指定した名称のファイルを削除するコマンド
この %%"変数名" をFOR文の中で指定して, 繰り返し処理を行い削除を進める.

/f→ ファイル解析オプション. ファイルを扱うときに.

"skip="任意の整数""→ "任意の整数"で指定した数だけ処理をスキップする. すなわちforでまわすリストの先頭から"任意の整数"の数のファイルは削除しない, となる.

 %%"変数名"→ 実行するコマンド内で用いる変数. 

in ('dir/b /O-D "対象ファイル名"')→変数に入れる値. 今回はファイル名. オプションいろいろ.

  dir/b 対象ディレクトリ. 今回はこの.batのあるディレクトリ.

  /O-D ファイルの並び. 「D」が日付を示し, 「-」が降順を示す. すなわち, 新しい順に並ぶ. skipと合わせて, 新しい"任意の整数"件のファイルを残して削除する, となる.

  "対象ファイル名"→そのまま, 削除対象となるファイル. 「?」をワイルドカードとして使うことで特定のルールで作られたファイル名をまとめて対象に含むことが出来る.
(ex> 対象ファイル名 = log????.log とすれば, log0904.log,log0905.log,log0906.logと順に作成したファイルをまとめて対象に取れる.)


削除.batを作ったら, それをテストしたいところ. しかし一々メモ帳を開いてファイルを作ったり, コピーからのリネームで量産するのも芸がない.
そこで折角のfor文を用いてのダミーファイル量産計画.


for /L %%"変数名" in ("初期値","増加値","限界値") do TYPE NUL> "ファイル名"

ただループをまわすだけならこれでOK.
/L→Iではない. ただループをまわすオプション?
in ("初期値","増加値","限界値")→"変数名"に入る値. 当然数値. java等でよく見るfor文に近い内容. "初期値"から始まり, "限界値"まで, "増加値"ずつ増加していく. なお"限界値"以下である間回るので, "限界値"は含まれる.

TYPE NUL> "ファイル名"→ファイルの作成. 中身はこのままだと当然なし. ファイル名に%%"変数名"を用いることで, ファイル名を動的に変更できる.

これで量産可能. ループ中に桁がずれたときなどには注意.
(ex> …, log098.log, log099.log,log0910.logといった感じにファイル名がずれてしまう. 桁数ごとにループを作るのが無難)





…最近javaしてないなぁ…(・ω・`)

MS SQLのバックアップコマンドとbatからの呼び出し

batを叩いてでMS SQLの復旧用バックアップを取れ!

といった感じのミッション.



まずはバックアップを取り, bakファイルを作るSQL文から


BACKUP DATABASE "バックアップを取りたいDB名" TO disk='"保存先のパス"' WITH INIT



TO disk → 保存先のフルパス. ".bak"まで書く. ファイルは無くても自動で作ってくれるが, ファイルを置くディレクトリまでは作ってくれないので注意

INIT→既に指定したファイルが有った場合, 上書きする, という設定. WITH句以下に書く. ちなみに追記する場合は NOINIT.

このSQLを投げれば, 投げた時点でのフルバックアップをとる. 差分バックアップを取りたい場合は, WITH句に","で続けて, "DIFFERENTIAL"を追加する.

※フルバックアップ→DB全体のバックアップを取ること, 差分バックアップ→最後にとったフルバックアップからの更新されたデータをバックアップする. 全てフルバックアップするよりも容量を圧迫しない.
復旧時も, 復旧したい時点の差分ファイルと, その直前のフルバックアップのひとつずつ指定すれば復旧できる.

復旧用.sqlはフルバックアップファイルだけで復旧するならば


restore database "復旧するDB名" from disk='".bakファイルのパス"'



だけでOK
ただし差分バックアップファイルを用いる場合は



restore database "復旧するDB名"  from disk='"フル.bakファイルのパス" '
WITH NORECOVERY
restore database "復旧するDB名" from disk='"差分.bakファイルのパス"'



と, フル→差分の順に呼ぶことと, フルバックアップファイルを呼んだ際, WITH句で"NORECOVERY"を指定し, トランザクションのロールバックを防ぐことで, 続けて差分.bakを呼んで復旧することが出来る.





そして, これらの処理を, 叩くだけでこなしてくれるようなbatのコマンド

バックアップを取る.bat


sqlcmd  -U "ユーザID" -P "パスワード"  -v buckupdate ="%date:/=%" -i .bakまでのパス


このとき, -U -Pは大文字でないと反応してくれない点に注意.
-v で.batを叩いた時点の日付をとって, SQLファイルに投げてくれる(ex> 20120906)
こうすることで, ファイル名に日付をつけることが出来るため, 復旧時に使いやすくなる.
なおSQL文内で使うときは $(buckupdate) で投げた値を使える.
(おまけ: "%date%"と表記するとexは2012/09/06となる. また時間を使いたいときは"%time%")
(おまけ2: "%date:/=%"の「:/=」の部分で, 表記される「/」を「」へと変換している.)


そして復旧する.bat



SET /P input="復元に使うファイルの日付を入力してください"
sqlcmd -U "ユーザID" -P "パスワード" -v buckupdate =%input% -i 復旧用.sqlのパス


復旧を行なう際は, 復旧用ファイルを指定する指定しなければいけない.
そこでSET /Pコマンドでユーザーからの入力をうけつけ, それを -v に与えて.sql内で用いる.
入力のさせ方などは工夫の見せ所.
ファイル名などを工夫してやると良いかも.




長かった…('A`) -3

2012年9月3日月曜日

Loggerの設定とか

Loggerの設定ファイルを書くことがあったのでその辺りをちらほらと.

1. 設定フィルを準備
 
      設定ファイルの中身はこんな感じ
handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler.level=FINEST

java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

#出力の設定
#ログとして出力するログのレベル. このレベル以上のログだけ出力される.
java.util.logging.FileHandler.level=WARNING
#出力ファイル名. カレントディレクトリから見て場所を指定する.%uと%gは世代番号
#もちろん名前は自由
#この時, ディレクトリがないとエラーになるので, あらかじめ作っておくか,
#なかった場合ディレクトリを作成する処理を行うといい.
java.util.logging.FileHandler.pattern=Log/OutPut%u.%g.log
#フォーマッターの設定, 自作のフォーマッターの宣言も可能
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
#追記設定, trueなら追記, falseなら上書き
java.util.logging.FileHandler.append=true
#最大世代番号, この数だけログファイルを作る
java.util.logging.FileHandler.count=10
#一つのファイルに書き込める最大バイト数の設定
java.util.logging.FileHandler.limit=2000
3つ目のブロックで細かい設定を行う. 上の2ブロックは・・・HandlerとFormatter?


これをパスの通ったところ(src以下など)に置いておく
あとはLoggerを使う際にこの設定を呼んでやればいい

2. 設定を呼び出すクラスの作成

自分は参考にしたサイトのとおり, クラスを作ってみた

/**
 * ログ設定プロパティファイルのファイル名.
 */
protected static final String LOGGING_PROPERTIES = "logger.properties";
//Loggerのプロパティファイルの名前
//パスが通ったところに起きましょう


/**
 * static initializer によるログ設定の初期化.
 */
static {
 File directory = new File("Log");
 if (!directory.exists()) {
  Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)
    .warning("ログディレクトリがありません");
  if (directory.mkdir()) {
   Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info("Log folder was made");
  } else {
   Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("Log folder couldn't make");
  }
 }
  final Logger logger = Logger.getLogger("オリジナルの名前");
 // クラスパスの中から ログ設定プロパティファイルを取得
 InputStream inStream = "".class
   .getClassLoader().getResourceAsStream(
     LOGGING_PROPERTIES);
 if (inStream != null) {
  try {
   LogManager.getLogManager().readConfiguration(inStream);
  } catch (IOException e) {
   logger.warning("ログ設定のエラー");
  } finally {
   if (inStream != null) {
    try {
     inStream.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 } else {
  logger.info("設定ファイルがありません");
 }
}
//プロパティファイルのローダ
//staticイニシャライザで設定することで, 最初の一度だけ設定を行なう

public static Logger getLogger(){
        return Logger.getLogger("オリジナルの名前");
}
これらを設定した後,
Logger.getLogger("オリジナルの名前").info/warning/severeで呼ぶと設定は反映されている
オリジナルの名前には基本このクラス名を入れるとか


使う際はこのクラスのgetLoggerを呼ぶようにすると, 最初に呼ばれた際にのみstaticイニシャライザで設定ファイルを読み込む.

2012年8月24日金曜日

HashMap宣言の小ネタ

HashMapの初期値の宣言時,

HashMap<String, Integer[]> sampleHashMap = new HashMap<String, Integer[]>(){
     put("要素A", 値A);
     put("要素B", 値B);
     put("", null);
     }
};

と, 内部クラス(でいいのかな…)で宣言すると, すっきり収まる, 気がする.

特にフィールドとして持ちたいときに, この中で宣言が完結できるのでメソッドがすっきりするかと.

2012年8月21日火曜日

このブログは

このブログは, タイトル通り自分がお仕事や趣味などで覚えた, 知ったJAVA, Android周りのことをメモしていくブログ(予定)です.
基本動くことを確認したものを書いていくつもりではありますが, 間違いや無駄などが多分に含まれます.
ご利用の際はご注意ください.

AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...