質問の概要:
1)最初にビデオを一時停止として表示し、すぐに再生しない方法は?
2)タッチでビデオを一時停止/一時停止解除する方法、およびActionBarとMediaControllerを非表示/表示する方法。
アドバイスをいただければ幸いです。ありがとう! (関連コードが添付されています)
更新1
質問2の解決策がいくらか見つかりました(falseを返す必要があります)が、質問1に答える方法がまだわかりません。
ユーザーが私のアプリのボタンを押すと、ビデオを見るのに時間がかかります。彼らが最初にその画面を開いたとき、私はビデオを一時停止してすぐに再生しないようにしたいと思います。また、画面をタップして動画の再生を一時停止できるようにしたいのですが。動画が一時停止したら、ActionBar
とMediaController
を表示したいと思います。ビデオが再開されたら、ActionBar
とMediaController
を非表示にします(おそらく少し遅れて?)
いくつか試しましたが、動画が一時停止しても再開されない、ActionBar
とMediaController
が正しく表示または非表示にならないなどの問題が発生します。
アップデート2
質問1の部分的な解決策を見つけ、ビデオを最初に開いたときに一時停止として表示するようにコードを更新しました。ただし、初めて開いたときは、ビデオビューをタッチして再生するまで、黒い画面しか表示されません。ビデオを1回視聴すると、最初にリセットされて一時停止し、再び再生されるのを待ちます。また、ビデオの最初から正しい画像が表示されます。しかし、最初は黒い画面を回避する方法がわかりません。
関連コード:
public class ViewImageVideoFragment extends Fragment
{
private int position = 0;
private MediaController mMediaController;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mMediaController = new MediaController(getActivity());
...
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
if (savedInstanceState != null)
{
position = savedInstanceState.getInt("position");
}
View v = inflater.inflate(R.layout.fragment_video_view, parent, false);
mVideoView = (VideoView) v.findViewById(R.id.fragmentVideoView);
mVideoView.setVideoPath(videoPath);
mVideoView.setMediaController(mMediaController);
mVideoView.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent motionEvent)
{
if (mVideoView.isPlaying())
{
mVideoView.pause();
if (!getActivity().getActionBar().isShowing())
{
getActivity().getActionBar().show();
mMediaController.show(0);
}
position = mVideoView.getCurrentPosition();
return false;
}
else
{
if (getActivity().getActionBar().isShowing())
{
getActivity().getActionBar().hide();
mMediaController.hide();
}
mVideoView.seekTo(position);
mVideoView.start();
return false;
}
}
});
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mediaPlayer)
{
mVideoView.seekTo(0);
}
});
if (position != 0)
{
mVideoView.seekTo(position);
mVideoView.start();
}
else
{
mVideoView.seekTo(0);
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
if (mVideoView != null)
{
savedInstanceState.putInt("position", mVideoView.getCurrentPosition());
}
mVideoView.pause();
}
}
最初に動画を一時停止として表示するには、コードでseekTo(0)
をseekTo(1)
に変更するだけです。これにより、ビデオが1ミリ秒の時間に移動し、そこから取得できます。
//edited here
private int position = 1;
private MediaController mMediaController;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mMediaController = new MediaController(getActivity());
...
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
if (savedInstanceState != null)
{
position = savedInstanceState.getInt("position");
}
View v = inflater.inflate(R.layout.fragment_video_view, parent, false);
mVideoView = (VideoView) v.findViewById(R.id.fragmentVideoView);
mVideoView.setVideoPath(videoPath);
mVideoView.setMediaController(mMediaController);
mVideoView.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent motionEvent)
{
if (mVideoView.isPlaying())
{
mVideoView.pause();
if (!getActivity().getActionBar().isShowing())
{
getActivity().getActionBar().show();
mMediaController.show(0);
}
position = mVideoView.getCurrentPosition();
return false;
}
else
{
if (getActivity().getActionBar().isShowing())
{
getActivity().getActionBar().hide();
mMediaController.hide();
}
mVideoView.seekTo(position);
mVideoView.start();
return false;
}
}
});
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mediaPlayer)
{
//here
mVideoView.seekTo(1);
}
});
//here
if (position != 1)
{
mVideoView.seekTo(position);
mVideoView.start();
}
else
{
//here
mVideoView.seekTo(1);
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
if (mVideoView != null)
{
savedInstanceState.putInt("position", mVideoView.getCurrentPosition());
}
mVideoView.pause();
}
}
私が正しく理解していれば、ビデオを開始する準備ができるまで、ビデオのフレームをプレースホルダーとして表示したいと思います。これを達成するために私が知っている2つの方法があります:
MediaPlayer.seekTo
を使用して、ビデオを数フレーム先に移動できます。たとえば、値150
を使用して、ビデオファイルの150ミリ秒のフレームを表示できます。シークするためにビデオを開始する必要はありません。
MediaMetadataRetriever met = new MediaMetadataRetriever();
try {
met.setDataSource(data[0], new HashMap<String, String>()); //use this constructor, other one has a bug...
Bitmap b = met.getFrameAtTime();
if (b == null)
b = met.getFrameAtTime(150, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
met.release();
return b;
} catch (Exception e) {
Log.d(TAG, "MediaMetadata failed", e);
}
これにより、Bitmap
が得られ、これをImageView
に入れて、ビデオの代わりに設定できます。ただし、このAPIは、扱っているビデオコーデックの種類によっては、常にバグがあります。
私の情報源-
show()
show(int timeout)
hide()
isShowing()
onTouchEvent()
すべてのメモはコードにあります
public class ViewImageVideoFragment extends Fragment
{
private int position = 0;
private MediaController mMediaController;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mMediaController = new MediaController(getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
if (savedInstanceState != null)
{
position = savedInstanceState.getInt("position");
}
v = inflater.inflate(R.layout.fragment_video_view, parent, false);
mVideoView = (VideoView) v.findViewById(R.id.fragmentVideoView);
mVideoView.setVideoPath(videoPath);
mVideoView.setMediaController(mMediaController);
mVideoView.setOnTouchListener(
new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent motionEvent)
{
if (mVideoView.isPlaying())
{
mVideoView.pause();
/*
Ok, so now you want to use that show(), preferrably without the int timeout
I didn't add it in myself but you should be able to handle it yourself
*/
return true;
}
else /* I changed it to else, change it to if else if you have something specific you want to deal with */
{
/*
I would use that hide method I linked here, then start the
video, I assume you know how to play the video yourself
*/
}
return false;
}
});
mVideoView.seekTo(position);
mVideoView.start();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
if (mVideoView != null)
{
savedInstanceState.putInt("position", mVideoView.getCurrentPosition());
}
mVideoView.pause();
}
}
他の方法を提供したのは、続行する方法によっては、将来の質問を妨げる場合と妨げない場合があるためです。