スクロールするToolbarを実装する1

レイアウトを作成

RecyclerViewを使った簡単な構造を記載する
Toolbarをスクロールするのに必要な最低限の属性しか記述していないため、このままではエラーになるので注意

まずは、レイアウト全体をCoordinatorLayoutで包み、その中にAppBarLayoutとRecyclerViewを配置する
ToolbarをAppBarLayout内に配置し、layout_scrollFlags属性にscrollフラグをセットする
これにより、RecyclerViewのスクロールにより、ToolBarもスクロールするようになる。

しかし、このままだと、リストを一番上までスクロールしないとToolBarが表示されないため、
リストを下にスクロールした時にToolBarが表示されるようにenterAlwaysフラグを一緒にセットする

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:fitsSystemWindows="true">
    <android.support.design.widget.AppBarLayout>
        <android.support.v7.widget.Toolbar
            app:layout_scrollFlags="scroll|enterAlways" />
    </android.support.design.widget.AppBarLayout>
    <android.support.v7.widget.RecyclerView
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.design.widget.CoordinatorLayout>

実装をほぼ変更せずにレイアウトのみでToolBarのスクロールを実装することができる。

問題点

実に簡単に実装できるが少々難点もある

  • RecyclerView内のアイテムがスクロールするのに必要な数がなくても、ToolBarがスクロールする
  • 今回は単純なレイアウトだったが、RcyclerVIewの代わりにFragmentを使用していると、レイアウト構成の変更が必要な場合がある

問題点については次回以降確認する

参考サイト
http://android-developers.blogspot.jp/2015/05/android-design-support-library.html

Jellybeanのソースをダウンロードする

前回のエントリUbuntu12.04でAndroidのビルド環境構築 - forestsoftjpdevの日記にて、環境構築についてメモしたので、次はAndroid環境のダウンロードです。

まずは、ソースをダウンロードします。

参考サイト
Downloading the Source  |  Android Open Source Project

1.repoのダウンロード

まずはrepoのダウンロードフォルダの作成し、パスを通す。

$ mkdir ~/bin
$ PATH=~/bin:$PATH

repoをダウンロードし、実行権限をつける

$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

2.Jellybeanのソースをダウンロードする
まずはダウンロードするフォルダを作成
自分の場合、タグ名と同じにした

$ mkdir android-4.1.1_r4
$ cd android-4.1.1_r4

repoの設定と、sync

$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.1.1_r4

ここで、ユーザ名とメールアドレスを設定する。
そして、sync

repo sync -j4

あとは待つだけです。

また、AOSPのミラーを作成することもできます。
ミラーを作成しておくと、ソースをダウンロードする時間が大幅に短縮できます。
ミラー用のディレクトリを作成し、repoの設定、syncをします。

$ mkdir -p ~/aosp-mirror
$ cd ~/aosp-mirror
$ repo init -u https://android.googlesource.com/mirror/manifest --mirror
$ repo sync

このsyncにはとても時間がかかります。
ミラーの容量は2012年8月20日現在 62.9 GBになっています。

ミラーが終了したら、ミラーからsyncできます。

$ mkdir android-4.1.1_r4
$ cd android-4.1.1_r4
$ repo init -u ~/aosp-mirror/platform/manifest -b android-4.1.1_r4
$ repo sync

以上です。

Ubuntu12.04でAndroidのビルド環境構築

SSDにUbuntu12.04をインストールしたのでJBのビルド環境を整えた。

1.Java6をインストールする

参考
http://aleksmaus.blogspot.jp/2012/05/bulding-aosp-on-ubuntu-1204.html

ラクルのサイトから自分の環境にあったファイルをダウンロードする。
http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u32-downloads-1594644.html

自分の場合は下記ファイルをダウンロード
jdk-6u32-linux-x64.bin

ダウンロードしたフォルダで以下を実行

$ chmod u+x jdk-6u32-linux-x64.bin
$ ./jdk-6u32-linux-x64.bin
$ sudo mv jdk1.6.0_32 /usr/lib/jvm/
$ sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/bin/java" 1
$ sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/bin/javac" 1
$ sudo update-alternatives --install "/usr/bin/javac" "javadoc" "/usr/lib/jvm/bin/javadoc" 1

