2012年6月30日土曜日

PhoneモードとTabletモードの切り分け

ICSから変更されています。
これは注目すべき変更点です。

Phone/Tabletの切り分け

PhoneWindowManagerService#setInitialDisplaySizeの処理を確認

        // SystemUI (status bar) layout policy
        int shortSizeDp = shortSize
                * DisplayMetrics.DENSITY_DEFAULT
                / DisplayMetrics.DENSITY_DEVICE;

        if (shortSizeDp < 600) {
            // 0-599dp: "phone" UI with a separate status & navigation bar
            mHasSystemNavBar = false;
            mNavigationBarCanMove = true;
        } else if (shortSizeDp < 720) {
            // 600-719dp: "phone" UI with modifications for larger screens
            mHasSystemNavBar = false;
            mNavigationBarCanMove = false;
        } else {
            // 720dp: "tablet" UI with a single combined status & navigation bar
            mHasSystemNavBar = true;
            mNavigationBarCanMove = false;
        }


ICSでは600dp以上をTabletとして扱っていました。
JBでTabletとして認識するには720dp以上が必要です。

Android 4.1で追加されたNAVIGATION_BAR_PANEL_LAYERについて

f:id:baroqueworksdev:20120701053040p:image:w240

以下の記事にて、表示レイヤーの確認を行いました。

JBの表示レイヤーについて
http://d.hatena.ne.jp/baroqueworksdev/20120630/1341084903

今回は新規追加レイヤー、NAVIGATION_BAR_PANEL_LAYERの確認です。


NAVIGATION_BAR_PANEL_LAYERの使用箇所

PhoneWindowManager#windowTypeToLayerLw()にてwindowTypeからLayerの値に変換するので、grepはTYPE_NAVIGATION_BAR_PANELで。
引っかかるのは以下の3ファイルでした。

SystemUIが使用していますね。

  • com\android\systemui\statusbar\phone\PhoneStatusBar.java
  • com\android\systemui\statusbar\tablet\TabletStatusBar.java
  • com\android\systemui\statusbar\tablet\TabletTicker.java

PhoneStatusBar.javaに焦点をあてて調査します。
TYPE_NAVIGATION_BAR_PANELを使用しているのは以下のモジュール。
BaseStatusBar#updateSearchPanel
↓
PhoneStatusBar#getSearchLayoutParams() ←★ここでWindowLayoutのパラメータとして使用

BaseStatusBar#updateSearchPanelのモジュール内で、
mSearchPanelViewというViewをWindowにaddViewしていました。

    protected void updateSearchPanel() {
        // Search Panel
        boolean visible = false;
        if (mSearchPanelView != null) {
            visible = mSearchPanelView.isShowing();
            WindowManagerImpl.getDefault().removeView(mSearchPanelView);
        }

        // Provide SearchPanel with a temporary parent to allow layout params to work.
        LinearLayout tmpRoot = new LinearLayout(mContext);
        mSearchPanelView = (SearchPanelView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_search_panel, tmpRoot, false);
        mSearchPanelView.setOnTouchListener(
                 new TouchOutsideListener(MSG_CLOSE_SEARCH_PANEL, mSearchPanelView));
        mSearchPanelView.setVisibility(View.GONE);

        WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());

        WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
        mSearchPanelView.setBar(this);
        if (visible) {
            mSearchPanelView.show(true, false);
        }
    }



SearchPanelViewってなんだ?


mSearchPanelViewの表示タイミングは以下のソースを参照。
com\android\systemui\statusbar\phone\PhoneStatusBar.java


    @Override
    public void showSearchPanel() {
        super.showSearchPanel();
        WindowManager.LayoutParams lp =
            (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
        lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
    }


    private Runnable mShowSearchPanel = new Runnable() {
        public void run() {
            showSearchPanel();
        }
    };
    View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!shouldDisableNavbarGestures()) {
                    mHandler.removeCallbacks(mShowSearchPanel);
                    mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
                }
            break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mHandler.removeCallbacks(mShowSearchPanel);
            break;
        }
        return false;
        }
    };

    private void prepareNavigationBarView() {
        mNavigationBarView.reorient();

        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
        mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
        mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
        updateSearchPanel();
    }



