自由に画面を作成できるプロジェクションモードの説明をしたいと思います。
※ただ、残念ながらこのモードはSDLの趣旨から外れているようですが・・。
#プロジェクションモードって?
簡単に言うとテンプレートのようにSDL側で画面を生成するのではなく、
Android側の画面をストリーミングで配信して表示する方法です。
そのためAndroidの開発と同じ方法で、画面を設計する事ができます。
SDL単体では難しい動画の再生なども可能になります。
今回は、こちらのGithub:SDLのサンプルをベースに説明していきます。
注意:プロジェクションモードは、MantiCoreエミュレータでは動作しません。
** 動きを見るには、SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」が必要です。**
画面を作る
画面のデザインを作る
特殊な作業はありません。
Android StudioのLayout Editorで画面を作成します。
利用可能なコントロールに制限がある可能性もありますが、
VideoView、TextureView、WebViewなども動いているようです。
注意:ImageViewで画像を設定する場合、app:srcCompat
を使用すると
正しく表示されないようです。src
で画像を設定してください。
画面を作る
表示する画面は、SdlRemoteDisplay
を継承させて作ります。
setContentView(R.layout.remote_display)
で作った画面レイアウトを設定するだけです。
public static class RemoteDisplay extends SdlRemoteDisplay {
public RemoteDisplay(Context context, Display display) {
super(context, display);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.remote_display);
}
}
ボタンのイベントを作る
各種コントロールの制御方法は、通常のAndroid開発と同じですので、
ここでは説明しません。
注意が必要なのは、ボタン操作においてOnClickListener
イベントは発生しません。
基本的には、OnTouchListener
が有効のようです。
final TextView textView = (TextView)this.findViewById(R.id.textView);
Button button01 = (Button)this.findViewById(R.id.button01);
button01.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//このToastは、SDL側ではなくスマホ側で表示されます。
Toast.makeText(view.getContext(),"Touch event received: " + motionEvent.getX(),Toast.LENGTH_SHORT).show();
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
textView.setText("Hello SDL");
break;
}
return true;
}
});
AppHMITypeを設定する
AppHMITypeをNAVIGATION
に設定してください。
MEDIA
のままだと正しく出力されません。
Vector<AppHMIType> appType = new Vector<>();
appType.add(AppHMIType.NAVIGATION);
プロジェクションモードを開始する
startRemoteDisplayStream
を行う事で、SDL端末に画面が転送されます。
開始処理は、必ずSdlManager.start
が成功した後に呼び出してください。
注意:
startRemoteDisplayStream
の第三引数のparameterは、画面サイズなどを指定します。
null
の場合、自動的に最適な値が設定されます。
実際に表示されせるとこんな感じになります。
よく見ると、縦長に見えませんか?
SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」のカタログスペックでは、幅800px、縦480pxなのですが、幅800px、縦350pxの値が設定されるようで、なぜか縦長に表示されます。
正しく出力させるために、強制的に正しい値を設定します。
VideoStreamingParameters parameters = new VideoStreamingParameters();
parameters.getResolution().setResolutionWidth(800);
parameters.getResolution().setResolutionHeight(480);
sdlManager.getVideoStreamManager().startRemoteDisplayStream(getApplicationContext(), RemoteDisplay.class, parameters, false);
この設定だと、このように正しいアスペクト比で表示されます。
ただし、タッチの位置までは対応しきれないようで、縦のタッチ位置がずれます。
いろいろ試しましたが、解決方法が見つかっていません。。
また、何か分かりましたら追記します。
プロジェクションモードを終了する
SDL終了時には、必ずstopStreaming
を行います。
sdlManager.getVideoStreamManager().stopStreaming();
実際に動かしてみる
テキストや、画像が切り替わる簡単なデモです。
ストリーミングなため、反応は遅めです。
補足
テンプレートとプロジェクションモードの切り替えはできるのか??
簡単ではありますが、検証してみました。
※推測の部分がありますのでご注意ください。
テンプレートだけの場合、テンプレートの切り替えは可能でしたが、
現時点でテンプレートとプロジェクションモードは、切り替えできていません。
プロジェクションを構成するSdlRemoteDisplay
は、Dialogベースで作成されています。
Dialogを閉じるdismiss
をdismissPresentation
または、stop
で呼び出していますが
SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」では、閉じる事はできませんでした。
ちなみに、プロジェクション表示中にテンプレートを呼び出す事は可能でした。
補足:
正確には、SDLレベルでは切り替えは対応してるとのことでした。
使用したSDLアプリ開発キット「SDL DEVELOPMENT TOOLS」が、対応してないだけの可能性があります。
#最後に
プロジェクションモードが人気だと言う事で、先にプロジェクションモードの説明を行いました。
次回は、車のデータを取得してみたいと思います。