Javaのバージョンを切り替える場合は下記を実行する

$ sudo update-alternatives --config java
$ sudo update-alternatives --config javac
$ sudo update-alternatives --config javadoc

また、Javaの実行ファイルへのパスを通しておく。
.bashrcに下記記述を追加

export JAVA_HOME=/usr/lib/jvm
export PATH=$PATH:$JAVA_HOME/bin/

2.必要なものをインストールする。

参考
http://blog.sola-dolphin-1.net/archives/4195301.html

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl libc6-dev x11proto-core-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils python-software-properties xsltproc libx11-dev:i386 gcc-4.5 g++-4.5 gcc-4.5-multilib g++-4.5-multilib zlib1g-dev:i386 libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev lib32ncurses5-dev lib32readline-gplv2-dev lib32z-dev ia32-libs

環境構築は 以上になります。
参考にさせていただいたサイトの中のひとたちに感謝をこめて。

Jellybeanのソースをビルドする

前回のエントリJellybeanのソースをダウンロードする - forestsoftjpdevの日記の続きです。

ビルドする前に準備をします。
参考資料
Establishing a Build Environment  |  Android Open Source Project

1.CCACHEの設定を行う。
CCACHEのを使用するように、~/.bashrcに記載を追加します。

export USE_CCACHE=1
export CCACHE_DIR=<path-to-your-cache-directory>

自分は、ccacheディレクトリに ~/.ccache を指定しました。

次はCCACHEのサイズを指定します。
ダウンロードしたソースのルートディレクトリに移動し、サイズを指定します。

$ cd ~/android-4.1.1_r4
$ prebuilts/misc/linux-x86/ccache/ccache -M 50G

ちなみに、参考資料のサイトでは、以下のようになってますが、
いつの間にか上記のようにパスが変更されていました。

$ prebuilt/linux-x86/ccache/ccache -M 50G

2.ビルドする
とりあえず、full-engビルドします。

$ .build/envsetup.sh
$ lunch 1
$ time make -j8 2>&1 | tee log.txt

ビルドにかかった時間は以下になります。
real 90m2.224s
user 299m38.532s
sys 15m30.322s

スペック
メモリ:8GB
CPU:Intel® Core™ i7-2620M CPU @ 2.70GHz

以上です。

Nexus Sに公式アップデートが来て 4.1.1 Jellybeanになりました。

Nexus SにもJelly Beanの公式アップデートが配信されているようです。

下記URLからupdate.zipが取得できます。
http://forum.xda-developers.com/showthread.php?t=1784584

fastbootを使ってアップデートしてみました。

fastboot -w update 9ZGgDXDi.zip

しかし、アップデートできません。

仕方なく、CWM Recoveryにてアップデートしました。

カスタムファームを焼いている人は公式ROMに焼き直してからチャレンジしてください。

公式FactoryImageは以下です。
https://developers.google.com/android/nexus/images

あれ?

Nexus SではChromeが標準ブラウザじゃない?

以上です。

JBで追加されたFrameworkの機能InputManagerについて

JBからInputManagerが追加されています。

InputManagerについてはAndroidのFramework調査 第4回 InputManagerに記載していますが、ICSまではInputManagerはアプリケーション向けに公開されていませんでした。

Android4.1ではアプリケーション向けに機能が公開されました。
このクラスは、USBや、Bluetoothにて、新しいInputDevice(ジョイスティックやゲームパッドなど)が追加されたことをアプリケーションに通知するためのクラスです。

ゲームなど、外付けInputDeviceがあったほうがよいアプリケーションは、その接続通知を受けて、画面上にコントローラーのためのUIを表示していたのを消したりすることができるでしょう。

確認バージョン

もちろんAndroid 4.1

パッケージ:android.hardware.input
クラス:InputManager

現在接続中のInputDeviceの一覧を取得するには以下のように記載します。

        // InputManagerの取得
        InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
        // InputDeviceのデバイスIDを取得する
        int[] ids = inputManager.getInputDeviceIds();
        int length = ids.length;
        for (int i = 0; i < length; i++) {
            Log.e(TAG, inputManager.getInputDevice(i).toString());
        }

