You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
8.3 KiB
243 lines
8.3 KiB
/*
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.camera;
|
|
|
|
import com.android.gallery.R;
|
|
|
|
import android.app.AlertDialog;
|
|
import android.content.ContentResolver;
|
|
import android.content.ContentValues;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.DialogInterface.OnCancelListener;
|
|
import android.content.DialogInterface.OnClickListener;
|
|
import android.database.Cursor;
|
|
import android.database.sqlite.SQLiteException;
|
|
import android.media.MediaPlayer;
|
|
import android.net.Uri;
|
|
import android.os.Handler;
|
|
import android.provider.MediaStore;
|
|
import android.provider.MediaStore.Video;
|
|
import android.view.View;
|
|
import android.widget.MediaController;
|
|
import android.widget.VideoView;
|
|
|
|
public class MovieViewControl implements MediaPlayer.OnErrorListener,
|
|
MediaPlayer.OnCompletionListener {
|
|
|
|
@SuppressWarnings("unused")
|
|
private static final String TAG = "MovieViewControl";
|
|
|
|
private static final int ONE_MINUTE = 60 * 1000;
|
|
private static final int TWO_MINUTES = 2 * ONE_MINUTE;
|
|
private static final int FIVE_MINUTES = 5 * ONE_MINUTE;
|
|
|
|
// Copied from MediaPlaybackService in the Music Player app. Should be
|
|
// public, but isn't.
|
|
private static final String SERVICECMD =
|
|
"com.android.music.musicservicecommand";
|
|
private static final String CMDNAME = "command";
|
|
private static final String CMDPAUSE = "pause";
|
|
|
|
private final VideoView mVideoView;
|
|
private final View mProgressView;
|
|
private final Uri mUri;
|
|
private final ContentResolver mContentResolver;
|
|
|
|
// State maintained for proper onPause/OnResume behaviour.
|
|
private int mPositionWhenPaused = -1;
|
|
private boolean mWasPlayingWhenPaused = false;
|
|
private MediaController mMediaController;
|
|
|
|
Handler mHandler = new Handler();
|
|
|
|
Runnable mPlayingChecker = new Runnable() {
|
|
public void run() {
|
|
if (mVideoView.isPlaying()) {
|
|
mProgressView.setVisibility(View.GONE);
|
|
} else {
|
|
mHandler.postDelayed(mPlayingChecker, 250);
|
|
}
|
|
}
|
|
};
|
|
|
|
public MovieViewControl(View rootView, Context context, Uri videoUri) {
|
|
mContentResolver = context.getContentResolver();
|
|
mVideoView = (VideoView) rootView.findViewById(R.id.surface_view);
|
|
mProgressView = rootView.findViewById(R.id.progress_indicator);
|
|
|
|
mUri = videoUri;
|
|
|
|
// For streams that we expect to be slow to start up, show a
|
|
// progress spinner until playback starts.
|
|
String scheme = mUri.getScheme();
|
|
if ("http".equalsIgnoreCase(scheme)
|
|
|| "rtsp".equalsIgnoreCase(scheme)) {
|
|
mHandler.postDelayed(mPlayingChecker, 250);
|
|
} else {
|
|
mProgressView.setVisibility(View.GONE);
|
|
}
|
|
|
|
mVideoView.setOnErrorListener(this);
|
|
mVideoView.setOnCompletionListener(this);
|
|
mVideoView.setVideoURI(mUri);
|
|
mMediaController = new MediaController(context);
|
|
mVideoView.setMediaController(mMediaController);
|
|
|
|
// make the video view handle keys for seeking and pausing
|
|
mVideoView.requestFocus();
|
|
|
|
Intent i = new Intent(SERVICECMD);
|
|
i.putExtra(CMDNAME, CMDPAUSE);
|
|
context.sendBroadcast(i);
|
|
|
|
final Integer bookmark = getBookmark();
|
|
if (bookmark != null) {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
builder.setTitle(R.string.resume_playing_title);
|
|
builder.setMessage(String.format(
|
|
context.getString(R.string.resume_playing_message),
|
|
MenuHelper.formatDuration(context, bookmark)));
|
|
builder.setOnCancelListener(new OnCancelListener() {
|
|
public void onCancel(DialogInterface dialog) {
|
|
onCompletion();
|
|
}});
|
|
builder.setPositiveButton(R.string.resume_playing_resume,
|
|
new OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
mVideoView.seekTo(bookmark);
|
|
mVideoView.start();
|
|
}});
|
|
builder.setNegativeButton(R.string.resume_playing_restart,
|
|
new OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
mVideoView.start();
|
|
}});
|
|
builder.show();
|
|
} else {
|
|
mVideoView.start();
|
|
}
|
|
}
|
|
|
|
private static boolean uriSupportsBookmarks(Uri uri) {
|
|
String scheme = uri.getScheme();
|
|
String authority = uri.getAuthority();
|
|
return ("content".equalsIgnoreCase(scheme)
|
|
&& MediaStore.AUTHORITY.equalsIgnoreCase(authority));
|
|
}
|
|
|
|
private Integer getBookmark() {
|
|
if (!uriSupportsBookmarks(mUri)) {
|
|
return null;
|
|
}
|
|
|
|
String[] projection = new String[] {
|
|
Video.VideoColumns.DURATION,
|
|
Video.VideoColumns.BOOKMARK};
|
|
|
|
try {
|
|
Cursor cursor = mContentResolver.query(
|
|
mUri, projection, null, null, null);
|
|
if (cursor != null) {
|
|
try {
|
|
if (cursor.moveToFirst()) {
|
|
int duration = getCursorInteger(cursor, 0);
|
|
int bookmark = getCursorInteger(cursor, 1);
|
|
if ((bookmark < TWO_MINUTES)
|
|
|| (duration < FIVE_MINUTES)
|
|
|| (bookmark > (duration - ONE_MINUTE))) {
|
|
return null;
|
|
}
|
|
return Integer.valueOf(bookmark);
|
|
}
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
}
|
|
} catch (SQLiteException e) {
|
|
// ignore
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static int getCursorInteger(Cursor cursor, int index) {
|
|
try {
|
|
return cursor.getInt(index);
|
|
} catch (SQLiteException e) {
|
|
return 0;
|
|
} catch (NumberFormatException e) {
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
private void setBookmark(int bookmark) {
|
|
if (!uriSupportsBookmarks(mUri)) {
|
|
return;
|
|
}
|
|
|
|
ContentValues values = new ContentValues();
|
|
values.put(Video.VideoColumns.BOOKMARK, Integer.toString(bookmark));
|
|
try {
|
|
mContentResolver.update(mUri, values, null, null);
|
|
} catch (SecurityException ex) {
|
|
// Ignore, can happen if we try to set the bookmark on a read-only
|
|
// resource such as a video attached to GMail.
|
|
} catch (SQLiteException e) {
|
|
// ignore. can happen if the content doesn't support a bookmark
|
|
// column.
|
|
} catch (UnsupportedOperationException e) {
|
|
// ignore. can happen if the external volume is already detached.
|
|
}
|
|
}
|
|
|
|
public void onPause() {
|
|
mHandler.removeCallbacksAndMessages(null);
|
|
setBookmark(mVideoView.getCurrentPosition());
|
|
|
|
mPositionWhenPaused = mVideoView.getCurrentPosition();
|
|
mWasPlayingWhenPaused = mVideoView.isPlaying();
|
|
mVideoView.stopPlayback();
|
|
}
|
|
|
|
public void onResume() {
|
|
if (mPositionWhenPaused >= 0) {
|
|
mVideoView.setVideoURI(mUri);
|
|
mVideoView.seekTo(mPositionWhenPaused);
|
|
mPositionWhenPaused = -1;
|
|
if (mWasPlayingWhenPaused) {
|
|
mMediaController.show(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean onError(MediaPlayer player, int arg1, int arg2) {
|
|
mHandler.removeCallbacksAndMessages(null);
|
|
mProgressView.setVisibility(View.GONE);
|
|
return false;
|
|
}
|
|
|
|
public void onCompletion(MediaPlayer mp) {
|
|
onCompletion();
|
|
}
|
|
|
|
public void onCompletion() {
|
|
}
|
|
}
|