忍者ブログ
[1] [2] [3] [4] [5] [6] [7]

DATE : 2024/04/25 (Thu)
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


DATE : 2012/02/23 (Thu)

Javaでは、メソッドやクラスなどをパッケージスコープとする際にアクセス修飾子を省略します。しかしソースコードの作者以外の人から見ると、アクセス修飾子を省略したのかそれとも書き忘れたのか、判断できません。そこでパッケージスコープであると明示的に示そうと、「/* package */」のようなコメントをアクセス修飾子がない代わりに入れることがあります。例えば、パッケージスコープなメソッドは次のように書きます。

    /* package */ void method() {
        ...
    }

Eclipseの一部やAndroidに標準搭載されているブラウザアプリケーションや設定アプリケーションなどがそのようなコーディングルールで記述されています。

Javaで書かれたソースコードがコーディング規約に従っているかどうかをチェックする際には、Checkstyleがよく使用されます。しかし、本記事の執筆時点の最新バージョンであるCheckstyle 5.5では、パッケージスコープを表すコメントの有無をチェックできません。

そこで今回、パッケージスコープを表すコメントの有無をチェックするCheckstyleプラグインを作ってみました。GitHubで公開しています。ライセンスはCheckstyleと同じLGPLです。Checkstyle 5.5以上に対応しています。

本プラグインでは、アクセス修飾子のないクラスなどの定義にパッケージスコープを表すコメントが書かれていることをチェックし、書かれていなければ警告します。加えて、アクセス修飾子が書かれているにもかかわらず以下のようにパッケージスコープを表すコメントがある場合に警告を行います。

    /* package */ public void method() {
        ...
    }

使い方は次の通りです。まず、Checkstyleの設定ファイルに本プラグインのモジュールを追加します。本プラグインのモジュールは、TreeWalkerモジュールのサブモジュールです。例えば、次のようになります。

  <module name="TreeWalker">
    <module name="CommentedPackageVisibilityCheck" />
  </module>

クラスパスに本プラグインのJARファイルを追加して、Checkstyleを実行してください。

JARファイルは、「commented-package-visibility-check-0.1.zip」をダウンロードして展開すると手に入ります。

CommentedPackageVisibilityCheckモジュールには、以下のプロパティを用意しています。必要に応じて設定してください。

プロパティ名 説明 省略時の値
format パッケージスコープを表すコメントにマッチする正規表現。 /\* package \*/
requireLatterWhiteSpace パッケージスコープを表すコメントの直後に、少なくとも1文字以上の空白が必要か。 true
PR

DATE : 2011/11/15 (Tue)

背景

Jenkinsを使ってAndroidプロジェクトで継続インテグレーションを行おうとしたのですが、JUnitのXML形式でテスト結果を出力する標準的な方法が見当たりませんでした。テキスト形式では出力できます。しかしXML形式でテスト結果が出力できれば、テストが何件成功して何件失敗したのかが一目でわかるほか、その件数がビルドを経るに従ってどのように推移したのかがグラフでわかりテスト結果が見やすくなります。

調査したなかでは、android.test.InstrumentationTestRunnerを拡張してXML形式を出力するようにすれば解決はできるようでした。実際、「Android JUnit Report Test Runner」というプロジェクトでそのようなtest runnerを含むJARライブラリが提供されています。しかしテストのために新しいライブラリを導入するのは気が引けました。元のソースコードには手を入れずにXML形式のテスト結果を出力する方法が欲しかったのです。

そこでAndroi SDKに含まれているddmlib.jarを使用して、テストを起動し、おのおののテストメソッドの結果を受け取り、XML形式にテスト結果を出力するJythonスクリプトを作成しました。スクリプトの形にすることで、ソースコードを変更しなくてもテスト結果をXML形式で出力することができるようになりました。

使い方

本スクリプトの実行にはAndroid SDKJython 2.5系が必要です。実行前には、CLASSPATH環境変数にddmlib.jarのパスを設定してください。ddmlib.jarのパスは<Android SDKのパス>/tools/lib/ddmlib.jarとなるはずです。

