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

DATE : 2017/06/27 (Tue)
×

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


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ターゲットを参照してください。

PR

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()の使用を検討すべきでしょう。


DATE : 2011/05/07 (Sat)

frameworks/base/services/java/com/android/server/PackageManagerService.javaのscanPackageLI(PackageParser.Package, int, int, long)メソッド内の処理に、以下のようなコメントがあります。

Note: We don't want to unpack the native binaries for system applications, unless they have been updated (the binaries are already under /system/lib). Also, don't unpack libs for apps on the external card since they should have their libraries in the ASEC container already. In other words, we're going to unpack the binaries only for non-system apps and system app upgrades.

本コメントがあるscanPackageLIメソッドは、アプリケーションのインストール関連のメソッドから呼ばれています。

結果、ApplicationInfo.FLAG_SYSTEMの立つアプリケーションのapk内のネイティブライブラリは、/data/dataの下に展開されません。システムアプリケーションのネイティブライブラリは、必ず/system/libに置かなければなりません。ただし、Android Marketなどからでのアップデート時には/data/dataの下に展開されます。

本変更の入ったコミットIDは、4f99e3c28449833b10ee23c538246847fdb6a498です。コミットメッセージに、具体的な動作が述べられています。本コミットは、Android 2.2(Froyo)以上に含まれています。

忍者ブログ [PR]
ブログ内検索
最近の状況
リンク
カレンダー
05 2017/06 07
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)
最新トラックバック
T/O
(11/05)
ブログ内検索
最近の状況
リンク
カレンダー
05 2017/06 07
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)
最新トラックバック
T/O
(11/05)