パッケージ:android.view
クラス:InputDevice
上記クラスのtoString()メソッドはオーバーライドされており、文字列として、情報を吐き出してくれます。

    @Override
    public String toString() {
        StringBuilder description = new StringBuilder();
        description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
        description.append("  Descriptor: ").append(mDescriptor).append("\n");
        description.append("  Generation: ").append(mGeneration).append("\n");
        description.append("  Location: ").append(mIsExternal ? "external" : "built-in").append("\n");

        description.append("  Keyboard Type: ");
        switch (mKeyboardType) {
            case KEYBOARD_TYPE_NONE:
                description.append("none");
                break;
            case KEYBOARD_TYPE_NON_ALPHABETIC:
                description.append("non-alphabetic");
                break;
            case KEYBOARD_TYPE_ALPHABETIC:
                description.append("alphabetic");
                break;
        }
        description.append("\n");

        description.append("  Has Vibrator: ").append(mHasVibrator).append("\n");

        description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
        appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
        appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
        appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
        appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
        appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
        description.append(" )\n");

        final int numAxes = mMotionRanges.size();
        for (int i = 0; i < numAxes; i++) {
            MotionRange range = mMotionRanges.get(i);
            description.append("    ").append(MotionEvent.axisToString(range.mAxis));
            description.append(": source=0x").append(Integer.toHexString(range.mSource));
            description.append(" min=").append(range.mMin);
            description.append(" max=").append(range.mMax);
            description.append(" flat=").append(range.mFlat);
            description.append(" fuzz=").append(range.mFuzz);
            description.append("\n");
        }
        return description.toString();
    }

端末に新しいInputDeviceが接続されたかどうかは、コールバックによって、通知を受けることができます。

コールバックの登録は下記

        // コールバックの登録処理
        inputManager.registerInputDeviceListener(mInputDeviceListener, new Handler());

コールバックはregisterInputDeviceListener()メソッドの第一引数に、
InputManager.InputManagerListenerインターフェースを実装したクラスを登録します。

    private InputDeviceListener mInputDeviceListener = new InputDeviceListener() {

        @Override
        public void onInputDeviceAdded(int deviceId) {
            // TODO デバイスが追加されたときの処理
            
        }

        @Override
        public void onInputDeviceRemoved(int deviceId) {
            // TODO デバイスが削除されたときの処理
            
        }

        @Override
        public void onInputDeviceChanged(int deviceId) {
            // TODO デバイスが変更されたときの処理
        }
    };

コールバックの解除は以下のメソッドで行います。

        // コールバックの登録解除処理
        inputManager.unregisterInputDeviceListener(mInputDeviceListener);

詳しいクラス図を次の機会にアップします。

以上になります。

Android USBドライバがアップデートされたのでUSBドライバへのデバイスの追加方法を調べた

SDKツールからインストールできるGoogle USBDriverがRev6になっていたので
ダウンロードした。

サポートされている端末は下記3つ
Google Nexus One
Google Nexus S
Google Nexus 7

Dreamなどは削除され、Galaxy NexusやXoomはDevPhoneではないので入ってません。

何も考えずにUSBドライバをアップデートしましたが、いままで追加してきた端末のデバイスIDが消えました。
端末の追加方法について、記載します。

まずはAndroid端末とPCをUSB接続し、端末のベンダーIDとプロダクトIDを調べます。

バイスマネージャを開き、Android ADB Interface のプロパティを開き、詳細のタブをクリック。
プロパティから、「ハードウェアID」を選択します。

これで、ベンダーIDとプロダクトIDがわかるのでコピーします。

調べたものを以下のファイルにほかの端末のものを参考に追加します。
自分が調べた端末はSharpの003shだったので下記のようになります。

;Sharp 003sh
%SingleAdbInterface% = USB_Install, USB\VID_04DD&PID_93B6
%CompositeAdbInterface% = USB_Install, USB\VID_04DD&PID_93B6&MI_01

これをSDK_ROOT\extras\google\usb_driver配下の「android_winusb.inf」ファイルに追加します。

あとはUSBドライバを更新する。


「コンピュータを参照してドライバソフトウェアを検索します」を選択


検索場所に、SDKのUSBドライバのパスを入力し次へ。


ドライバのソフトウェアの発行元がどうとか言われるので、無視してインストール


これでインストール完了。


インストール後のUSBデバイスの詳細はこちら。

以上です。