Androidデバイスもしくはエミュレータにテスト対象のアプリケーションとテストアプリケーションをインストール後、以下を実行してください。android.test.InstrumentationTestRunnerを実行し、結果をXMLで標準出力に出力します。なお以下の実行例はbash上のものです。

./run_tests_for_xml.py -a <adbのパス> <テストアプリケーションのパッケージ名>

「<adbのパス>」はAndroid SDKに含まれているadbのパスに置き換えてください。<Android SDKのパス>/platform-tools/adbとなるはずです。「<テストアプリケーションのパッケージ名>」は、テストプロジェクトのAndroidManifest.xmlにある、manifest要素のpackage属性の値に置き換えてください。

特定のtest runnerを実行したい場合には次のようにスクリプトを実行します。

./run_tests_for_xml.py -a <adbのパス> <テストアプリケーションのパッケージ名> <test runnerの名前>

「<test runnerの名前>」は、テストプロジェクトのAndroidManifest.xmlにある、instrumentation要素のandroid:name属性の値に置き換えてください。現在のスクリプトでは実行するtest runnerはひとつだけ指定できます。

特定のデバイスやエミュレータ上で実行したい場合には次のようにスクリプトを実行します。

./run_tests_for_xml.py -a <adbのパス> -s <デバイスもしくはエミュレータのシリアルナンバー> <テストアプリケーションのパッケージ名>

「<デバイスもしくはエミュレータのシリアルナンバー>」には「adb devices」で出力されるシリアルナンバーを指定します。Jenkins上でAndroid Emulator Pluginを使用している場合は次のようにしてエミュレータを指定します。

jython25 run_tests_for_xml.py -a <adbのパス> -s $ANDROID_AVD_DEVICE <テストアプリケーションのパッケージ名>

スクリプトのダウンロード

GitHub上に置いてあります。ライセンスはApache License 2.0です。

build.xmlへの統合

Android SDKが生成するbuild.xmlへ本スクリプトを使用するターゲットを追加するには、GitHub上にあるrun-tests.xmlの-test-xmlターゲットや-test-coverage-xmlターゲットを参照してください。


DATE : 2011/07/24 (Sun)

FindBugsは、バグらしきところをJavaバイトコードを解析して検査するツールです。AndroidアプリにもFindBugsをかけることができるため、FindBugsを実行するAntのtargetを書きました。

本targetを使用する手順は以下の通りです。

  1. FindBugsをインストールする。
  2. Antのライブラリディレクトリにfindbugs-ant.jarをコピーする。
  3. Androidプロジェクトのディレクトリの直下にあるbuild.xmlの<setup />の下に、以下をコピーアンドペーストする。
<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask" />

<target name="findbugs" depends="compile"
        description="Run FindBugs.">
    <findbugs home="${findbugs.home}"
            output="${findbugs.output}"
            outputFile="${findbugs.output.file}"
            excludeFilter="${findbugs.exclude.filter}">
        <sourcePath path="${source.absolute.dir}" />
        <sourcePath path="${gen.absolute.dir}" />
        <auxClasspath path="${android.jar}" />
        <class location="${out.classes.absolute.dir}" />
    </findbugs>
</target>

target中の以下のプロパティは適切なものを設定するか、置き換えください。findbugsタスクの詳細は、「Using the FindBugs™ Ant task」を参照してください。

findbugs.home
FindBugsがインストールされているディレクトリへのパス。
findbugs.output
レポートの形式。htmlを指定するとHTML形式で、xmlを指定するとXML形式で出力される。
findbugs.output.file
レポートを出力するパス。ファイル名も含む。
findbugs.exclude.filter
以下に示すXMLファイルへのパス。

自動生成されるR.javaの内部クラスの名前は小文字で始まるため、NM_CLASS_NAMING_CONVENTIONが指摘されます。そこで以下のXMLファイルでレポートの対象外とします。

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
    <Match>
        <Class name="~.*\.R\$.*" />
        <Bug code="Nm" />
    </Match>
</FindBugsFilter>

