Android 勉強会 #2 TextureViewのご紹介

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ひたすらと1つのComponentをほめたたえます

アジェンダ

  • TextureViewとは
  • サンプルコード
  • SurfaceViewとの比較
  • 移植の仕方
  • まとめ

4.0以降の情報についていけていますか?

早く市場から2.x系が駆逐されるといいと思います

TextureView?

  • ICS以降に追加された比較的新しいView Component
  • SupportPackageに入ってません!!
  • 日本語の情報が極端に少ない!
  • Open GL ESやMovieのストリーミングデータの高速描画絡み
  • SufaceViewをさらに強化した描画能力を持つ(らしい)
  • ピクセル単位のアルファブレンドができるらしい
  • システムレイヤにかぶせることができる(FLAG_HARDWARE_ACCELERATEDフラグ必須)

SurfaceViewの強化版みたいな

素晴らしい!

・・・気がする

TextureViewを知るまでの流れ

  • Open GL ES絡みの記事を執筆するために色々勉強する
  • 揺下さんこと(@eaglesakura さん)の著書「はじめてのOpen GL ES」で勉強する
  • 揺下さんがTextureViewに言及してるTweetを見かける
  • どうやらOpen GL ES絡みらしい
  • SurfaceTextureというものを利用したViewのようだ(An image stream as an OpenGL ES texture.)
  • しかも日本語の情報が不足しまくっている模様(StackOverflowとMLと @eaglesakuraさんのメモくらい)

日本語の情報が・・・確かにない

TextureView_info_IT TextureView_google_search

ご覧のありさまだよ

TextureViewの目的

GPUのハードウェアアクセラレータとSurfaceTextureによる、高速描画のための新しいView Component Widgetの提供。そのため、

  • SurfaceViewに特徴としては近い(unlike SurfaceViewとは公式に書いてあるけど)
  • 対象は、動画やCameraのプレビューのストリームデータ、Open GLデータとか
  • Viewと同じく、回転・変形・アニメーションが可能

SurfaceTexture?

SurfaceTexture

Captures frames from an image stream as an OpenGL ES texture.

Open GL ESのテクスチャとして描画されるので、GPUのハードウェアアクセラレータの恩恵を受けて描画が高速

サンプルコードを見てみる

全部解説できないので要素だけ

Interface

	// Callback Methodを実装する
	 implements TextureView.SurfaceTextureListener 
	 
	 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
	 	// TextureViewの準備ができたらCallされる
	 }
	 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
	 	// TextureViewのサイズ変更時にCallされる
	 }
	 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
	 	// TextureViewが破棄されるタイミングでCallされる
	 }
	 public void onSurfaceTextureUpdated(SurfaceTexture surface) {
	 	// TextureViewの描画が更新されたタイミングでCallされる
	 }
	

Set Callback Interface

	 // Callback Interfaceを設定
	 mTextureView.setSurfaceTextureListener(this); 
	
  • 様々な初期化は、onSurfaceTextureAvailable()で行えばOK
  • onSurfaceTextureUpdated()は、表示されているCanvasの再描画時にCallされる
  • Cameraクラスには、SurfaceTextureをセットすることで、Previewの動画ストリーミングデータを自動的に描画する機能がある。

ほとんどSurfaceViewの使い方と一緒

SurfaceViewとの比較

SurfaceViewの描画はちょっと特殊

  1. アプリケーションの裏に新しいWindowを生成する
  2. アプリケーションの一部に穴を開けて裏のWindowを表示する

これにより、裏のWindowの描画とアプリケーションの描画が切り離されるので、RenderingのRefresh時にUIスレッドを妨害することがない

  1. 裏のWindowに描画されたコンテンツなので、意図したとおりに変形させられない
  2. このため、ListViewやScrollViewで使いづらい
  3. UIに直接作用するView Propertyが使えない。View#setAlpha()とか

Viewとしてちょっと使いづらい

対 【SurfaceView】 3番勝負

1.Rotationを使って回転させる

Demo

TextureViewの勝ち

2.透過させてみる

Demo

TextureViewの勝ち

実は透過させる方法もありますけど。Viewプロパティの操作だけじゃNG

3.ListViewのアイテムに組み込んでみる

Demo

TextureViewの勝ち

圧倒的じゃないか。わが軍は

SurfaceViewからTextureViewへの移植を試みる

Function SurfaceView TextureView
Interface Callback SurfaceTextureListener
Ready surfaceCreated onSurfaceTextureAvailable
Changed surfaceChanged onSurfaceTextureSizeChanged
Destroy surfaceDestroyed onSurfaceTextureDestroyed
Update - onSurfaceTextureUpdated

対応するメソッドさえ気をつければOK

あとはざくっと

  1. Callback, Callback2 InterfaceをSurfaceTextureListenerへ変更
  2. 前の表に従ってまるっと移植
  3. SurfaceHolder#lockCanvas, unlockCanvasAndPostを、SurfaceTextureView#lockCanvasやらに変更

注意

  • draw()メソッドをOverrideしている、SurfaceのExtendsクラスの場合は注意が必要です。TextureViewのdraw()メソッドはfinalで潰されているので、Overrideできませぬ

Conclusion

  • SurfaceViewより使い勝手はよさそう
  • そこそこ移植性も高い
  • ハードウェアアクセラレータによるレンダリングを行なってくれるので、最近の端末であれば間違い無く高速
  • SurfaceViewがICS以降遅いという情報が散見される。
  • RSSurfaceViewの代用としてのRSTextureViewは、APIレベル16でDeprecatedに指定されたので、使っちゃダメ
  • EGL Surfaceの生成ができるとか、Open GL ESも絡めるらしいので、今後に期待。API 16(JB)でOpen GL関連のメソッドが追加されてる模様

TextureViewをつかいませう