Android
SDL

【Smart Device Link】画面とかを作ってみる

今回は、SDLの画面をいろいろ触ってみたいと思います。
似たようなタイミングで、ASCIIさんもSDLの連載をされています。
エミュレータの作成など、かなり詳しく記載されてますので、
こちらもご覧頂けるといろいろ知識が得られるかなと思います。

SDLの画面について

SDLの画面表示は、Android Autoなどとは異なり、
基本的には、テンプレートを利用することを想定しているようです。
あらかじめ決まった画面構成(画像や、ボタンなど)に対して、情報を設定し動作させます。

開発者側は、SDL端末のデザインを気にすることなく、統一感のあるデザインで機能を提供することができます。
※良いように言い過ぎな気もします。。

自由に画面を作成する方法(プロジェクションモード)もありますが、それは別の機会に説明します。

今回は、Github:SDLのサンプルをベースに説明していきます。

画面を作ってみる

テンプレートの設定

何も設定しない場合は、PredefinedLayout.MEDIAが設定されている状態になります。
特定のテンプレートを使用したい場合は、SetDisplayLayout.setDisplayLayoutでテンプレートを指定し、sdlManager.sendRPCで登録します。

SdlService.java
private void setDisplayGraphicWithTextButtons(){
    SetDisplayLayout setDisplayLayoutRequest = new SetDisplayLayout();

    //GRAPHIC_WITH_TEXT_AND_SOFTBUTTONSのテンプレートを設定
    setDisplayLayoutRequest.setDisplayLayout(PredefinedLayout.GRAPHIC_WITH_TEXTBUTTONS.toString());
    setDisplayLayoutRequest.setOnRPCResponseListener(new OnRPCResponseListener() {
        @Override
        public void onResponse(int correlationId, RPCResponse response) {
            //テンプレートの設定に成功した場合
            if(((SetDisplayLayoutResponse) response).getSuccess()){
                Log.i("SdlService", "Display layout set successfully.");
                //ここで画面の設定処理などを記載します。
            }else{
                Log.i("SdlService", "Display layout request rejected.");
            }
    });

    sdlManager.sendRPC(setDisplayLayoutRequest);
}
利用可能なテンプレートは??

テンプレートは、SDL端末に依存するため、テンプレートを利用する前に利用可能かチェックする必要があります。
利用可能なテンプレートは、以下の方法で取得可能です。

SdlService.java
private void checkTemplateType(){
    Object result = sdlManager.getSystemCapabilityManager().getCapability(SystemCapabilityType.DISPLAY);
    if( result instanceof DisplayCapabilities){
        List<String> templates = ((DisplayCapabilities) result).getTemplatesAvailable();
        Log.i("Templete", templates.toString());
    }
}

ちなみに、Manticoreのエミュレータで利用可能なテンプレートは以下の通りです。
※でも、正しく動かなかったりするものもあったり・・。

[DEFAULT, MEDIA, NON-MEDIA, ONSCREEN_PRESETS, NAV_FULLSCREEN_MAP, NAV_KEYBOARD, GRAPHIC_WITH_TEXT, TEXT_WITH_GRAPHIC, TILES_ONLY, TEXTBUTTONS_ONLY, GRAPHIC_WITH_TILES, TILES_WITH_GRAPHIC, GRAPHIC_WITH_TEXT_AND_SOFTBUTTONS, TEXT_AND_SOFTBUTTONS_WITH_GRAPHIC, GRAPHIC_WITH_TEXTBUTTONS, TEXTBUTTONS_WITH_GRAPHIC, LARGE_GRAPHIC_WITH_SOFTBUTTONS, DOUBLE_GRAPHIC_WITH_SOFTBUTTONS, LARGE_GRAPHIC_ONLY]

参考:DisplayCapabilitiesクラスの説明
参考:デザインについて

画像やテキストを設定してみる

画像や、テキストは、sdlManager.getScreenManager().beginTransactionから
sdlManager.getScreenManager().commitの間で設定します。
表示可能なテキストや、画像の位置や、サイズなどはテンプレートに依存するため指定することはできません。

画像を指定する場合、FileTypeは、画像の種類に合ったものを使用してください。
また、利用可能な画像もSDL端末に依存するため、実際に利用可能かは、テンプレートと同じくチェックする必要があります。
利用可能な画像は、DisplayCapabilities.getGraphicSupportedで確認できます。

SdlService.java
sdlManager.getScreenManager().beginTransaction();
//テキストを登録する場合
//sdlManager.getScreenManager().setTextField1("Hello, this is MainField1.");
//画像を登録する
SdlArtwork artwork = new SdlArtwork("sample01.png", FileType.GRAPHIC_PNG, R.drawable.sample01, true);
sdlManager.getScreenManager().setPrimaryGraphic(artwork);
sdlManager.getScreenManager().commit(new CompletionListener() {
    @Override
    public void onComplete(boolean success) {
        if (success) {
            Log.i(TAG, "welcome show successful");
        }
    }
});
ボタンを設定してみる

ボタンは、SoftButtonObjectをgetScreenManager().setSoftButtonObjectsすることで設定する事ができます。
テンプレートに応じて複数個のボタンも登録可能です。

SoftButtonObjectは、SoftButtonStateを保持しており、複数個設定する事で、
トグルボタンのように表示を切り替えて利用する事ができます。
ボタンの切り替えは、SoftButtonObject.transitionToNextStateで可能です。

SdlService.java
//一つ目のボタンの設定
//一つ目のボタンステート
SoftButtonState softButton01State1 = new SoftButtonState("button01_state1", "button01_state1", null);

//Artworkを設定する事でボタンに画像を貼り付けることも可能
SdlArtwork state_artwork = new SdlArtwork("state2.png", FileType.GRAPHIC_PNG, R.drawable.ic_sdl, true);
SoftButtonState softButton01State2 = new SoftButtonState("button01_state2", "button01_state2", state_artwork);

List<SoftButtonState> softButtonStates = Arrays.asList(softButton01State1, softButton01State2);
SoftButtonObject softButtonObject1 = new SoftButtonObject("softButtonObject01", softButtonStates, softButton01State1.getName(), null);

//二つ目のボタン設定
SoftButtonState softButton02State1 = new SoftButtonState("button02_state1", "button02_state1", null);
SoftButtonObject softButtonObject2 = new SoftButtonObject("softButtonObject02",  Collections.singletonList(softButton02State1), softButton02State1.getName(), null);

//二つのボタンを登録する
List<SoftButtonObject> buttons = Arrays.asList(softButtonObject1, softButtonObject2);
sdlManager.getScreenManager().setSoftButtonObjects(buttons);

ボタンのイベントは、SoftButtonObjectの生成時、またはsetOnEventListenerで登録する事ができます。
onPressは、ボタンが押されたとき呼び出されます。
onEventは、各動作毎に呼び出され、OnButtonEvent.getButtonEventModeをチェックする事で、
BUTTONUPまたは、BUTTONDOWNを判断する事ができます。

SdlService.java
softButtonObject1.setOnEventListener(new SoftButtonObject.OnEventListener() {
    @Override
    public void onPress(SoftButtonObject softButtonObject, OnButtonPress onButtonPress) {
        softButtonObject.transitionToNextState();
    }

    @Override
    public void onEvent(SoftButtonObject softButtonObject, OnButtonEvent onButtonEvent) {
    }
});

今回のサンプルを実際に動かすとこんな感じになります。
button01_state1を動かすとボタンが切り替わります。
button02_state1を動かすと左の画像が切り替わります。

参考:テキスト、画像とボタンについて

最後に

ざっくりですが、画面の作り方について説明してみました。
本気で作る場合、SDL依存チェック(テンプレートとか、画像フォーマットとかいろいろ・・)がたくさん入り少し面倒な感じです。
ただ、簡単なデモ用のアプリを作る分には、今回の内容がわかればいろいろ作っていけそうな気がします。

SdlManagerListenerなど基本的な部分を飛ばしていたりするところもありますが、
次回は、自動車からの情報取得をやってみたいと思います。