ようはHomeキーを一定時間押し続けると、SearchPanelViewが表示されます。
Viewの処理はこちらのソースを参照

\sources\android-16\com\android\systemui\SearchPanelView.java




JBの表示レイヤーについて


Android SDKのAPI 16が公開されました。
一緒にソースもDLできるので、毎度おなじみの表示レイヤーのチェックを行いました。

確認OSバージョン

Android OS 4.1 JB

表示レイヤー

OSのメジャーアップデートなので、表示レイヤーの変更点があるかどうか確認しました。
ソース
SDK\sources\android-16\com\android\internal\policy\impl
- PhoneWindowManager.java
(★ = JBにて新規追加されたレイヤー)
値レイヤー名用途
2WALLPAPER_LAYER壁紙
2APPLICATION_LAYER一般アプリケーション
3PHONE_LAYER着信などの電話用
4SEARCH_BAR_LAYER検索バー
5SYSTEM_DIALOG_LAYER電源OFFダイアログなど
6TOAST_LAYERトースト表示
7PRIORITY_PHONE_LAYERSIMエラー表示など
8SYSTEM_ALERT_LAYERANRやLowバッテリー通知
9INPUT_METHOD_LAYER文字入力UI
10INPUT_METHOD_DIALOG_LAYER文字入力UIのダイアログ
11KEYGUARD_LAYERキーガード表示
12KEYGUARD_DIALOG_LAYERシャットダウン中やSIMロック表示、キーガード表示中の電源OFFダイアログなど
13SCREENSAVER_LAYERスクリーンセーバー★
14STATUS_BAR_SUB_PANEL_LAYERPhone用expandしたパネル
15STATUS_BAR_LAYERStatusBar
16STATUS_BAR_PANEL_LAYERStatusBarをexpandしたパネル
17VOLUME_OVERLAY_LAYERボリューム変更
18SYSTEM_OVERLAY_LAYERキーガードより上位に表示するシステムオーバーレイ
19NAVIGATION_BAR_LAYERナビゲーションBar
20NAVIGATION_BAR_PANEL_LAYERナビゲーションBarの上に表示するために必要なパネル(searchなど)★
21SYSTEM_ERROR_LAYERシステムエラー通知
22DRAG_LAYERドラッグ&ドロップ操作用
23SECURE_SYSTEM_OVERLAY_LAYER
24BOOT_PROGRESS_LAYERBoot中のDialog表示
25POINTER_LAYERマウスポインター
26HIDDEN_NAV_CONSUMER_LAYERFakeWindow用


大きな変更点は
  1. SCREENSAVER_LAYERの追加
  2. NAVIGATION_BAR_PANEL_LAYERの追加

NAVIGATION_BAR_PANEL_LAYERのの使用箇所はべっと調査します。

2012年3月31日土曜日

AOSPのTag間のdiffとlogを取得する



AOSPにandroid-4.0.4_r1.1が現れました。

android-4.0.3_r1とのdiffとlogの取得を行いました。


diffの取得

ファイル差分すべてを取得
$ repo forall -p -c git diff android-4.0.3_r1..android-4.0.4_r1.1 > diff_android-4.0.3_r1_android-4.0.4_r1.1.txt


変更されたファイルの一覧と変更行数を取得
$ repo forall -p -c git diff --stat android-4.0.3_r1..android-4.0.4_r1.1 > diff_android-4.0.3_r1_android-4.0.4_r1.1_stat.txt


ディレクトリ毎の変更量(%)を取得
$ repo forall -p -c git diff --dirstat android-4.0.3_r1..android-4.0.4_r1.1 > diff_android-4.0.3_r1_android-4.0.4_r1.1_dirstat.txt


logの取得


TAG間のlog(コミットタイトル)を取得
$ repo forall -p -c git log --oneline --no-merges android-4.0.3_r1..android-4.0.4_r1.1 > log_android-4.0.3_r1_android-4.0.4_r1.1.txt


どうぞ


diffとlogの実行結果を以下にUploadしました。よろしければ、どうぞ。

https://docs.google.com/leaf?id=0BwdCdBWuE_7cSHE0Mkpodm5TN3VMZjFmOTJ2QUU0UQ

2011年7月30日土曜日

NFCを使ってみる その1


NFCを使用した簡単なアプリを作成しようと思います。
まずはTAGを受け取れるようになるまで。

