【Smart Device Link】プロジェクションモードを試してみる

自由に画面を作成できるプロジェクションモードの説明をしたいと思います。
※ただ、残念ながらこのモードはSDLの趣旨から外れているようですが・・。

#プロジェクションモードって？
簡単に言うとテンプレートのようにSDL側で画面を生成するのではなく、
Android側の画面をストリーミングで配信して表示する方法です。
そのためAndroidの開発と同じ方法で、画面を設計する事ができます。
SDL単体では難しい動画の再生なども可能になります。

今回は、こちらのGithub:[SDLのサンプル](https://github.com/tanaka3/SDLDisplaySampleProjection)をベースに説明していきます。

**注意：プロジェクションモードは、MantiCoreエミュレータでは動作しません。**
**　　　動きを見るには、[SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」](http://ascii-store.jp/p/2018113017120/?aid=jpcampaign)が必要です。**

# 画面を作る
###### 画面のデザインを作る
特殊な作業はありません。
Android StudioのLayout Editorで画面を作成します。
利用可能なコントロールに制限がある可能性もありますが、
**VideoView**、**TextureView**、**WebView**なども動いているようです。

注意：ImageViewで画像を設定する場合、`app:srcCompat`を使用すると
正しく表示されないようです。`src`で画像を設定してください。

<img width="80%" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/189829/1e053edb-f59a-051e-a241-55982f465ea5.png">

###### 画面を作る

表示する画面は、`SdlRemoteDisplay`を継承させて作ります。
`setContentView(R.layout.remote_display)`で作った画面レイアウトを設定するだけです。

```java:SdlService.java
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`が有効のようです。

```java:SdlService.java
			
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`のままだと正しく出力されません。

```java:SdlService.java
Vector<AppHMIType> appType = new Vector<>();
appType.add(AppHMIType.NAVIGATION);
```

###### プロジェクションモードを開始する

`startRemoteDisplayStream`を行う事で、SDL端末に画面が転送されます。
開始処理は、必ず`SdlManager.start`が成功した後に呼び出してください。

注意：
`startRemoteDisplayStream`の第三引数のparameterは、画面サイズなどを指定します。
`null`の場合、自動的に最適な値が設定されます。

実際に表示されせるとこんな感じになります。

<img width="80%" alt="開発ツールの画面" src="https://qiita-image-store.s3.amazonaws.com/0/189829/c7c6c393-537a-fcb2-57c0-a4c766ac6a3d.jpeg"/>

よく見ると、縦長に見えませんか？

[SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」](http://ascii-store.jp/p/2018113017120/?aid=jpcampaign)のカタログスペックでは、幅800px、縦480pxなのですが、幅800px、縦350pxの値が設定されるようで、なぜか縦長に表示されます。

正しく出力させるために、強制的に正しい値を設定します。

```java:SdlService.java

VideoStreamingParameters parameters = new VideoStreamingParameters();
parameters.getResolution().setResolutionWidth(800);
parameters.getResolution().setResolutionHeight(480);

sdlManager.getVideoStreamManager().startRemoteDisplayStream(getApplicationContext(), RemoteDisplay.class, parameters, false);
```


この設定だと、このように正しいアスペクト比で表示されます。

<img width="80%" alt="開発ツールの画面" src="https://qiita-image-store.s3.amazonaws.com/0/189829/aceb9167-82c2-00e6-be5a-d523b336b736.jpeg"/>

ただし、タッチの位置までは対応しきれないようで、縦のタッチ位置がずれます。
いろいろ試しましたが、解決方法が見つかっていません。。
また、何か分かりましたら追記します。

###### プロジェクションモードを終了する

SDL終了時には、必ず`stopStreaming`を行います。

```java:SdlService.java
sdlManager.getVideoStreamManager().stopStreaming();
```


###### 実際に動かしてみる

テキストや、画像が切り替わる簡単なデモです。
ストリーミングなため、反応は遅めです。

<img width="80%" alt="動作画面" src="https://qiita-image-store.s3.amazonaws.com/0/189829/74955417-3243-84dd-6a68-375e8af6fc39.gif"/>

参考：[VideoStreaming](https://www.smartdevicelink.com/en/guides/android/mobile-navigation/video-streaming/)
# 補足
###### テンプレートとプロジェクションモードの切り替えはできるのか？？
簡単ではありますが、検証してみました。
_※推測の部分がありますのでご注意ください。_

テンプレートだけの場合、テンプレートの切り替えは可能でしたが、
現時点でテンプレートとプロジェクションモードは、切り替えできていません。

プロジェクションを構成する`SdlRemoteDisplay`は、Dialogベースで作成されています。
Dialogを閉じる`dismiss`を`dismissPresentation`または、`stop`で呼び出していますが
[SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」](http://ascii-store.jp/p/2018113017120/?aid=jpcampaign)では、閉じる事はできませんでした。

ちなみに、プロジェクション表示中にテンプレートを呼び出す事は可能でした。

補足：
正確には、SDLレベルでは切り替えは対応してるとのことでした。
使用した[SDLアプリ開発キット「SDL DEVELOPMENT TOOLS」](http://ascii-store.jp/p/2018113017120/?aid=jpcampaign)が、対応してないだけの可能性があります。

#最後に
プロジェクションモードが人気だと言う事で、先にプロジェクションモードの説明を行いました。
次回は、車のデータを取得してみたいと思います。