Hatena::ブログ(Diary)

Paamayim Nekudotayim

2012-04-11

sbt android plugin でテストできなかった件

| 17:35

はじめに

sbt android plugin とは、ScalaAndroid アプリを書くための素敵な方法だと聞き、特に考えもなく、どちらも経験が浅いのに、手を出しました。

最初のアプリは大した問題もなく、スムーズにリリースできました。しかし、機能追加に伴い、テストを書きたい、となったときに、この android plugin がサポートしている tests サブプロジェクトがうまく動きませんでした。

再現

https://github.com/jberkel/android-plugin/wiki/getting-started を参考に、プロジェクトを作成します。再現のためにすべてデフォルトを選択しました。

$ brew install giter8
$ g8 jberkel/android-app

Template for Android apps in Scala 

package [my.android.project]: 
name [My Android Project]: 
main_activity [MainActivity]: 
scala_version [2.9.1]: 
api_level [10]: 
useProguard [true]: 

Applied jberkel/android-app.g8 in my-android-project

プロジェクトディレクトリに移動して、sbt を起動し、パッケージを作ります。sbt は HomeBrew などでインストールしておいてください。

$ cd my-android-project
$ export ANDROID_HOME=/Applications/android-sdk-macosx
$ sbt

>android:package-debug

エミュレータを起動します。

> android:emulator-start my_avd
> android:start-emulator

問題なくサンプルプロジェクトが起動します。

テストプロジェクトの存在を知る

giter8 で作られたサンプルプロジェクトには、「tests」というサブプロジェクトが含まれています。https://github.com/jberkel/android-plugin/wiki/Building-Android-Test-Projects を参考に実行してみましょう。

> android:package-debug
> android:install-emulator
> tests/android:package-debug
> tests/android:install-emulator
> tests/android:test-emulator

このようになります。

[info] 
[info] my.android.project.tests.ActivityTests:INSTRUMENTATION_RESULT: shortMsg=java.lang.IllegalAccessError
[info] INSTRUMENTATION_RESULT: longMsg=java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
[info] INSTRUMENTATION_CODE: 0
[success] Total time: 3 s, completed 2012/04/11 16:59:14

何が success だ、と言いたくなります。

ddms でログなどを見た結果、JavaScala もにわかな私の認識では、TypedResource などのクラスの解決がうまくいっていない、といったところでした。

打開

5日ほど試行錯誤したのですが、何とかテストを実行させられた手順が以下になります。

まず android plugin に手をいれるので github から落としてくる。

$ cd ..
$ git clone git://github.com/jberkel/android-plugin.git
$ cd android-plugin

AndroidInstall.scala を編集(対象コミットは 6f6e4b9)