AndroidManifest.xmlに必要なパラメータを記載

NFCハードウェアを使用するために必要なパーミッションを追加
<uses-permission android:name>"android.permission.NFC" />


AndroidMarketにUpする際、NFC機能搭載端末のみ見えるようにするuses-featureを追加
<uses-feature android:name="android.hardware.nfc" android:required"true" />


ActivityでNFCデータをハンドリングしたい場合、inten-filterを追加
<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<data android:mimeType="mime/type"/><
/intent-filter>


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

<intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />

必要な<intent-filter>を記載しましょう。

<meta-data ・・・>はandroid.nfc.action.TECH_DISCOVERED用のタグです。
プロジェクトの「/res/xml」に 受け取りたいNFC規格を記載した「nfc_tech_filter.xml」を追加します。

詳しくはDeveloperサイトを参照



    android.nfc.tech.IsoDep
    android.nfc.tech.NfcA
    android.nfc.tech.NfcB
    android.nfc.tech.NfcF
    android.nfc.tech.NfcV
    android.nfc.tech.Ndef
    android.nfc.tech.NdefFormatable
    android.nfc.tech.MifareClassic
    android.nfc.tech.MifareUltralight




必要な<tech>タグのみ記載しましょう。

ちなみに、ここに記載する<tech>は「\frameworks\base\core\java\android\nfc\tech」に存在するクラス名です。


これだけで、SuiccaやICOCAなどのFelicaカードを端末にかざすと、android.nfc.action.XXXXのIntentを受けてActivityが起動します。

2011年6月16日木曜日

Fragmentについて



(作成中)


Fragmentのサンプル

難しい話は置いといて結果的にどうなるのか、
Android 3.1のエミュレータにインストールされている「ApiDemo」でUIを確認。
f:id:baroqueworksdev:20110618043421p:image:w640


サンプルプログラムはこちら。
http://developer.android.com/intl/ja/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html


ActivityにFragmentを追加しているのは以下のコード。

// Check what fragment is currently shown, replace if needed.
DetailsFragment details = (DetailsFragment)
                getFragmentManager().findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index) {
    // Make new fragment to show this selection.
    details = DetailsFragment.newInstance(index);

    // Execute a transaction, replacing any existing fragment
    // with this one inside the frame.
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.details, details);
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    ft.commit();
}


以下の箇所で、「containerViewをR.id.detailsとして、フラグメントdetailsに置き換えます」と指定。
    ft.replace(R.id.details, details);



ft.commit()後、DetailsFragment.onCreateView()がコールされて、フラグメントのViewをActivityに渡している。


Hierarchy ViewでView階層を確認。
ピンク枠がFragmentのcontainerView(親View)
黄色枠がFragmentが持っているView

f:id:baroqueworksdev:20110618044501p:image:w640


GingerBread以前のバージョンでもLayout.xmlを駆使すれば、
見た目は真似できますね。


Fragmentのライフサイクル

FragmentのライフサイクルはActivityのライフサイクルに結び付けられています。

Resume状態になるまでに呼び出されるライフサイクルメソッド

method内容
onAttach()Activityに関連付けれた際に1度だけコールされる
onCreate()fragmentの初期化生成のためによばれる
onCreateView()fragmentのView階層を生成し戻り値として返す
onActivityCreated()Activity.onCreaateが完了したことをframentに通知
onStart()ActivityのonStart()と同等
onResume()ActivityのonResume()と同等


Destroy状態になるまでに呼び出されるライフサイクルメソッド

method内容
onPause()fragment操作が一時停止状態に陥るとき、ActivityのonPause()と同等
onStop()fragment操作が一時停止状態となりユーザーから見えない状態、ActivityのonStop()と同等
onDestroyView()fragmentのView階層をCleanUp可能な状態
onDestroy()fragmentをCleanUp可能な状態
onDetach()Activityとの関連付けが解除された状態


上記のfragmentのライフサイクルとActivityのライフサイクルとの関係を、図に記す。
f:id:baroqueworksdev:20110617020005p:image

(developerサイトから拝借)

(作成中)

参考


http://developer.android.com/intl/ja/reference/android/app/Fragment.html

http://developer.android.com/intl/ja/guide/topics/fundamentals/fragments.html