package com.ijoomer.plugins;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.VideoView;
import com.ijoomer.customviews.IjoomerTextView;
import com.ijoomer.media.player.FileId;
import com.ijoomer.media.player.PlaylistId;
import com.ijoomer.media.player.VideoId;
import com.ijoomer.media.player.YouTubeId;
import com.ijoomer.media.player.YouTubeUtility;
import java.util.ArrayList;
/**
* This Class Contains UnNormalizeFields PluginsYoutubeMediaPlayer.
*
* @author tasol
*
*/
public class PluginsYoutubeMediaPlayer extends Activity implements OnGestureListener {
protected IjoomerTextView mProgressMessage;
protected ProgressBar mProgressBar;
protected VideoView mVideoView;
protected Button btnNext;
protected Button btnPrevious;
private GestureDetector gDetector;
public static final String SCHEME_YOUTUBE_VIDEO = "ytv";
public static final String SCHEME_YOUTUBE_PLAYLIST = "ytpl";
public static final String SCHEME_FILE = "file";
public static final String SCHEME_MP4_VIDEO = "mp4";
static final String YOUTUBE_VIDEO_INFORMATION_URL = "http://www.youtube.com/get_video_info?&video_id=";
static final String YOUTUBE_PLAYLIST_ATOM_FEED_URL = "http://gdata.youtube.com/feeds/api/playlists/";
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
public final static String MSG_INIT = "com.keyes.video.msg.init";
protected String mMsgInit = "Initializing";
public final static String MSG_DETECT = "com.keyes.video.msg.detect";
protected String mMsgDetect = "Detecting Bandwidth";
public final static String MSG_PLAYLIST = "com.keyes.video.msg.playlist";
protected String mMsgPlaylist = "Determining Latest Video in YouTube Playlist";
public final static String MSG_TOKEN = "com.keyes.video.msg.token";
protected String mMsgToken = "Retrieving YouTube Video Token";
public final static String MSG_LO_BAND = "com.keyes.video.msg.loband";
protected String mMsgLowBand = "Buffering Low-bandwidth Video";
public final static String MSG_HI_BAND = "com.keyes.video.msg.hiband";
protected String mMsgHiBand = "Buffering High-bandwidth Video";
public final static String MSG_ERROR_TITLE = "com.keyes.video.msg.error.title";
protected String mMsgErrorTitle = "Communications Error";
public final static String MSG_ERROR_MSG = "com.keyes.video.msg.error.msg";
protected String mMsgError = "An error occurred during the retrieval of the video. This could be due to network issues or YouTube protocols. Please try again later.";
/**
* Background task on which all of the interaction with YouTube is done
*/
protected QueryYouTubeTask mQueryYouTubeTask;
YouTubeId lYouTubeId = null;
protected String mVideoId = null;
private ArrayList<String> IN_ID_ARRAY;
private int IN_INDEX;
/**
* Overrides methods
*/
@Override
protected void onCreate(Bundle pSavedInstanceState) {
super.onCreate(pSavedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setupView();
getIntenData();
extractMessages();
getWindow().setFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mProgressBar.bringToFront();
mProgressBar.setVisibility(View.VISIBLE);
mProgressMessage.setText(mMsgInit);
lYouTubeId = new VideoId(IN_ID_ARRAY.get(IN_INDEX));
mQueryYouTubeTask = (QueryYouTubeTask) new QueryYouTubeTask().execute(lYouTubeId);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
getNextVideo();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
getPreviousVideo();
}
return true;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gDetector.onTouchEvent(event);
}
@Override
protected void onDestroy() {
super.onDestroy();
YouTubeUtility.markVideoAsViewed(this, mVideoId);
if (mQueryYouTubeTask != null) {
mQueryYouTubeTask.cancel(true);
}
if (mVideoView != null) {
mVideoView.stopPlayback();
}
getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
this.mQueryYouTubeTask = null;
this.mVideoView = null;
}
/**
* Class methods
*/
/**
* This method used to show messages to display during video load and initialization.
*/
private void extractMessages() {
Intent lInvokingIntent = getIntent();
String lMsgInit = lInvokingIntent.getStringExtra(MSG_INIT);
if (lMsgInit != null) {
mMsgInit = lMsgInit;
}
String lMsgDetect = lInvokingIntent.getStringExtra(MSG_DETECT);
if (lMsgDetect != null) {
mMsgDetect = lMsgDetect;
}
String lMsgPlaylist = lInvokingIntent.getStringExtra(MSG_PLAYLIST);
if (lMsgPlaylist != null) {
mMsgPlaylist = lMsgPlaylist;
}
String lMsgToken = lInvokingIntent.getStringExtra(MSG_TOKEN);
if (lMsgToken != null) {
mMsgToken = lMsgToken;
}
String lMsgLoBand = lInvokingIntent.getStringExtra(MSG_LO_BAND);
if (lMsgLoBand != null) {
mMsgLowBand = lMsgLoBand;
}
String lMsgHiBand = lInvokingIntent.getStringExtra(MSG_HI_BAND);
if (lMsgHiBand != null) {
mMsgHiBand = lMsgHiBand;
}
String lMsgErrTitle = lInvokingIntent.getStringExtra(MSG_ERROR_TITLE);
if (lMsgErrTitle != null) {
mMsgErrorTitle = lMsgErrTitle;
}
String lMsgErrMsg = lInvokingIntent.getStringExtra(MSG_ERROR_MSG);
if (lMsgErrMsg != null) {
mMsgError = lMsgErrMsg;
}
}
/**
* This method used to Create the view in which the video will be rendered.
*/
private void setupView() {
gDetector = new GestureDetector(getBaseContext(),this);
LinearLayout lLinLayout = new LinearLayout(this);
lLinLayout.setId(1);
lLinLayout.setOrientation(LinearLayout.VERTICAL);
lLinLayout.setGravity(Gravity.CENTER);
lLinLayout.setBackgroundColor(Color.BLACK);
LayoutParams lLinLayoutParms = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
lLinLayout.setLayoutParams(lLinLayoutParms);
this.setContentView(lLinLayout);
RelativeLayout lRelLayout = new RelativeLayout(this);
lRelLayout.setId(2);
lRelLayout.setGravity(Gravity.CENTER);
lRelLayout.setBackgroundColor(Color.BLACK);
android.widget.RelativeLayout.LayoutParams lRelLayoutParms = new android.widget.RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
lRelLayout.setLayoutParams(lRelLayoutParms);
lLinLayout.addView(lRelLayout);
mVideoView = new VideoView(this);
mVideoView.setId(3);
android.widget.RelativeLayout.LayoutParams lVidViewLayoutParams = new android.widget.RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lVidViewLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
mVideoView.setLayoutParams(lVidViewLayoutParams);
lRelLayout.addView(mVideoView);
mProgressBar = new ProgressBar(this);
mProgressBar.setIndeterminate(true);
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setEnabled(true);
mProgressBar.setId(4);
android.widget.RelativeLayout.LayoutParams lProgressBarLayoutParms = new android.widget.RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lProgressBarLayoutParms.addRule(RelativeLayout.CENTER_IN_PARENT);
mProgressBar.setLayoutParams(lProgressBarLayoutParms);
lRelLayout.addView(mProgressBar);
mProgressMessage = new IjoomerTextView(this);
mProgressMessage.setId(5);
android.widget.RelativeLayout.LayoutParams lProgressMsgLayoutParms = new android.widget.RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lProgressMsgLayoutParms.addRule(RelativeLayout.CENTER_HORIZONTAL);
lProgressMsgLayoutParms.addRule(RelativeLayout.BELOW, 4);
mProgressMessage.setLayoutParams(lProgressMsgLayoutParms);
mProgressMessage.setTextColor(Color.LTGRAY);
mProgressMessage.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
mProgressMessage.setText("...");
lRelLayout.addView(mProgressMessage);
}
/**
* This method used to update progress.
* @param pProgressMsg represented progress message
*/
public void updateProgress(String pProgressMsg) {
try {
mProgressMessage.setText(pProgressMsg);
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), "Error updating video status!", e);
}
}
/**
* This method used to update progress info.
* @author tasol
*
*/
private class ProgressUpdateInfo {
public String mMsg;
public ProgressUpdateInfo(String pMsg) {
mMsg = pMsg;
}
}
/**
* This method used to Task to figure out details by calling out to YouTube GData API. We only
* use public methods that don't require authentication.
*/
private class QueryYouTubeTask extends AsyncTask<YouTubeId, ProgressUpdateInfo, Uri> {
private boolean mShowedError = false;
@Override
protected Uri doInBackground(YouTubeId... pParams) {
if (pParams[0] instanceof FileId) {
return Uri.parse(pParams[0].getId());
} else {
String lUriStr = null;
String lYouTubeFmtQuality = "17"; // 3gpp medium quality, which
// should be fast enough to
// view over EDGE connection
String lYouTubeVideoId = null;
if (isCancelled())
return null;
try {
publishProgress(new ProgressUpdateInfo(mMsgDetect));
WifiManager lWifiManager = (WifiManager) PluginsYoutubeMediaPlayer.this.getSystemService(Context.WIFI_SERVICE);
TelephonyManager lTelephonyManager = (TelephonyManager) PluginsYoutubeMediaPlayer.this.getSystemService(Context.TELEPHONY_SERVICE);
// //////////////////////////
// if we have a fast connection (wifi or 3g), then we'll get
// a high quality YouTube video
if ((lWifiManager.isWifiEnabled() && lWifiManager.getConnectionInfo() != null && lWifiManager.getConnectionInfo().getIpAddress() != 0)
|| ((lTelephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS ||
/*
* icky... using literals to make backwards
* compatible with 1.5 and 1.6
*/
lTelephonyManager.getNetworkType() == 9 /* HSUPA */|| lTelephonyManager.getNetworkType() == 10 /* HSPA */|| lTelephonyManager.getNetworkType() == 8 /* HSDPA */
|| lTelephonyManager.getNetworkType() == 5 /* EVDO_0 */|| lTelephonyManager.getNetworkType() == 6 /*
* EVDO
* A
*/)
&& lTelephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED)) {
lYouTubeFmtQuality = "18";
}
// /////////////////////////////////
// if the intent is to show a playlist, get the latest video
// id from the playlist, otherwise the video
// id was explicitly declared.
if (pParams[0] instanceof PlaylistId) {
publishProgress(new ProgressUpdateInfo(mMsgPlaylist));
lYouTubeVideoId = YouTubeUtility.queryLatestPlaylistVideo((PlaylistId) pParams[0]);
} else if (pParams[0] instanceof VideoId) {
lYouTubeVideoId = pParams[0].getId();
}
mVideoId = lYouTubeVideoId;
publishProgress(new ProgressUpdateInfo(mMsgToken));
if (isCancelled())
return null;
// //////////////////////////////////
// calculate the actual URL of the video, encoded with
// proper YouTube token
lUriStr = YouTubeUtility.calculateYouTubeUrl(lYouTubeFmtQuality, true, lYouTubeVideoId);
if (isCancelled())
return null;
if (lYouTubeFmtQuality.equals("17")) {
publishProgress(new ProgressUpdateInfo(mMsgLowBand));
} else {
publishProgress(new ProgressUpdateInfo(mMsgHiBand));
}
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), "Error occurred while retrieving information from YouTube.", e);
}
if (lUriStr != null) {
return Uri.parse(lUriStr);
} else {
return null;
}
}
}
@Override
protected void onPostExecute(Uri pResult) {
super.onPostExecute(pResult);
try {
if (isCancelled())
return;
if (pResult == null) {
throw new RuntimeException("Invalid NULL Url.");
}
mVideoView.setVideoURI(pResult);
if (isCancelled())
return;
mVideoView.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer pMp) {
if (isCancelled())
return;
if (++IN_INDEX < IN_ID_ARRAY.size()) {
lYouTubeId = new VideoId(IN_ID_ARRAY.get(IN_INDEX));
PluginsYoutubeMediaPlayer.this.mProgressBar.setVisibility(View.VISIBLE);
PluginsYoutubeMediaPlayer.this.mProgressMessage.setVisibility(View.VISIBLE);
mQueryYouTubeTask = (QueryYouTubeTask) new QueryYouTubeTask().execute(lYouTubeId);
}
// ExtraYoutubeMediaPlayer.this.finish();
}
});
if (isCancelled())
return;
final MediaController lMediaController = new MediaController(PluginsYoutubeMediaPlayer.this);
lMediaController.setAnchorView(mVideoView);
mVideoView.setMediaController(lMediaController);
Bundle bundle = getIntent().getExtras();
boolean showControllerOnStartup = false;
if (!(bundle == null))
showControllerOnStartup = bundle.getBoolean("show_controller_on_startup", false);
if (showControllerOnStartup)
lMediaController.show(0);
// mVideoView.setKeepScreenOn(true);
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer pMp) {
if (isCancelled())
return;
PluginsYoutubeMediaPlayer.this.mProgressBar.setVisibility(View.GONE);
PluginsYoutubeMediaPlayer.this.mProgressMessage.setVisibility(View.GONE);
mVideoView.start();
}
});
if (isCancelled())
return;
mVideoView.requestFocus();
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), "Error playing video!", e);
if (!mShowedError) {
showErrorAlert();
}
}
}
private void showErrorAlert() {
try {
Builder lBuilder = new AlertDialog.Builder(PluginsYoutubeMediaPlayer.this);
lBuilder.setTitle(mMsgErrorTitle);
lBuilder.setCancelable(false);
lBuilder.setMessage(mMsgError);
lBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface pDialog, int pWhich) {
finish();
}
});
AlertDialog lDialog = lBuilder.create();
lDialog.show();
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), "Problem showing error dialog.", e);
}
}
@Override
protected void onProgressUpdate(ProgressUpdateInfo... pValues) {
super.onProgressUpdate(pValues);
PluginsYoutubeMediaPlayer.this.updateProgress(pValues[0].mMsg);
}
}
/**
* This method used to get intent data.
*/
public void getIntenData() {
IN_ID_ARRAY = (ArrayList<String>) getIntent().getStringArrayListExtra("IN_ID_ARRAY");
IN_INDEX = getIntent().getIntExtra("IN_INDEX", 0);
Log.e("size", IN_ID_ARRAY.size() + "");
}
/**
* This method used to get next video.
*/
public void getNextVideo() {
if (++IN_INDEX < IN_ID_ARRAY.size()) {
lYouTubeId = new VideoId(IN_ID_ARRAY.get(IN_INDEX));
stopPlayer();
PluginsYoutubeMediaPlayer.this.mProgressBar.setVisibility(View.VISIBLE);
PluginsYoutubeMediaPlayer.this.mProgressMessage.setVisibility(View.VISIBLE);
mQueryYouTubeTask = (QueryYouTubeTask) new QueryYouTubeTask().execute(lYouTubeId);
} else {
IN_INDEX = IN_ID_ARRAY.size() - 1;
}
}
/**
* This method used to get previous video.
*/
public void getPreviousVideo() {
if (--IN_INDEX >= 0) {
lYouTubeId = new VideoId(IN_ID_ARRAY.get(IN_INDEX));
stopPlayer();
PluginsYoutubeMediaPlayer.this.mProgressBar.setVisibility(View.VISIBLE);
PluginsYoutubeMediaPlayer.this.mProgressMessage.setVisibility(View.VISIBLE);
mQueryYouTubeTask = (QueryYouTubeTask) new QueryYouTubeTask().execute(lYouTubeId);
} else {
IN_INDEX = 0;
}
}
/**
* This method used to stop player.
*/
public void stopPlayer() {
if (mVideoView != null) {
if (mVideoView.isPlaying()) {
mVideoView.pause();
}
}
}
}