これで、「ant findbugs」と実行するとFindBugsをかけることができます。

レポートが文字化けする場合は、以下のいずれかの対策を取ります。

  1. findbugsタグの属性として「jvmargs="-Duser.language=en"」を追加し、レポートの言語を英語に変更する。
  2. FindBugsに含まれている日本語のメッセージファイルのエンコーディングをUTF-8に変換する。詳しくは「UTF-8環境での eclipse findbugs-plugin の文字化け解消」などを参照。

DATE : 2011/05/22 (Sun)

android.view.GestureDetectorを使用する場合、生成時に指定するGestureDetector.OnGestureListenerとしてGestureDetector.SimpleOnGestureListenerを使用すると余分なメソッドを実装せずに済むため便利です。しかしダブルタップとシングルタップとを区別しようとして、シングルタップを通知するメソッドの取り違えを起こしやすくもあります。

これは、前者がGestureDetector.OnGestureListenerに定義されているメソッドで、後者がGestureDetector.OnDoubleTapListenerで定義されており、GestureDetector.SimpleOnGestureListenerはその両者を実装しているためです。GestureDetector.OnGestureListenerは、ダブルタップを考慮しません。

そのため、ダブルタップとシングルタップとを区別したい場合は、GestureDetector.SimpleOnGestureListener#onSingleTapUp(MotionEvent)ではなくGestureDetector.SimpleOnGestureListener#onSingleTapConfirmed(MotionEvent)を使用すべきです。

なお、前者はMotionEvent.ACTION_UPの動作を通知し、後者はMotionEvent.ACTION_DOWNの動作を通知することにも注意が必要です。


DATE : 2011/05/08 (Sun)

Androidには、以下の2つの方法でスレッドの優先度を変更できます。

両者に違いはあるのでしょうか。気になったので調べてみました。結論としては、両者の動作に違いはありません。

android.os.Process.setThreadPriority()は、android.os.Processに定義されているANDROID_PRIORITY_*定数をnice値としてsetpriorityシステムコールを呼び出します。処理の流れは以下の通りです。

  1. android.os.Process.setThreadPriority()はネイティブメソッドで、frameworks/base/core/jni/android_util_Process.cppのandroid_os_Process_setThreadPriority関数が実行されます。
  2. android_os_Process_setThreadPriority関数がframeworks/base/libs/utils/Threads.cppのandroidSetThreadPriority関数を呼び出します。
  3. androidSetThreadPriority関数は、android.os.Processに定義されているANDROID_PRIORITY_*定数をnice値としてsetpriorityシステムコールを呼び出します。

java.lang.Thread.setPriority()は、java.lang.Threadに定義されているスレッド優先度をnice値に変換してsetpriorityシステムコールを呼び出します。処理の流れは以下の通りです。

  1. java.lang.Thread.setPriority()がjava.lang.VMThraed.setPriority()を呼び出します。
  2. java.lang.VMThraed.setPriority()はネイティブメソッドで、libcore/vm/native/java_lang_VMThread.cのDalvik_java_lang_VMThread_setPriority関数が実行されます。
  3. Dalvik_java_lang_VMThread_setPriority関数は、dalvik/vm/Thread.cのdvmChangeThreadPriority関数を呼び出します。
  4. dvmChangeThreadPriority関数は、java.lang.Threadで定義されているスレッド優先度をnice値に変換してsetpriorityシステムコールを呼び出します。

結果、両者の効果は同じです。ただし、android.os.Processではスレッドの優先度が用途ごとに定数として定義されているため、まずandroid.os.Process.setThreadPriority()の使用を検討すべきでしょう。

忍者ブログ [PR]
ブログ内検索
最近の状況
リンク
カレンダー
03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
使用許諾
最新コメント
(08/15)
(05/04)
(03/06)
(03/04)
(09/25)
最新トラックバック
ブログ内検索
最近の状況
リンク
カレンダー
03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
使用許諾
最新コメント
(08/15)
(05/04)
(03/06)
(03/04)
(09/25)
最新トラックバック