読者です 読者をやめる 読者になる 読者になる

プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

【Android】Android1.6のコーディングの注意点

Android 1.6 でアプリケーションを作成していて気がついたことをメモがわりにまとめておきます。

1.Date#toStringが遅い

型番リーダー』では、写真撮影後ネット経由でOCRサーバーにアクセスして、その結果を表示するのですが、最初組んだ時は、結果が返ってきてから表示されるまでに、非常に時間がかかりました。

ここでの処理は、OCR結果文字列、日時のエポックからのミリ秒の文字列、テンポラリで保存した画像ファイルのファイル名をインテント経由で取得し、onCreateにおいて、文字列の取得や画像の表示を行うというものでした。

多分、画像の表示に時間がかかっているのだろうと、ログを入れて調べると、どうも違うようです。なぜか、日時処理まわりで時間がかかっているようです。

そこで、ネットを調べてみると、こちらの記事にあるように、Date#toStringの処理に非常に時間がかかることがわかりました。

実際に、自分でもTraceViewを使い、調べてみるとこの通り、非常に時間がかかっていました。

対策

Date#toStringは、受け取った処理日時(エポックからのミリ秒)を人が読める形式に変換して、送信データに添付するために使います。

このため、一度画像が表示され、次にユーザーにより共有ボタンが押されるまでに、変換処理が完了していれば問題ありません。

そこで、この部分を下記のように別スレッドにて処理するようにしました(表示しているActivityの内部クラスとしています)。

    private class DateTimeTask extends Thread {
        private long mDatetime;
        
        DateTimeTask(long datetime) {
            mDatetime = datetime;
        }
        
        @Override
        public void run() {
            mDatetimeStr = new Date(mDatetime).toString();
        }
    }

Activityが表示された時のonCreateで、

        // android 1.6 では下記処理が遅いため、別スレッド処理とする
        //mDatetime = new Date(datetime).toString();
        mTask = new DateTimeTask(datetime);
        mTask.start();
として、処理を開始させておきます。

ユーザー操作による送信データを処理するメソッドの先頭部分で、

            if (flags.isUseDateTime()) {
                try {
                    mTask.join(mWaitTime);
                } catch (InterruptedException e) {
                    Log.e(TAG, "failed to get datetime.", e);
                    Toast.makeText(ctx, R.string.err_datetime_failure, Toast.LENGTH_LONG).show();
                    return;
                }
            }
のように、joinを使い処理が終わるのを待つようにしました。

なお、前述の記事によると Android 2.1では修正されているようです。

 

2.TraceView利用時にパーミッションが必要

手元にあるAndroidアプリの書籍が、android1.5をベースにしていました。

この書籍では、アプリケーションのプロファイルを取るために、TraceViewを使う場合、トレースの開始と終了を指示する一文を入れればよいとだけありました。

しかし、実際に試してみるとトレースが取れません。

こちらの記事このディスカッションによると、Android1.6では、SDカードへの書き込みパーミッションを許可する必要があるようです。

実際に、AndroidManifest.xmlに

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
というパーミッションを追加したら、問題なくトレースが取れるようになりました。

 

3.カメラプレビュー サイズへの対応

Android1.6そのものの問題ではありませんが、Android2.xの実機(Nexus Oneなど)では、カメラプレビューのサイズとして許されたサイズ以外のものが指定されると例外を投げるそうです。

このため、Android1.6でカメラプレビューをするようなアプリの場合、Android2.xの実機で動かすと異常終了する場合があるようです。

また、やっかいなことにエミュレーターではこの現象がでません。

これを回避するには、Camera.Parameters.getSupportedPictureSizesを使い、有効なプレビューサイズを取得すればよいのですが、このメソッがAndroid 2.0 で追加されたものなので、そのままではAndroid 1.6では使えません。

この場合は 、下記サイト等で解説されているように、リフレクションを使う必要があります。Android1.6の場合は適当に決定したサイズを用い、Android2.xの場合は、getSupportedPictureSizesメソッドの戻り値を使えばよいということになります。

 

Techfirm Android Lab NexusOneでAPIDemos/CameraPreviewが落ちる件

camera setPreviewSize, on Nexus One, apiVersion 7(英語)