動画を再生するにはMediaPlayerとVideoViewを使用する方法があります。
VideoView を使うサンプルはネット上に多く公開されているので、今回はMediaPlayerで動画を再生してみます。
加えて、Android 5.0から追加されたrequestVisibleBehind()を利用して、ホームボタンを押されてもバックグランドで動画再生を続けてみます。
サンプルはAndroid TV上での動画再生を想定しています。
スポンサードリンク
MediaPlayerで動画を再生するには、
という順序でAPIを呼ぶ必要があります。
ネット上の動画再生を行う場合には、setDataSource() メソッドにURIを指定します。
その他、知っとくべきメソッドとして、
MediaPlayerではlayoutにSurfaceViewを使用しますが、SurfaceViewを使用するにはSurfaceHolder.Callbackを使用する必要があります。
音声は再生できるのに、映像が表示されない場合はholderの渡し方が間違っています。
音声のバックグランド再生は、サービスを使って再生を継続する方法が一般的に使われています。
Android5.0 (ロリポップ)からは、requestVisibleBehind() というメソッドが追加されました。
バックグランドでコンテンツの再生を続けたい場合には、onResume()とonPause()の間にこのメソッドを呼べば半透明なActivityとして動作再生を続けてくれます。
MediaControllerを利用すれば、単純な 再生/一時停止、早送り、巻き戻しボタンを提供してくれます。
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().setFormat(PixelFormat.TRANSPARENT);
スポンサードリンク
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nehori.videoplayer" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.TV" > <android:logo="@drawable/banner"> <activity android:name=".VideoPlayer" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
AndroidTV向けに「android.intent.category.LEANBACK_LAUNCHER」というカテゴリを持つIntentFilterをマニフェストに宣言しています。
また <android:logo="@drawable/banner" >を宣言するとアプリケーションを起動するLauncherアイコンとして使用されます。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <SurfaceView android:id="@+id/surface" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
全画面に「SurfaceView」を保有している簡単なlayoutです。
package com.nehori.videoplayer; import java.io.IOException; import android.app.Activity; import android.graphics.PixelFormat; import android.annotation.SuppressLint; import android.media.MediaPlayer; import android.os.Bundle; import android.net.Uri; import android.util.Log; import android.view.KeyEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.WindowManager; import android.widget.MediaController; import android.widget.MediaController.MediaPlayerControl; public class VideoPlayer extends Activity implements SurfaceHolder.Callback, MediaPlayerControl { private static final String TAG = "VideoPlayer"; private SurfaceHolder mHolder; private SurfaceView mPreview; private MediaPlayer mMediaPlayer = null; private MediaController mMediaController; @Override public void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate"); super.onCreate(savedInstanceState); // レイアウトを読み込む setContentView(R.layout.activity_video_player); // スクリーンセーバをオフにする getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().setFormat(PixelFormat.TRANSPARENT); mPreview = (SurfaceView) findViewById(R.id.surface); mHolder = mPreview.getHolder(); mHolder.addCallback(this); // MediaPlayerを利用する mMediaPlayer = new MediaPlayer(); // MediaControllerを利用する mMediaController = new MediaController(this); mMediaController.setMediaPlayer(this); mMediaController.setAnchorView(mPreview); } @SuppressLint("NewApi") protected void onResume() { super.onResume(); // allow to continue playing media in the background. // バックグラウンド再生を許可する requestVisibleBehind(true); } public boolean onDestroy(MediaPlayer mp, int what, int extra) { Log.d(TAG, "onDestroy"); if (mp != null) { mp.release(); mp = null; } return false; } @Override public void surfaceCreated(SurfaceHolder paramSurfaceHolder) { Log.d(TAG, "surfaceCreated"); // URLの先にある動画を再生する Uri mediaPath = Uri.parse("http://xxxxx.com/xxxx.mp4"); try { mMediaPlayer.setDataSource(this, mediaPath); mMediaPlayer.setDisplay(paramSurfaceHolder); mMediaPlayer.prepare(); mMediaPlayer.start(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder paramSurfaceHolder, int paramInt1, int paramInt2, int paramInt3) { } @Override public void surfaceDestroyed(SurfaceHolder paramSurfaceHolder) { Log.d(TAG, "surfaceDestroyed"); if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } } // ここから先はMediaController向け -------------------------- @Override public boolean dispatchKeyEvent(KeyEvent event) { Log.d(TAG, "KeyCode:"+ event.getKeyCode()); if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) { if (!mMediaController.isShowing()){ mMediaController.show(); } else { mMediaController.hide(); } } return super.dispatchKeyEvent(event); } @Override public void start() { mMediaPlayer.start(); } @Override public void pause() { mMediaPlayer.pause(); } @Override public int getDuration() { return mMediaPlayer.getDuration(); } @Override public int getCurrentPosition() { return mMediaPlayer.getCurrentPosition(); } @Override public void seekTo(int pos) { mMediaPlayer.seekTo(pos); } @Override public boolean isPlaying() { return mMediaPlayer.isPlaying(); } @Override public int getBufferPercentage() { return 0; } @Override public boolean canPause() { return true; } @Override public boolean canSeekBackward() { return true; } @Override public boolean canSeekForward() { return true; } @Override public int getAudioSessionId() { return 0; } }
スポンサードリンク