--- a/src/main/scala/AndroidInstall.scala
+++ b/src/main/scala/AndroidInstall.scala
@@ -69,8 +69,7 @@ object AndroidInstall {
      classesMinJarPath, libraryJarPath, manifestPackage, proguardOption) =>
       if (useProguard) {
           val optimizationOptions = if (proguardOptimizations.isEmpty) Seq("-dontoptimize") else proguardOptimizations
-          val manifestr = List("!META-INF/MANIFEST.MF", "R.class", "R$*.class",
-                               "TR.class", "TR$.class", "library.properties")
+          val manifestr = List("!META-INF/MANIFEST.MF", "library.properties")
           val sep = JFile.pathSeparator
           val inJars = ("\"" + classDirectory.absolutePath + "\"") +:
                        proguardInJars.map("\""+_+"\""+manifestr.mkString("(", ",!**/", ")"))

72行目あたり、manifestr から "R.class", "R$*.class", "TR.class", "TR$.class" を削除します。このへんは ProGuard という機構の設定をしているようです。

編集したら、publish-local します。

$ sbt publish-local

サンプルプロジェクトに戻り、project/plugins.sbt を編集します。

--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,3 +1,3 @@
 resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases"))(Resolver.ivyStylePatterns)
 
-addSbtPlugin("org.scala-sbt" % "sbt-android-plugin" % "0.6.1")
+addSbtPlugin("org.scala-sbt" % "sbt-android-plugin" % "0.6.2-SNAPSHOT")

sbt-android-plugin のバージョンを 0.6.2-SNAPSHOT に変えることで、さっき編集したバージョンを読みにいかせます(この説明は自信がない…)。

編集したら、もう一度テストを実行します。

> reload
> clean
> tests/clean
> android:package-debug
> android:install-emulator
> tests/android:package-debug
> tests/android:install-emulator
> tests/android:test-emulator

今度はうまくいくはず。

[info] 
[info] my.android.project.tests.ActivityTests:.
[info] my.android.project.tests.AndroidTests:..
[info] Test results for InstrumentationTestRunner=...
[info] Time: 1.509
[info] 
[info] OK (3 tests)
[info] 
[info] 
[success] Total time: 4 s, completed 2012/04/11 17:25:30

結論

正直、このやり方でいいのかわかりません。何しろ ScalaJava も sbt もにわかなので(だからこそ5日も悩みました)。私的には、AndroidInstall.scala を上記のように編集したことで、管理されたソースである TR.scala がうまく tests プロジェクトに対してエクスポートされたのでは、と考えています。

間違った知識を流布してもいけないので、おかしなところはご指摘いただけると幸いです。

2011-12-14

けいおん!劇場版ただの感想 ネタバレあり

| 00:06

早々に観に行ったのは、Twitter でのネタバレに怯えながら暮らすのが嫌なのと、エンディング曲が The Offspring の Mota を彷彿させるというツイートを見て、それを確認したかったのがある。

メタル寄りなリアル軽音部に所属していた自分としては、とりあえずあの最初のシーン(デスデビルごっこ)にがっつり掴まれた。マキシマムザホルモンの曲をMMDけいおんのキャラに演奏させたMADがあったけど、あれへの公式によるオマージュかと思ったほどだ。個人的にあれがクライマックスだったといってもいい。あそこが音も割れんばかりの大音量で流れることは映画館にとって必須項目である。

構成としてはロンドン旅行と梓へのプレゼントのお話で、それ以上でもそれ以下でもない。どこにでもありそうな軽音部女子の日常を描いた作品ということで自分の中では完結している。ただその描き方が秀逸というか、丁寧というか、監督を始め女性スタッフが多い気がしたのでそのためかな、と劇場版に限った話ではないのだろうが、思った。

舞台も女子高だし、男子が見てはいけない世界を覗いているような感覚もあり、もし全世代に平等に観てもらえる機会を失っているとすればその辺なのかなと思ったりもした。もちろんどんな男子も、多少なりとも女性的な部分を持ち合わせているはずで、それなりに共感できるシーンは多い。自分が女だったら思わず「かわい〜」とか「あるあるw」と言ってしまいそうなシーンばかりだったが、リアル女性にとってはどう映るのかはまったくわからない。

あとは、実際にライブやってみたことがある人にとっては、ちょっとしたシーンの音響のリアルさもニヤニヤしてしまったと思う。

何でも一般化してしまう癖があり、個々のシーンに関してはその場で楽しんだだけでよく覚えてないし後から特に言いたいこともない。ただ、実況向きだと思うので、一日も早くテレビなどで放送されることを望んでいる。

2011-11-04

Network.Shpider と Codec.Text.IConv を使って EUC-JP のサイトのソースを UTF-8 で出力

| 18:32

Haskell の練習。

ByteString は Haskell Platform に入ってたんだっけ…。

-- shpidertest.hs

import Network.Shpider
import Codec.Text.IConv
import Data.ByteString.Lazy.Char8 as B

main = runShpider $ do
  (_, page) <- download "http://www.sampou.org/haskell/a-a-monads/html/hardway.html"
  let u_source = convert "EUC-JP" "UTF-8" $ B.pack $ source page
  lift $ B.putStrLn u_source
$ cabal install shpider iconv
$ runhaskell shpidertest.hs

game botgame bot 2011/12/02 11:37 もう、mmorpgゲームをいちいち手でやるのはやめましょう。
自動狩りが出来るオートマウスで楽にゲームを楽しみませんか?
オートマウスにやらせた時間には他のことをやったりしましょう!
BANされにくいので安心して使えます。
詳しい機能は下記のホームページで確認出来ますのでご参考までに。。。
(www.automouse.jp)

2011-09-15

WordPress でアイキャッチ画像を選択したあと自動的にメディアウィンドウを閉じる

| 17:54

そのような要求があったので知らない jQuery を調べつつ書いたコード。

テーマの functions.php に下記のコードを書く。以下 foo はテーマ名。

<?php
function enqueue_override_script() {
        wp_enqueue_script('override', '/wp-content/themes/foo/js/override.js', array('set-post-thumbnail'), '1.0');
}

if (is_admin()) {
        add_action('admin_init', 'enqueue_override_script');
}

下記の内容で wp-content/themes/foo/js/override.js を作る

var WPSetAsThumbnail = (function() {
        var original_WPSetAsThumbnail = WPSetAsThumbnail;
        return function(id, nonce) {
                var $link = jQuery('a#wp-post-thumbnail-' + id);
                var win = window.dialogArguments || opener || parent || top;
                win.WPSetThumbnailHTML = function(html){
                        win.jQuery('.inside', '#postimagediv').html(html);
                        $link.queue(function(){
                                win.jQuery('#TB_closeWindowButton').click();
                                jQuery(this).dequeue();
                        });
                };
                original_WPSetAsThumbnail(id, nonce);
        }
})();

以上。

Uncheck comment status when specific category is checked

| 19:10

Put these codes into your theme's functions.php

<?php
function disable_comment_status_when_specific_category_checked() {
        $cat = get_category_by_slug('info'); // Change 'info' to any category you want to disable comments.
?>
        <script type="text/javascript">
        jQuery('#in-category-<?php echo $cat->term_id; ?>').click(function(){
                if (jQuery(this).is(':checked')) {
                        jQuery('#comment_status').attr('checked', false);
                }
        });
        </script>
<?php
}

add_action('admin_footer', 'disable_comment_status_when_specific_category_checked');

2011-09-10

出力を文字列として得る関数

| 18:56

PHP5.3以上で使える無名関数を利用する。

<?php
function capture($f) {
        ob_start();
        $f();
        $content = ob_get_contents();
        ob_end_clean();
        return $content;
}

こういうのを作っておくと

<?php
function tag($tag, $content) {
        return "<$tag>$content</$tag>\n";
}

$tr = tag('tr', capture(function(){ ?>
        <td>foo</td>
        <td>bar</td>
<?php }));

echo tag('table', $tr . tag('tr', capture(function(){ ?>
        <td>FOO</td>
        <td>BAR</td>
<?php })) . $tr);

みたいなことができる。RailsActionView::Helpers::CaptureHelper#capture みたいなもの。

PHP は <?php 〜 ?> の文法が本質だと思っているし、HTMLエディタシンタックスハイライトのあるエディタでも文字列で渡すよりは見栄えのよいソースが出来ると思うから、早く PHP5.3 が広まってこういうコードを気兼ねなく書けるようになればいいと思う。

この日記のはてなブックマーク数