初始化
@@ -0,0 +1,13 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="fm.jiecao.jcvideoplayer_lib">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,234 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>统一管理MediaPlayer的地方,只有一个mediaPlayer实例,那么不会有多个视频同时播放,也节省资源。</p>
|
||||
* <p>Unified management MediaPlayer place, there is only one MediaPlayer instance, then there will be no more video broadcast at the same time, also save resources.</p>
|
||||
* Created by Nathen
|
||||
* On 2015/11/30 15:39
|
||||
*/
|
||||
public class JCMediaManager implements TextureView.SurfaceTextureListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener, MediaPlayer.OnVideoSizeChangedListener {
|
||||
public static String TAG = "JieCaoVideoPlayer";
|
||||
|
||||
private static JCMediaManager JCMediaManager;
|
||||
public static JCResizeTextureView textureView;
|
||||
public static SurfaceTexture savedSurfaceTexture;
|
||||
public MediaPlayer mediaPlayer = new MediaPlayer();
|
||||
public static String CURRENT_PLAYING_URL;
|
||||
public static boolean CURRENT_PLING_LOOP;
|
||||
public static Map<String, String> MAP_HEADER_DATA;
|
||||
public int currentVideoWidth = 0;
|
||||
public int currentVideoHeight = 0;
|
||||
|
||||
public static final int HANDLER_PREPARE = 0;
|
||||
public static final int HANDLER_RELEASE = 2;
|
||||
HandlerThread mMediaHandlerThread;
|
||||
MediaHandler mMediaHandler;
|
||||
Handler mainThreadHandler;
|
||||
|
||||
public static JCMediaManager instance() {
|
||||
if (JCMediaManager == null) {
|
||||
JCMediaManager = new JCMediaManager();
|
||||
}
|
||||
return JCMediaManager;
|
||||
}
|
||||
|
||||
public JCMediaManager() {
|
||||
mMediaHandlerThread = new HandlerThread(TAG);
|
||||
mMediaHandlerThread.start();
|
||||
mMediaHandler = new MediaHandler((mMediaHandlerThread.getLooper()));
|
||||
mainThreadHandler = new Handler();
|
||||
}
|
||||
|
||||
public Point getVideoSize() {
|
||||
if (currentVideoWidth != 0 && currentVideoHeight != 0) {
|
||||
return new Point(currentVideoWidth, currentVideoHeight);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class MediaHandler extends Handler {
|
||||
public MediaHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
switch (msg.what) {
|
||||
case HANDLER_PREPARE:
|
||||
try {
|
||||
currentVideoWidth = 0;
|
||||
currentVideoHeight = 0;
|
||||
mediaPlayer.release();
|
||||
mediaPlayer = new MediaPlayer();
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
Class<MediaPlayer> clazz = MediaPlayer.class;
|
||||
Method method = clazz.getDeclaredMethod("setDataSource", String.class, Map.class);
|
||||
method.invoke(mediaPlayer, CURRENT_PLAYING_URL, MAP_HEADER_DATA);
|
||||
mediaPlayer.setLooping(CURRENT_PLING_LOOP);
|
||||
mediaPlayer.setOnPreparedListener(JCMediaManager.this);
|
||||
mediaPlayer.setOnCompletionListener(JCMediaManager.this);
|
||||
mediaPlayer.setOnBufferingUpdateListener(JCMediaManager.this);
|
||||
mediaPlayer.setScreenOnWhilePlaying(true);
|
||||
mediaPlayer.setOnSeekCompleteListener(JCMediaManager.this);
|
||||
mediaPlayer.setOnErrorListener(JCMediaManager.this);
|
||||
mediaPlayer.setOnInfoListener(JCMediaManager.this);
|
||||
mediaPlayer.setOnVideoSizeChangedListener(JCMediaManager.this);
|
||||
mediaPlayer.prepareAsync();
|
||||
mediaPlayer.setSurface(new Surface(savedSurfaceTexture));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case HANDLER_RELEASE:
|
||||
mediaPlayer.release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void prepare() {
|
||||
releaseMediaPlayer();
|
||||
Message msg = new Message();
|
||||
msg.what = HANDLER_PREPARE;
|
||||
mMediaHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void releaseMediaPlayer() {
|
||||
Message msg = new Message();
|
||||
msg.what = HANDLER_RELEASE;
|
||||
mMediaHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
|
||||
Log.i(TAG, "onSurfaceTextureAvailable [" + this.hashCode() + "] ");
|
||||
if (savedSurfaceTexture == null) {
|
||||
savedSurfaceTexture = surfaceTexture;
|
||||
prepare();
|
||||
} else {
|
||||
textureView.setSurfaceTexture(savedSurfaceTexture);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
|
||||
// 如果SurfaceTexture还没有更新Image,则记录SizeChanged事件,否则忽略
|
||||
Log.i(TAG, "onSurfaceTextureSizeChanged [" + this.hashCode() + "] ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
|
||||
return savedSurfaceTexture == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
mediaPlayer.start();
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().onPrepared();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().onAutoCompletion();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(MediaPlayer mp, final int percent) {
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().setBufferProgress(percent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekComplete(MediaPlayer mp) {
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().onSeekComplete();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, final int what, final int extra) {
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().onError(what, extra);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInfo(MediaPlayer mp, final int what, final int extra) {
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().onInfo(what, extra);
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
|
||||
currentVideoWidth = width;
|
||||
currentVideoHeight = height;
|
||||
mainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().onVideoSizeChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.TextureView;
|
||||
|
||||
/**
|
||||
* <p>参照Android系统的VideoView的onMeasure方法
|
||||
* <br>注意!relativelayout中无法全屏,要嵌套一个linearlayout</p>
|
||||
* <p>Referring Android system Video View of onMeasure method
|
||||
* <br>NOTE! Can not fullscreen relativelayout, to nest a linearlayout</p>
|
||||
* Created by Nathen
|
||||
* On 2016/06/02 00:01
|
||||
*/
|
||||
public class JCResizeTextureView extends TextureView {
|
||||
protected static final String TAG = "JCResizeTextureView";
|
||||
|
||||
// x as width, y as height
|
||||
protected Point mVideoSize;
|
||||
|
||||
public JCResizeTextureView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public JCResizeTextureView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mVideoSize = new Point(0, 0);
|
||||
}
|
||||
|
||||
public void setVideoSize(Point videoSize) {
|
||||
if (videoSize != null && !mVideoSize.equals(videoSize)) {
|
||||
this.mVideoSize = videoSize;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotation(float rotation) {
|
||||
if (rotation != getRotation()) {
|
||||
super.setRotation(rotation);
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
Log.i(TAG, "onMeasure " + " [" + this.hashCode() + "] ");
|
||||
int viewRotation = (int) getRotation();
|
||||
int videoWidth = mVideoSize.x;
|
||||
int videoHeight = mVideoSize.y;
|
||||
Log.i(TAG, "videoWidth = " + videoWidth + ", " + "videoHeight = " + videoHeight);
|
||||
Log.i(TAG, "viewRotation = " + viewRotation);
|
||||
|
||||
// 如果判断成立,则说明显示的TextureView和本身的位置是有90度的旋转的,所以需要交换宽高参数。
|
||||
if (viewRotation == 90 || viewRotation == 270) {
|
||||
int tempMeasureSpec = widthMeasureSpec;
|
||||
widthMeasureSpec = heightMeasureSpec;
|
||||
heightMeasureSpec = tempMeasureSpec;
|
||||
}
|
||||
|
||||
int width = getDefaultSize(videoWidth, widthMeasureSpec);
|
||||
int height = getDefaultSize(videoHeight, heightMeasureSpec);
|
||||
if (videoWidth > 0 && videoHeight > 0) {
|
||||
|
||||
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
Log.i(TAG, "widthMeasureSpec [" + MeasureSpec.toString(widthMeasureSpec) + "]");
|
||||
Log.i(TAG, "heightMeasureSpec [" + MeasureSpec.toString(heightMeasureSpec) + "]");
|
||||
|
||||
if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
|
||||
// the size is fixed
|
||||
width = widthSpecSize;
|
||||
height = heightSpecSize;
|
||||
// for compatibility, we adjust size based on aspect ratio
|
||||
if (videoWidth * height < width * videoHeight) {
|
||||
width = height * videoWidth / videoHeight;
|
||||
} else if (videoWidth * height > width * videoHeight) {
|
||||
height = width * videoHeight / videoWidth;
|
||||
}
|
||||
} else if (widthSpecMode == MeasureSpec.EXACTLY) {
|
||||
// only the width is fixed, adjust the height to match aspect ratio if possible
|
||||
width = widthSpecSize;
|
||||
height = width * videoHeight / videoWidth;
|
||||
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
|
||||
// couldn't match aspect ratio within the constraints
|
||||
height = heightSpecSize;
|
||||
width = height * videoWidth / videoHeight;
|
||||
}
|
||||
} else if (heightSpecMode == MeasureSpec.EXACTLY) {
|
||||
// only the height is fixed, adjust the width to match aspect ratio if possible
|
||||
height = heightSpecSize;
|
||||
width = height * videoWidth / videoHeight;
|
||||
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
|
||||
// couldn't match aspect ratio within the constraints
|
||||
width = widthSpecSize;
|
||||
height = width * videoHeight / videoWidth;
|
||||
}
|
||||
} else {
|
||||
// neither the width nor the height are fixed, try to use actual video size
|
||||
width = videoWidth;
|
||||
height = videoHeight;
|
||||
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
|
||||
// too tall, decrease both width and height
|
||||
height = heightSpecSize;
|
||||
width = height * videoWidth / videoHeight;
|
||||
}
|
||||
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
|
||||
// too wide, decrease both width and height
|
||||
width = widthSpecSize;
|
||||
height = width * videoHeight / videoWidth;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no size yet, just adopt the given spec sizes
|
||||
}
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
/**
|
||||
* Created by Nathen
|
||||
* On 2016/04/04 22:13
|
||||
*/
|
||||
public interface JCUserAction {
|
||||
|
||||
int ON_CLICK_START_ICON = 0;
|
||||
int ON_CLICK_START_ERROR = 1;
|
||||
int ON_CLICK_START_AUTO_COMPLETE = 2;
|
||||
|
||||
int ON_CLICK_PAUSE = 3;
|
||||
int ON_CLICK_RESUME = 4;
|
||||
int ON_SEEK_POSITION = 5;
|
||||
int ON_AUTO_COMPLETE = 6;
|
||||
|
||||
int ON_ENTER_FULLSCREEN = 7;
|
||||
int ON_QUIT_FULLSCREEN = 8;
|
||||
int ON_ENTER_TINYSCREEN = 9;
|
||||
int ON_QUIT_TINYSCREEN = 10;
|
||||
|
||||
|
||||
int ON_TOUCH_SCREEN_SEEK_VOLUME = 11;
|
||||
int ON_TOUCH_SCREEN_SEEK_POSITION = 12;
|
||||
|
||||
void onEvent(int type, String url, int screen, Object... objects);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
/**
|
||||
* Created by Nathen
|
||||
* On 2016/04/26 20:53
|
||||
*/
|
||||
public interface JCUserActionStandard extends JCUserAction {
|
||||
|
||||
int ON_CLICK_START_THUMB = 101;
|
||||
int ON_CLICK_BLANK = 102;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.view.ContextThemeWrapper;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Formatter;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by Nathen
|
||||
* On 2016/02/21 12:25
|
||||
*/
|
||||
public class JCUtils {
|
||||
|
||||
public static String stringForTime(int timeMs) {
|
||||
if (timeMs <= 0 || timeMs >= 24 * 60 * 60 * 1000) {
|
||||
return "00:00";
|
||||
}
|
||||
int totalSeconds = timeMs / 1000;
|
||||
int seconds = totalSeconds % 60;
|
||||
int minutes = (totalSeconds / 60) % 60;
|
||||
int hours = totalSeconds / 3600;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Formatter mFormatter = new Formatter(stringBuilder, Locale.getDefault());
|
||||
if (hours > 0) {
|
||||
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
|
||||
} else {
|
||||
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method requires the caller to hold the permission ACCESS_NETWORK_STATE.
|
||||
*
|
||||
* @param context a application context
|
||||
* @return if wifi is connected,return true
|
||||
*/
|
||||
public static boolean isWifiConnected(Context context) {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
|
||||
return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get activity from context object
|
||||
*
|
||||
* @param context something
|
||||
* @return object of Activity or null if it is not Activity
|
||||
*/
|
||||
public static Activity scanForActivity(Context context) {
|
||||
if (context == null) return null;
|
||||
|
||||
if (context instanceof Activity) {
|
||||
return (Activity) context;
|
||||
} else if (context instanceof ContextWrapper) {
|
||||
return scanForActivity(((ContextWrapper) context).getBaseContext());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AppCompatActivity from context
|
||||
*
|
||||
* @param context
|
||||
* @return AppCompatActivity if it's not null
|
||||
*/
|
||||
public static AppCompatActivity getAppCompActivity(Context context) {
|
||||
if (context == null) return null;
|
||||
if (context instanceof AppCompatActivity) {
|
||||
return (AppCompatActivity) context;
|
||||
} else if (context instanceof ContextThemeWrapper) {
|
||||
return getAppCompActivity(((ContextThemeWrapper) context).getBaseContext());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int dip2px(Context context, float dpValue) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
public static void saveProgress(Context context, String url, int progress) {
|
||||
if (!JCVideoPlayer.SAVE_PROGRESS) return;
|
||||
SharedPreferences spn = context.getSharedPreferences("JCVD_PROGRESS",
|
||||
Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = spn.edit();
|
||||
editor.putInt(url, progress);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static int getSavedProgress(Context context, String url) {
|
||||
if (!JCVideoPlayer.SAVE_PROGRESS) return 0;
|
||||
SharedPreferences spn;
|
||||
spn = context.getSharedPreferences("JCVD_PROGRESS",
|
||||
Context.MODE_PRIVATE);
|
||||
return spn.getInt(url, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* if url == null, clear all progress
|
||||
*
|
||||
* @param context
|
||||
* @param url if url!=null clear this url progress
|
||||
*/
|
||||
public static void clearSavedProgress(Context context, String url) {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
SharedPreferences spn = context.getSharedPreferences("JCVD_PROGRESS",
|
||||
Context.MODE_PRIVATE);
|
||||
spn.edit().clear().apply();
|
||||
} else {
|
||||
SharedPreferences spn = context.getSharedPreferences("JCVD_PROGRESS",
|
||||
Context.MODE_PRIVATE);
|
||||
spn.edit().putInt(url, 0).apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,954 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Created by Nathen on 16/7/30.
|
||||
*/
|
||||
public abstract class JCVideoPlayer extends FrameLayout implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, View.OnTouchListener {
|
||||
|
||||
public static final String TAG = "JieCaoVideoPlayer";
|
||||
|
||||
public static boolean ACTION_BAR_EXIST = true;
|
||||
public static boolean TOOL_BAR_EXIST = true;
|
||||
public static int FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
|
||||
public static int NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
||||
public static boolean SAVE_PROGRESS = true;
|
||||
|
||||
public static boolean WIFI_TIP_DIALOG_SHOWED = false;
|
||||
|
||||
public static final int FULLSCREEN_ID = 33797;
|
||||
public static final int TINY_ID = 33798;
|
||||
public static final int THRESHOLD = 80;
|
||||
public static final int FULL_SCREEN_NORMAL_DELAY = 300;
|
||||
public static long CLICK_QUIT_FULLSCREEN_TIME = 0;
|
||||
|
||||
public static final int SCREEN_LAYOUT_NORMAL = 0;
|
||||
public static final int SCREEN_LAYOUT_LIST = 1;
|
||||
public static final int SCREEN_WINDOW_FULLSCREEN = 2;
|
||||
public static final int SCREEN_WINDOW_TINY = 3;
|
||||
|
||||
public static final int CURRENT_STATE_NORMAL = 0;
|
||||
public static final int CURRENT_STATE_PREPARING = 1;
|
||||
public static final int CURRENT_STATE_PLAYING = 2;
|
||||
public static final int CURRENT_STATE_PLAYING_BUFFERING_START = 3;
|
||||
public static final int CURRENT_STATE_PAUSE = 5;
|
||||
public static final int CURRENT_STATE_AUTO_COMPLETE = 6;
|
||||
public static final int CURRENT_STATE_ERROR = 7;
|
||||
|
||||
public static int BACKUP_PLAYING_BUFFERING_STATE = -1;
|
||||
|
||||
public int currentState = -1;
|
||||
public int currentScreen = -1;
|
||||
public boolean loop = false;
|
||||
public Map<String, String> headData;
|
||||
|
||||
public String url = "";
|
||||
public Object[] objects = null;
|
||||
public int seekToInAdvance = 0;
|
||||
|
||||
public ImageView startButton;
|
||||
public SeekBar progressBar;
|
||||
public ImageView fullscreenButton;
|
||||
public TextView currentTimeTextView, totalTimeTextView;
|
||||
public ViewGroup textureViewContainer;
|
||||
public ViewGroup topContainer, bottomContainer;
|
||||
|
||||
protected static JCUserAction JC_USER_EVENT;
|
||||
protected static Timer UPDATE_PROGRESS_TIMER;
|
||||
|
||||
protected int mScreenWidth;
|
||||
protected int mScreenHeight;
|
||||
protected AudioManager mAudioManager;
|
||||
protected Handler mHandler;
|
||||
protected ProgressTimerTask mProgressTimerTask;
|
||||
|
||||
protected boolean mTouchingProgressBar;
|
||||
protected float mDownX;
|
||||
protected float mDownY;
|
||||
protected boolean mChangeVolume;
|
||||
protected boolean mChangePosition;
|
||||
protected boolean mChangeBrightness;
|
||||
protected int mGestureDownPosition;
|
||||
protected int mGestureDownVolume;
|
||||
protected float mGestureDownBrightness;
|
||||
protected int mSeekTimePosition;
|
||||
|
||||
public JCVideoPlayer(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public JCVideoPlayer(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public void init(Context context) {
|
||||
View.inflate(context, getLayoutId(), this);
|
||||
startButton = (ImageView) findViewById(R.id.start);
|
||||
fullscreenButton = (ImageView) findViewById(R.id.fullscreen);
|
||||
progressBar = (SeekBar) findViewById(R.id.bottom_seek_progress);
|
||||
currentTimeTextView = (TextView) findViewById(R.id.current);
|
||||
totalTimeTextView = (TextView) findViewById(R.id.total);
|
||||
bottomContainer = (ViewGroup) findViewById(R.id.layout_bottom);
|
||||
textureViewContainer = (ViewGroup) findViewById(R.id.surface_container);
|
||||
topContainer = (ViewGroup) findViewById(R.id.layout_top);
|
||||
|
||||
startButton.setOnClickListener(this);
|
||||
fullscreenButton.setOnClickListener(this);
|
||||
progressBar.setOnSeekBarChangeListener(this);
|
||||
bottomContainer.setOnClickListener(this);
|
||||
textureViewContainer.setOnClickListener(this);
|
||||
textureViewContainer.setOnTouchListener(this);
|
||||
|
||||
mScreenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
|
||||
mScreenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
mHandler = new Handler();
|
||||
}
|
||||
|
||||
public void setUp(String url, int screen, Object... objects) {
|
||||
if (!TextUtils.isEmpty(this.url) && TextUtils.equals(this.url, url)) {
|
||||
return;
|
||||
}
|
||||
this.url = url;
|
||||
this.objects = objects;
|
||||
this.currentScreen = screen;
|
||||
this.headData = null;
|
||||
setUiWitStateAndScreen(CURRENT_STATE_NORMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.start) {
|
||||
Log.i(TAG, "onClick start [" + this.hashCode() + "] ");
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
Toast.makeText(getContext(), getResources().getString(R.string.no_url), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (currentState == CURRENT_STATE_NORMAL || currentState == CURRENT_STATE_ERROR) {
|
||||
if (!url.startsWith("file") && !JCUtils.isWifiConnected(getContext()) && !WIFI_TIP_DIALOG_SHOWED) {
|
||||
showWifiDialog();
|
||||
return;
|
||||
}
|
||||
prepareMediaPlayer();
|
||||
onEvent(currentState != CURRENT_STATE_ERROR ? JCUserAction.ON_CLICK_START_ICON : JCUserAction.ON_CLICK_START_ERROR);
|
||||
} else if (currentState == CURRENT_STATE_PLAYING) {
|
||||
onEvent(JCUserAction.ON_CLICK_PAUSE);
|
||||
Log.d(TAG, "pauseVideo [" + this.hashCode() + "] ");
|
||||
JCMediaManager.instance().mediaPlayer.pause();
|
||||
setUiWitStateAndScreen(CURRENT_STATE_PAUSE);
|
||||
} else if (currentState == CURRENT_STATE_PAUSE) {
|
||||
onEvent(JCUserAction.ON_CLICK_RESUME);
|
||||
JCMediaManager.instance().mediaPlayer.start();
|
||||
setUiWitStateAndScreen(CURRENT_STATE_PLAYING);
|
||||
} else if (currentState == CURRENT_STATE_AUTO_COMPLETE) {
|
||||
onEvent(JCUserAction.ON_CLICK_START_AUTO_COMPLETE);
|
||||
prepareMediaPlayer();
|
||||
}
|
||||
} else if (i == R.id.fullscreen) {
|
||||
Log.i(TAG, "onClick fullscreen [" + this.hashCode() + "] ");
|
||||
if (currentState == CURRENT_STATE_AUTO_COMPLETE) return;
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
//quit fullscreen
|
||||
backPress();
|
||||
} else {
|
||||
Log.d(TAG, "toFullscreenActivity [" + this.hashCode() + "] ");
|
||||
onEvent(JCUserAction.ON_ENTER_FULLSCREEN);
|
||||
startWindowFullscreen();
|
||||
}
|
||||
} else if (i == R.id.surface_container && currentState == CURRENT_STATE_ERROR) {
|
||||
Log.i(TAG, "onClick surfaceContainer State=Error [" + this.hashCode() + "] ");
|
||||
prepareMediaPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareMediaPlayer() {
|
||||
JCVideoPlayerManager.completeAll();
|
||||
Log.d(TAG, "prepareMediaPlayer [" + this.hashCode() + "] ");
|
||||
initTextureView();
|
||||
addTextureView();
|
||||
AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
|
||||
JCUtils.scanForActivity(getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
JCMediaManager.CURRENT_PLAYING_URL = url;
|
||||
JCMediaManager.CURRENT_PLING_LOOP = loop;
|
||||
JCMediaManager.MAP_HEADER_DATA = headData;
|
||||
setUiWitStateAndScreen(CURRENT_STATE_PREPARING);
|
||||
JCVideoPlayerManager.setFirstFloor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
int id = v.getId();
|
||||
if (id == R.id.surface_container) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
Log.i(TAG, "onTouch surfaceContainer actionDown [" + this.hashCode() + "] ");
|
||||
mTouchingProgressBar = true;
|
||||
|
||||
mDownX = x;
|
||||
mDownY = y;
|
||||
mChangeVolume = false;
|
||||
mChangePosition = false;
|
||||
mChangeBrightness = false;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
Log.i(TAG, "onTouch surfaceContainer actionMove [" + this.hashCode() + "] ");
|
||||
float deltaX = x - mDownX;
|
||||
float deltaY = y - mDownY;
|
||||
float absDeltaX = Math.abs(deltaX);
|
||||
float absDeltaY = Math.abs(deltaY);
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
if (!mChangePosition && !mChangeVolume && !mChangeBrightness) {
|
||||
if (absDeltaX > THRESHOLD || absDeltaY > THRESHOLD) {
|
||||
cancelProgressTimer();
|
||||
if (absDeltaX >= THRESHOLD) {
|
||||
// 全屏模式下的CURRENT_STATE_ERROR状态下,不响应进度拖动事件.
|
||||
// 否则会因为mediaplayer的状态非法导致App Crash
|
||||
if (currentState != CURRENT_STATE_ERROR) {
|
||||
mChangePosition = true;
|
||||
mGestureDownPosition = getCurrentPositionWhenPlaying();
|
||||
}
|
||||
} else {
|
||||
//如果y轴滑动距离超过设置的处理范围,那么进行滑动事件处理
|
||||
if (mDownX < mScreenWidth * 0.5f) {//左侧改变亮度
|
||||
mChangeBrightness = true;
|
||||
// WindowManager.LayoutParams lp = JCUtils.getAppCompActivity(getContext()).getWindow().getAttributes();
|
||||
// if (lp.screenBrightness < 0) {
|
||||
// try {
|
||||
// mGestureDownBrightness = Settings.System.getInt(getContext().getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
|
||||
// Log.i(TAG, "current system brightness: " + mGestureDownBrightness);
|
||||
// } catch (Settings.SettingNotFoundException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// } else {
|
||||
// mGestureDownBrightness = lp.screenBrightness * 255;
|
||||
// Log.i(TAG, "current activity brightness: " + mGestureDownBrightness);
|
||||
// }
|
||||
} else {//右侧改变声音
|
||||
mChangeVolume = true;
|
||||
mGestureDownVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mChangePosition) {
|
||||
int totalTimeDuration = getDuration();
|
||||
mSeekTimePosition = (int) (mGestureDownPosition + deltaX * totalTimeDuration / mScreenWidth);
|
||||
if (mSeekTimePosition > totalTimeDuration)
|
||||
mSeekTimePosition = totalTimeDuration;
|
||||
String seekTime = JCUtils.stringForTime(mSeekTimePosition);
|
||||
String totalTime = JCUtils.stringForTime(totalTimeDuration);
|
||||
|
||||
showProgressDialog(deltaX, seekTime, mSeekTimePosition, totalTime, totalTimeDuration);
|
||||
}
|
||||
if (mChangeVolume) {
|
||||
deltaY = -deltaY;
|
||||
int max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
|
||||
int deltaV = (int) (max * deltaY * 3 / mScreenHeight);
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mGestureDownVolume + deltaV, 0);
|
||||
//dialog中显示百分比
|
||||
int volumePercent = (int) (mGestureDownVolume * 100 / max + deltaY * 3 * 100 / mScreenHeight);
|
||||
showVolumeDialog(-deltaY, volumePercent);
|
||||
}
|
||||
|
||||
if (mChangeBrightness) {
|
||||
deltaY = -deltaY;
|
||||
int deltaV = (int) (255 * deltaY * 3 / mScreenHeight);
|
||||
// WindowManager.LayoutParams params = JCUtils.getAppCompActivity(getContext()).getWindow().getAttributes();
|
||||
if (((mGestureDownBrightness + deltaV) / 255) >= 1) {//这和声音有区别,必须自己过滤一下负值
|
||||
// params.screenBrightness = 1;
|
||||
} else if (((mGestureDownBrightness + deltaV) / 255) <= 0) {
|
||||
// params.screenBrightness = 0.01f;
|
||||
} else {
|
||||
// params.screenBrightness = (mGestureDownBrightness + deltaV) / 255;
|
||||
}
|
||||
// JCUtils.getAppCompActivity(getContext()).getWindow().setAttributes(params);
|
||||
//dialog中显示百分比
|
||||
int brightnessPercent = (int) (mGestureDownBrightness * 100 / 255 + deltaY * 3 * 100 / mScreenHeight);
|
||||
showBrightnessDialog(brightnessPercent);
|
||||
// mDownY = y;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
Log.i(TAG, "onTouch surfaceContainer actionUp [" + this.hashCode() + "] ");
|
||||
mTouchingProgressBar = false;
|
||||
dismissProgressDialog();
|
||||
dismissVolumeDialog();
|
||||
dismissBrightnessDialog();
|
||||
if (mChangePosition) {
|
||||
onEvent(JCUserAction.ON_TOUCH_SCREEN_SEEK_POSITION);
|
||||
JCMediaManager.instance().mediaPlayer.seekTo(mSeekTimePosition);
|
||||
int duration = getDuration();
|
||||
int progress = mSeekTimePosition * 100 / (duration == 0 ? 1 : duration);
|
||||
progressBar.setProgress(progress);
|
||||
}
|
||||
if (mChangeVolume) {
|
||||
onEvent(JCUserAction.ON_TOUCH_SCREEN_SEEK_VOLUME);
|
||||
}
|
||||
startProgressTimer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int widthRatio = 0;
|
||||
public int heightRatio = 0;
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN || currentScreen == SCREEN_WINDOW_TINY) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
return;
|
||||
}
|
||||
if (widthRatio != 0 && heightRatio != 0) {
|
||||
int specWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int specHeight = (int) ((specWidth * (float) heightRatio) / widthRatio);
|
||||
setMeasuredDimension(specWidth, specHeight);
|
||||
|
||||
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(specWidth, MeasureSpec.EXACTLY);
|
||||
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(specHeight, MeasureSpec.EXACTLY);
|
||||
getChildAt(0).measure(childWidthMeasureSpec, childHeightMeasureSpec);
|
||||
} else {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void initTextureView() {
|
||||
removeTextureView();
|
||||
JCMediaManager.textureView = new JCResizeTextureView(getContext());
|
||||
JCMediaManager.textureView.setSurfaceTextureListener(JCMediaManager.instance());
|
||||
}
|
||||
|
||||
public void addTextureView() {
|
||||
Log.d(TAG, "addTextureView [" + this.hashCode() + "] ");
|
||||
FrameLayout.LayoutParams layoutParams =
|
||||
new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
Gravity.CENTER);
|
||||
textureViewContainer.addView(JCMediaManager.textureView, layoutParams);
|
||||
}
|
||||
|
||||
public void removeTextureView() {
|
||||
JCMediaManager.savedSurfaceTexture = null;
|
||||
if (JCMediaManager.textureView != null && JCMediaManager.textureView.getParent() != null) {
|
||||
((ViewGroup) JCMediaManager.textureView.getParent()).removeView(JCMediaManager.textureView);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUiWitStateAndScreen(int state) {
|
||||
currentState = state;
|
||||
switch (currentState) {
|
||||
case CURRENT_STATE_NORMAL:
|
||||
cancelProgressTimer();
|
||||
if (isCurrentJcvd()) {//这个if是无法取代的,否则进入全屏的时候会releaseMediaPlayer
|
||||
JCMediaManager.instance().releaseMediaPlayer();
|
||||
}
|
||||
break;
|
||||
case CURRENT_STATE_PREPARING:
|
||||
resetProgressAndTime();
|
||||
break;
|
||||
case CURRENT_STATE_PLAYING:
|
||||
case CURRENT_STATE_PAUSE:
|
||||
case CURRENT_STATE_PLAYING_BUFFERING_START:
|
||||
startProgressTimer();
|
||||
break;
|
||||
case CURRENT_STATE_ERROR:
|
||||
cancelProgressTimer();
|
||||
break;
|
||||
case CURRENT_STATE_AUTO_COMPLETE:
|
||||
cancelProgressTimer();
|
||||
progressBar.setProgress(100);
|
||||
currentTimeTextView.setText(totalTimeTextView.getText());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void startProgressTimer() {
|
||||
cancelProgressTimer();
|
||||
UPDATE_PROGRESS_TIMER = new Timer();
|
||||
mProgressTimerTask = new ProgressTimerTask();
|
||||
UPDATE_PROGRESS_TIMER.schedule(mProgressTimerTask, 0, 300);
|
||||
}
|
||||
|
||||
public void cancelProgressTimer() {
|
||||
if (UPDATE_PROGRESS_TIMER != null) {
|
||||
UPDATE_PROGRESS_TIMER.cancel();
|
||||
}
|
||||
if (mProgressTimerTask != null) {
|
||||
mProgressTimerTask.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPrepared() {
|
||||
Log.i(TAG, "onPrepared " + " [" + this.hashCode() + "] ");
|
||||
|
||||
if (currentState != CURRENT_STATE_PREPARING) return;
|
||||
if (seekToInAdvance != 0) {
|
||||
JCMediaManager.instance().mediaPlayer.seekTo(seekToInAdvance);
|
||||
seekToInAdvance = 0;
|
||||
} else {
|
||||
int position = JCUtils.getSavedProgress(getContext(), url);
|
||||
if (position != 0) {
|
||||
JCMediaManager.instance().mediaPlayer.seekTo(position);
|
||||
}
|
||||
}
|
||||
startProgressTimer();
|
||||
setUiWitStateAndScreen(CURRENT_STATE_PLAYING);
|
||||
}
|
||||
|
||||
public void clearFullscreenLayout() {
|
||||
ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView();
|
||||
.findViewById(Window.ID_ANDROID_CONTENT);
|
||||
View oldF = vp.findViewById(FULLSCREEN_ID);
|
||||
View oldT = vp.findViewById(TINY_ID);
|
||||
if (oldF != null) {
|
||||
vp.removeView(oldF);
|
||||
}
|
||||
if (oldT != null) {
|
||||
vp.removeView(oldT);
|
||||
}
|
||||
showSupportActionBar(getContext());
|
||||
}
|
||||
|
||||
public void onAutoCompletion() {
|
||||
//加上这句,避免循环播放video的时候,内存不断飙升。
|
||||
Runtime.getRuntime().gc();
|
||||
Log.i(TAG, "onAutoCompletion " + " [" + this.hashCode() + "] ");
|
||||
onEvent(JCUserAction.ON_AUTO_COMPLETE);
|
||||
dismissVolumeDialog();
|
||||
dismissProgressDialog();
|
||||
dismissBrightnessDialog();
|
||||
cancelProgressTimer();
|
||||
setUiWitStateAndScreen(CURRENT_STATE_AUTO_COMPLETE);
|
||||
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
backPress();
|
||||
}
|
||||
JCUtils.saveProgress(getContext(), url, 0);
|
||||
}
|
||||
|
||||
public void onCompletion() {
|
||||
Log.i(TAG, "onCompletion " + " [" + this.hashCode() + "] ");
|
||||
//save position
|
||||
if (currentState == CURRENT_STATE_PLAYING || currentState == CURRENT_STATE_PAUSE) {
|
||||
int position = getCurrentPositionWhenPlaying();
|
||||
// int duration = getDuration();
|
||||
JCUtils.saveProgress(getContext(), url, position);
|
||||
}
|
||||
cancelProgressTimer();
|
||||
setUiWitStateAndScreen(CURRENT_STATE_NORMAL);
|
||||
// 清理缓存变量
|
||||
textureViewContainer.removeView(JCMediaManager.textureView);
|
||||
JCMediaManager.instance().currentVideoWidth = 0;
|
||||
JCMediaManager.instance().currentVideoHeight = 0;
|
||||
|
||||
AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
|
||||
JCUtils.scanForActivity(getContext()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
clearFullscreenLayout();
|
||||
// JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(NORMAL_ORIENTATION);
|
||||
|
||||
JCMediaManager.textureView = null;
|
||||
JCMediaManager.savedSurfaceTexture = null;
|
||||
}
|
||||
|
||||
//退出全屏和小窗的方法
|
||||
public void playOnThisJcvd() {
|
||||
Log.i(TAG, "playOnThisJcvd " + " [" + this.hashCode() + "] ");
|
||||
//1.清空全屏和小窗的jcvd
|
||||
currentState = JCVideoPlayerManager.getSecondFloor().currentState;
|
||||
clearFloatScreen();
|
||||
//2.在本jcvd上播放
|
||||
setUiWitStateAndScreen(currentState);
|
||||
addTextureView();
|
||||
}
|
||||
|
||||
public void clearFloatScreen() {
|
||||
// JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(NORMAL_ORIENTATION);
|
||||
showSupportActionBar(getContext());
|
||||
JCVideoPlayer currJcvd = JCVideoPlayerManager.getCurrentJcvd();
|
||||
currJcvd.textureViewContainer.removeView(JCMediaManager.textureView);
|
||||
ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView();
|
||||
.findViewById(Window.ID_ANDROID_CONTENT);
|
||||
vp.removeView(currJcvd);
|
||||
JCVideoPlayerManager.setSecondFloor(null);
|
||||
}
|
||||
|
||||
public static long lastAutoFullscreenTime = 0;
|
||||
|
||||
//重力感应的时候调用的函数,
|
||||
public void autoFullscreen(float x) {
|
||||
if (isCurrentJcvd()
|
||||
&& currentState == CURRENT_STATE_PLAYING
|
||||
&& currentScreen != SCREEN_WINDOW_FULLSCREEN
|
||||
&& currentScreen != SCREEN_WINDOW_TINY) {
|
||||
if (x > 0) {
|
||||
// JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(
|
||||
// ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
} else {
|
||||
// JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(
|
||||
// ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
|
||||
}
|
||||
startWindowFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
public void autoQuitFullscreen() {
|
||||
if ((System.currentTimeMillis() - lastAutoFullscreenTime) > 2000
|
||||
&& isCurrentJcvd()
|
||||
&& currentState == CURRENT_STATE_PLAYING
|
||||
&& currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
lastAutoFullscreenTime = System.currentTimeMillis();
|
||||
backPress();
|
||||
}
|
||||
}
|
||||
|
||||
public void onSeekComplete() {
|
||||
|
||||
}
|
||||
|
||||
public void onError(int what, int extra) {
|
||||
Log.e(TAG, "onError " + what + " - " + extra + " [" + this.hashCode() + "] ");
|
||||
if (what != 38 && what != -38) {
|
||||
setUiWitStateAndScreen(CURRENT_STATE_ERROR);
|
||||
if (isCurrentJcvd()) {
|
||||
JCMediaManager.instance().releaseMediaPlayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onInfo(int what, int extra) {
|
||||
Log.d(TAG, "onInfo what - " + what + " extra - " + extra);
|
||||
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
|
||||
if (currentState == CURRENT_STATE_PLAYING_BUFFERING_START) return;
|
||||
BACKUP_PLAYING_BUFFERING_STATE = currentState;
|
||||
setUiWitStateAndScreen(CURRENT_STATE_PLAYING_BUFFERING_START);//没这个case
|
||||
Log.d(TAG, "MEDIA_INFO_BUFFERING_START");
|
||||
} else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
|
||||
if (BACKUP_PLAYING_BUFFERING_STATE != -1) {
|
||||
setUiWitStateAndScreen(BACKUP_PLAYING_BUFFERING_STATE);
|
||||
BACKUP_PLAYING_BUFFERING_STATE = -1;
|
||||
}
|
||||
Log.d(TAG, "MEDIA_INFO_BUFFERING_END");
|
||||
}
|
||||
}
|
||||
|
||||
public void onVideoSizeChanged() {
|
||||
Log.i(TAG, "onVideoSizeChanged " + " [" + this.hashCode() + "] ");
|
||||
if (JCMediaManager.textureView != null) {
|
||||
JCMediaManager.textureView.setVideoSize(JCMediaManager.instance().getVideoSize());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
Log.i(TAG, "bottomProgress onStartTrackingTouch [" + this.hashCode() + "] ");
|
||||
cancelProgressTimer();
|
||||
ViewParent vpdown = getParent();
|
||||
while (vpdown != null) {
|
||||
vpdown.requestDisallowInterceptTouchEvent(true);
|
||||
vpdown = vpdown.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
Log.i(TAG, "bottomProgress onStopTrackingTouch [" + this.hashCode() + "] ");
|
||||
onEvent(JCUserAction.ON_SEEK_POSITION);
|
||||
startProgressTimer();
|
||||
ViewParent vpup = getParent();
|
||||
while (vpup != null) {
|
||||
vpup.requestDisallowInterceptTouchEvent(false);
|
||||
vpup = vpup.getParent();
|
||||
}
|
||||
if (currentState != CURRENT_STATE_PLAYING &&
|
||||
currentState != CURRENT_STATE_PAUSE) return;
|
||||
int time = seekBar.getProgress() * getDuration() / 100;
|
||||
JCMediaManager.instance().mediaPlayer.seekTo(time);
|
||||
Log.i(TAG, "seekTo " + time + " [" + this.hashCode() + "] ");
|
||||
}
|
||||
|
||||
public static boolean backPress() {
|
||||
Log.i(TAG, "backPress");
|
||||
if ((System.currentTimeMillis() - CLICK_QUIT_FULLSCREEN_TIME) < FULL_SCREEN_NORMAL_DELAY)
|
||||
return false;
|
||||
if (JCVideoPlayerManager.getSecondFloor() != null) {
|
||||
CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
|
||||
JCVideoPlayer jcVideoPlayer = JCVideoPlayerManager.getSecondFloor();
|
||||
jcVideoPlayer.onEvent(jcVideoPlayer.currentScreen == JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN ?
|
||||
JCUserAction.ON_QUIT_FULLSCREEN :
|
||||
JCUserAction.ON_QUIT_TINYSCREEN);
|
||||
JCVideoPlayerManager.getFirstFloor().playOnThisJcvd();
|
||||
return true;
|
||||
} else if (JCVideoPlayerManager.getFirstFloor() != null &&
|
||||
(JCVideoPlayerManager.getFirstFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN ||
|
||||
JCVideoPlayerManager.getFirstFloor().currentScreen == SCREEN_WINDOW_TINY)) {//以前我总想把这两个判断写到一起,这分明是两个独立是逻辑
|
||||
CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
|
||||
//直接退出全屏和小窗
|
||||
JCVideoPlayerManager.getCurrentJcvd().currentState = CURRENT_STATE_NORMAL;
|
||||
JCVideoPlayerManager.getFirstFloor().clearFloatScreen();
|
||||
JCMediaManager.instance().releaseMediaPlayer();
|
||||
JCVideoPlayerManager.setFirstFloor(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void startWindowFullscreen() {
|
||||
Log.i(TAG, "startWindowFullscreen " + " [" + this.hashCode() + "] ");
|
||||
hideSupportActionBar(getContext());
|
||||
// JCUtils.getAppCompActivity(getContext()).setRequestedOrientation(FULLSCREEN_ORIENTATION);
|
||||
|
||||
ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView();
|
||||
.findViewById(Window.ID_ANDROID_CONTENT);
|
||||
View old = vp.findViewById(FULLSCREEN_ID);
|
||||
if (old != null) {
|
||||
vp.removeView(old);
|
||||
}
|
||||
// ((ViewGroup)JCMediaManager.textureView.getParent()).removeView(JCMediaManager.textureView);
|
||||
textureViewContainer.removeView(JCMediaManager.textureView);
|
||||
try {
|
||||
Constructor<JCVideoPlayer> constructor = (Constructor<JCVideoPlayer>) JCVideoPlayer.this.getClass().getConstructor(Context.class);
|
||||
JCVideoPlayer jcVideoPlayer = constructor.newInstance(getContext());
|
||||
jcVideoPlayer.setId(FULLSCREEN_ID);
|
||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
vp.addView(jcVideoPlayer, lp);
|
||||
jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects);
|
||||
jcVideoPlayer.setUiWitStateAndScreen(currentState);
|
||||
jcVideoPlayer.addTextureView();
|
||||
JCVideoPlayerManager.setSecondFloor(jcVideoPlayer);
|
||||
// final Animation ra = AnimationUtils.loadAnimation(getContext(), R.anim.start_fullscreen);
|
||||
// jcVideoPlayer.setAnimation(ra);
|
||||
CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void startWindowTiny() {
|
||||
Log.i(TAG, "startWindowTiny " + " [" + this.hashCode() + "] ");
|
||||
onEvent(JCUserAction.ON_ENTER_TINYSCREEN);
|
||||
if (currentState == CURRENT_STATE_NORMAL || currentState == CURRENT_STATE_ERROR) return;
|
||||
ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(getContext()))//.getWindow().getDecorView();
|
||||
.findViewById(Window.ID_ANDROID_CONTENT);
|
||||
View old = vp.findViewById(TINY_ID);
|
||||
if (old != null) {
|
||||
vp.removeView(old);
|
||||
}
|
||||
textureViewContainer.removeView(JCMediaManager.textureView);
|
||||
|
||||
try {
|
||||
Constructor<JCVideoPlayer> constructor = (Constructor<JCVideoPlayer>) JCVideoPlayer.this.getClass().getConstructor(Context.class);
|
||||
JCVideoPlayer jcVideoPlayer = constructor.newInstance(getContext());
|
||||
jcVideoPlayer.setId(TINY_ID);
|
||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(400, 400);
|
||||
lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
|
||||
vp.addView(jcVideoPlayer, lp);
|
||||
jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_TINY, objects);
|
||||
jcVideoPlayer.setUiWitStateAndScreen(currentState);
|
||||
jcVideoPlayer.addTextureView();
|
||||
JCVideoPlayerManager.setSecondFloor(jcVideoPlayer);
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public class ProgressTimerTask extends TimerTask {
|
||||
@Override
|
||||
public void run() {
|
||||
if (currentState == CURRENT_STATE_PLAYING || currentState == CURRENT_STATE_PAUSE || currentState == CURRENT_STATE_PLAYING_BUFFERING_START) {
|
||||
// Log.v(TAG, "onProgressUpdate " + position + "/" + duration + " [" + this.hashCode() + "] ");
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setProgressAndText();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentPositionWhenPlaying() {
|
||||
int position = 0;
|
||||
if (JCMediaManager.instance().mediaPlayer == null)
|
||||
return position;//这行代码不应该在这,如果代码和逻辑万无一失的话,心头之恨呐
|
||||
if (currentState == CURRENT_STATE_PLAYING ||
|
||||
currentState == CURRENT_STATE_PAUSE ||
|
||||
currentState == CURRENT_STATE_PLAYING_BUFFERING_START) {
|
||||
try {
|
||||
position = JCMediaManager.instance().mediaPlayer.getCurrentPosition();
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
return position;
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
int duration = 0;
|
||||
if (JCMediaManager.instance().mediaPlayer == null) return duration;
|
||||
try {
|
||||
duration = JCMediaManager.instance().mediaPlayer.getDuration();
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
return duration;
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setProgressAndText() {
|
||||
int position = getCurrentPositionWhenPlaying();
|
||||
int duration = getDuration();
|
||||
int progress = position * 100 / (duration == 0 ? 1 : duration);
|
||||
if (!mTouchingProgressBar) {
|
||||
if (progress != 0) progressBar.setProgress(progress);
|
||||
}
|
||||
if (position != 0) currentTimeTextView.setText(JCUtils.stringForTime(position));
|
||||
totalTimeTextView.setText(JCUtils.stringForTime(duration));
|
||||
}
|
||||
|
||||
public void setBufferProgress(int bufferProgress) {
|
||||
if (bufferProgress != 0) progressBar.setSecondaryProgress(bufferProgress);
|
||||
}
|
||||
|
||||
public void resetProgressAndTime() {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setSecondaryProgress(0);
|
||||
currentTimeTextView.setText(JCUtils.stringForTime(0));
|
||||
totalTimeTextView.setText(JCUtils.stringForTime(0));
|
||||
}
|
||||
|
||||
public static AudioManager.OnAudioFocusChangeListener onAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
|
||||
@Override
|
||||
public void onAudioFocusChange(int focusChange) {
|
||||
switch (focusChange) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN:
|
||||
break;
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
releaseAllVideos();
|
||||
Log.d(TAG, "AUDIOFOCUS_LOSS [" + this.hashCode() + "]");
|
||||
break;
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
try {
|
||||
if (JCMediaManager.instance().mediaPlayer != null &&
|
||||
JCMediaManager.instance().mediaPlayer.isPlaying()) {
|
||||
JCMediaManager.instance().mediaPlayer.pause();
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT [" + this.hashCode() + "]");
|
||||
break;
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void release() {
|
||||
if (url.equals(JCMediaManager.CURRENT_PLAYING_URL) &&
|
||||
(System.currentTimeMillis() - CLICK_QUIT_FULLSCREEN_TIME) > FULL_SCREEN_NORMAL_DELAY) {
|
||||
//在非全屏的情况下只能backPress()
|
||||
if (JCVideoPlayerManager.getSecondFloor() != null &&
|
||||
JCVideoPlayerManager.getSecondFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN) {//点击全屏
|
||||
} else if (JCVideoPlayerManager.getSecondFloor() == null && JCVideoPlayerManager.getFirstFloor() != null &&
|
||||
JCVideoPlayerManager.getFirstFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN) {//直接全屏
|
||||
} else {
|
||||
Log.d(TAG, "release [" + this.hashCode() + "]");
|
||||
releaseAllVideos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//isCurrentJcvd and isCurrenPlayUrl should be two logic methods,isCurrentJcvd is for different jcvd with same
|
||||
//url when fullscreen or tiny screen. isCurrenPlayUrl is to find where is myself when back from tiny screen.
|
||||
//Sometimes they are overlap.
|
||||
public boolean isCurrentJcvd() {//虽然看这个函数很不爽,但是干不掉
|
||||
return JCVideoPlayerManager.getCurrentJcvd() != null
|
||||
&& JCVideoPlayerManager.getCurrentJcvd() == this;
|
||||
}
|
||||
|
||||
// public boolean isCurrenPlayingUrl() {
|
||||
// return url.equals(JCMediaManager.CURRENT_PLAYING_URL);
|
||||
// }
|
||||
|
||||
public static void releaseAllVideos() {
|
||||
if ((System.currentTimeMillis() - CLICK_QUIT_FULLSCREEN_TIME) > FULL_SCREEN_NORMAL_DELAY) {
|
||||
Log.d(TAG, "releaseAllVideos");
|
||||
JCVideoPlayerManager.completeAll();
|
||||
JCMediaManager.instance().releaseMediaPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setJcUserAction(JCUserAction jcUserEvent) {
|
||||
JC_USER_EVENT = jcUserEvent;
|
||||
}
|
||||
|
||||
public void onEvent(int type) {
|
||||
if (JC_USER_EVENT != null && isCurrentJcvd()) {
|
||||
JC_USER_EVENT.onEvent(type, url, currentScreen, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void startFullscreen(Context context, Class _class, String url, Object... objects) {
|
||||
hideSupportActionBar(context);
|
||||
// JCUtils.getAppCompActivity(context).setRequestedOrientation(FULLSCREEN_ORIENTATION);
|
||||
ViewGroup vp = (ViewGroup) (JCUtils.scanForActivity(context))//.getWindow().getDecorView();
|
||||
.findViewById(Window.ID_ANDROID_CONTENT);
|
||||
View old = vp.findViewById(JCVideoPlayer.FULLSCREEN_ID);
|
||||
if (old != null) {
|
||||
vp.removeView(old);
|
||||
}
|
||||
try {
|
||||
Constructor<JCVideoPlayer> constructor = _class.getConstructor(Context.class);
|
||||
final JCVideoPlayer jcVideoPlayer = constructor.newInstance(context);
|
||||
jcVideoPlayer.setId(JCVideoPlayer.FULLSCREEN_ID);
|
||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
vp.addView(jcVideoPlayer, lp);
|
||||
// final Animation ra = AnimationUtils.loadAnimation(context, R.anim.start_fullscreen);
|
||||
// jcVideoPlayer.setAnimation(ra);
|
||||
jcVideoPlayer.setUp(url, JCVideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects);
|
||||
CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
|
||||
jcVideoPlayer.startButton.performClick();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void hideSupportActionBar(Context context) {
|
||||
if (ACTION_BAR_EXIST) {
|
||||
// ActionBar ab = JCUtils.getAppCompActivity(context).getSupportActionBar();
|
||||
// if (ab != null) {
|
||||
// ab.setShowHideAnimationEnabled(false);
|
||||
// ab.hide();
|
||||
// }
|
||||
}
|
||||
if (TOOL_BAR_EXIST) {
|
||||
// JCUtils.getAppCompActivity(context).getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
// WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showSupportActionBar(Context context) {
|
||||
if (ACTION_BAR_EXIST) {
|
||||
// ActionBar ab = JCUtils.getAppCompActivity(context).getSupportActionBar();
|
||||
// if (ab != null) {
|
||||
// ab.setShowHideAnimationEnabled(false);
|
||||
// ab.show();
|
||||
// }
|
||||
}
|
||||
if (TOOL_BAR_EXIST) {
|
||||
// JCUtils.getAppCompActivity(context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
|
||||
public static class JCAutoFullscreenListener implements SensorEventListener {
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {//可以得到传感器实时测量出来的变化值
|
||||
final float x = event.values[SensorManager.DATA_X];
|
||||
float y = event.values[SensorManager.DATA_Y];
|
||||
float z = event.values[SensorManager.DATA_Z];
|
||||
//过滤掉用力过猛会有一个反向的大数值
|
||||
if (((x > -15 && x < -10) || (x < 15 && x > 10)) && Math.abs(y) < 1.5) {
|
||||
if ((System.currentTimeMillis() - lastAutoFullscreenTime) > 2000) {
|
||||
if (JCVideoPlayerManager.getCurrentJcvd() != null) {
|
||||
JCVideoPlayerManager.getCurrentJcvd().autoFullscreen(x);
|
||||
}
|
||||
lastAutoFullscreenTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearSavedProgress(Context context, String url) {
|
||||
JCUtils.clearSavedProgress(context, url);
|
||||
}
|
||||
|
||||
public void showWifiDialog() {
|
||||
}
|
||||
|
||||
public void showProgressDialog(float deltaX,
|
||||
String seekTime, int seekTimePosition,
|
||||
String totalTime, int totalTimeDuration) {
|
||||
}
|
||||
|
||||
public void dismissProgressDialog() {
|
||||
|
||||
}
|
||||
|
||||
public void showVolumeDialog(float deltaY, int volumePercent) {
|
||||
|
||||
}
|
||||
|
||||
public void dismissVolumeDialog() {
|
||||
|
||||
}
|
||||
|
||||
public void showBrightnessDialog(int brightnessPercent) {
|
||||
|
||||
}
|
||||
|
||||
public void dismissBrightnessDialog() {
|
||||
|
||||
}
|
||||
|
||||
public abstract int getLayoutId();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
/**
|
||||
* Put JCVideoPlayer into layout
|
||||
* From a JCVideoPlayer to another JCVideoPlayer
|
||||
* Created by Nathen on 16/7/26.
|
||||
*/
|
||||
public class JCVideoPlayerManager {
|
||||
|
||||
public static JCVideoPlayer FIRST_FLOOR_JCVD;
|
||||
public static JCVideoPlayer SECOND_FLOOR_JCVD;
|
||||
|
||||
public static void setFirstFloor(JCVideoPlayer jcVideoPlayer) {
|
||||
FIRST_FLOOR_JCVD = jcVideoPlayer;
|
||||
}
|
||||
|
||||
public static void setSecondFloor(JCVideoPlayer jcVideoPlayer) {
|
||||
SECOND_FLOOR_JCVD = jcVideoPlayer;
|
||||
}
|
||||
|
||||
public static JCVideoPlayer getFirstFloor() {
|
||||
return FIRST_FLOOR_JCVD;
|
||||
}
|
||||
|
||||
public static JCVideoPlayer getSecondFloor() {
|
||||
return SECOND_FLOOR_JCVD;
|
||||
}
|
||||
|
||||
public static JCVideoPlayer getCurrentJcvd() {
|
||||
if (getSecondFloor() != null) {
|
||||
return getSecondFloor();
|
||||
}
|
||||
return getFirstFloor();
|
||||
}
|
||||
|
||||
public static void completeAll() {
|
||||
if (SECOND_FLOOR_JCVD != null) {
|
||||
SECOND_FLOOR_JCVD.onCompletion();
|
||||
SECOND_FLOOR_JCVD = null;
|
||||
}
|
||||
if (FIRST_FLOOR_JCVD != null) {
|
||||
FIRST_FLOOR_JCVD.onCompletion();
|
||||
FIRST_FLOOR_JCVD = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Manage UI
|
||||
* Created by Nathen
|
||||
* On 2016/04/10 15:45
|
||||
*/
|
||||
public class JCVideoPlayerSimple extends JCVideoPlayer {
|
||||
|
||||
public JCVideoPlayerSimple(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public JCVideoPlayerSimple(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.jc_layout_base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp(String url, int screen, Object... objects) {
|
||||
super.setUp(url, screen, objects);
|
||||
updateFullscreenButton();
|
||||
fullscreenButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUiWitStateAndScreen(int state) {
|
||||
super.setUiWitStateAndScreen(state);
|
||||
switch (currentState) {
|
||||
case CURRENT_STATE_NORMAL:
|
||||
startButton.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case CURRENT_STATE_PREPARING:
|
||||
startButton.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
case CURRENT_STATE_PLAYING:
|
||||
startButton.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case CURRENT_STATE_PAUSE:
|
||||
break;
|
||||
case CURRENT_STATE_ERROR:
|
||||
break;
|
||||
}
|
||||
updateStartImage();
|
||||
}
|
||||
|
||||
private void updateStartImage() {
|
||||
if (currentState == CURRENT_STATE_PLAYING) {
|
||||
startButton.setImageResource(R.drawable.jc_click_pause_selector);
|
||||
} else if (currentState == CURRENT_STATE_ERROR) {
|
||||
startButton.setImageResource(R.drawable.jc_click_error_selector);
|
||||
} else {
|
||||
startButton.setImageResource(R.drawable.jc_click_play_selector);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFullscreenButton() {
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
fullscreenButton.setImageResource(R.drawable.jc_shrink);
|
||||
} else {
|
||||
fullscreenButton.setImageResource(R.drawable.jc_enlarge);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.fullscreen && currentState == CURRENT_STATE_NORMAL) {
|
||||
Toast.makeText(getContext(), "Play video first", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
super.onClick(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (fromUser) {
|
||||
if (currentState == CURRENT_STATE_NORMAL) {
|
||||
Toast.makeText(getContext(), "Play video first", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.onProgressChanged(seekBar, progress, fromUser);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,785 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Created by Nathen
|
||||
* On 2016/04/18 16:15
|
||||
*/
|
||||
public class JCVideoPlayerStandard extends JCVideoPlayer {
|
||||
|
||||
protected static Timer DISMISS_CONTROL_VIEW_TIMER;
|
||||
|
||||
public ImageView backButton;
|
||||
public ProgressBar bottomProgressBar, loadingProgressBar;
|
||||
public TextView titleTextView;
|
||||
public ImageView thumbImageView;
|
||||
public ImageView tinyBackImageView;
|
||||
|
||||
|
||||
protected DismissControlViewTimerTask mDismissControlViewTimerTask;
|
||||
|
||||
|
||||
public JCVideoPlayerStandard(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public JCVideoPlayerStandard(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
super.init(context);
|
||||
bottomProgressBar = (ProgressBar) findViewById(R.id.bottom_progress);
|
||||
titleTextView = (TextView) findViewById(R.id.title);
|
||||
backButton = (ImageView) findViewById(R.id.back);
|
||||
thumbImageView = (ImageView) findViewById(R.id.thumb);
|
||||
loadingProgressBar = (ProgressBar) findViewById(R.id.loading);
|
||||
tinyBackImageView = (ImageView) findViewById(R.id.back_tiny);
|
||||
|
||||
thumbImageView.setOnClickListener(this);
|
||||
backButton.setOnClickListener(this);
|
||||
tinyBackImageView.setOnClickListener(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp(String url, int screen, Object... objects) {
|
||||
super.setUp(url, screen, objects);
|
||||
if (objects.length == 0) return;
|
||||
titleTextView.setText(objects[0].toString());
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
fullscreenButton.setImageResource(R.drawable.jc_shrink);
|
||||
backButton.setVisibility(View.VISIBLE);
|
||||
tinyBackImageView.setVisibility(View.INVISIBLE);
|
||||
changeStartButtonSize((int) getResources().getDimension(R.dimen.jc_start_button_w_h_fullscreen));
|
||||
} else if (currentScreen == SCREEN_LAYOUT_NORMAL
|
||||
|| currentScreen == SCREEN_LAYOUT_LIST) {
|
||||
fullscreenButton.setImageResource(R.drawable.jc_enlarge);
|
||||
backButton.setVisibility(View.GONE);
|
||||
tinyBackImageView.setVisibility(View.INVISIBLE);
|
||||
changeStartButtonSize((int) getResources().getDimension(R.dimen.jc_start_button_w_h_normal));
|
||||
} else if (currentScreen == SCREEN_WINDOW_TINY) {
|
||||
tinyBackImageView.setVisibility(View.VISIBLE);
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
}
|
||||
fullscreenButton.setVisibility(GONE);
|
||||
}
|
||||
|
||||
public void changeStartButtonSize(int size) {
|
||||
ViewGroup.LayoutParams lp = startButton.getLayoutParams();
|
||||
lp.height = size;
|
||||
lp.width = size;
|
||||
lp = loadingProgressBar.getLayoutParams();
|
||||
lp.height = size;
|
||||
lp.width = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.jc_layout_standard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUiWitStateAndScreen(int state) {
|
||||
super.setUiWitStateAndScreen(state);
|
||||
switch (currentState) {
|
||||
case CURRENT_STATE_NORMAL:
|
||||
changeUiToNormal();
|
||||
break;
|
||||
case CURRENT_STATE_PREPARING:
|
||||
changeUiToPreparingShow();
|
||||
startDismissControlViewTimer();
|
||||
break;
|
||||
case CURRENT_STATE_PLAYING:
|
||||
changeUiToPlayingShow();
|
||||
startDismissControlViewTimer();
|
||||
break;
|
||||
case CURRENT_STATE_PAUSE:
|
||||
changeUiToPauseShow();
|
||||
cancelDismissControlViewTimer();
|
||||
break;
|
||||
case CURRENT_STATE_ERROR:
|
||||
changeUiToError();
|
||||
break;
|
||||
case CURRENT_STATE_AUTO_COMPLETE:
|
||||
changeUiToCompleteShow();
|
||||
cancelDismissControlViewTimer();
|
||||
bottomProgressBar.setProgress(100);
|
||||
break;
|
||||
case CURRENT_STATE_PLAYING_BUFFERING_START:
|
||||
changeUiToPlayingBufferingShow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
int id = v.getId();
|
||||
if (id == R.id.surface_container) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
startDismissControlViewTimer();
|
||||
if (mChangePosition) {
|
||||
int duration = getDuration();
|
||||
int progress = mSeekTimePosition * 100 / (duration == 0 ? 1 : duration);
|
||||
bottomProgressBar.setProgress(progress);
|
||||
}
|
||||
if (!mChangePosition && !mChangeVolume) {
|
||||
onEvent(JCUserActionStandard.ON_CLICK_BLANK);
|
||||
onClickUiToggle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (id == R.id.bottom_seek_progress) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
cancelDismissControlViewTimer();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
startDismissControlViewTimer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onTouch(v, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
super.onClick(v);
|
||||
int i = v.getId();
|
||||
if (i == R.id.thumb) {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
Toast.makeText(getContext(), getResources().getString(R.string.no_url), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (currentState == CURRENT_STATE_NORMAL) {
|
||||
if (!url.startsWith("file") && !url.startsWith("/") &&
|
||||
!JCUtils.isWifiConnected(getContext()) && !WIFI_TIP_DIALOG_SHOWED) {
|
||||
showWifiDialog();
|
||||
return;
|
||||
}
|
||||
startVideo();
|
||||
} else if (currentState == CURRENT_STATE_AUTO_COMPLETE) {
|
||||
onClickUiToggle();
|
||||
}
|
||||
} else if (i == R.id.surface_container) {
|
||||
startDismissControlViewTimer();
|
||||
} else if (i == R.id.back) {
|
||||
backPress();
|
||||
} else if (i == R.id.back_tiny) {
|
||||
backPress();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void showWifiDialog() {
|
||||
super.showWifiDialog();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setMessage(getResources().getString(R.string.tips_not_wifi));
|
||||
builder.setPositiveButton(getResources().getString(R.string.tips_not_wifi_confirm), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
startVideo();
|
||||
WIFI_TIP_DIALOG_SHOWED = true;
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(getResources().getString(R.string.tips_not_wifi_cancel), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
dialog.dismiss();
|
||||
clearFullscreenLayout();
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
dialog.dismiss();
|
||||
clearFullscreenLayout();
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
super.onStartTrackingTouch(seekBar);
|
||||
cancelDismissControlViewTimer();
|
||||
}
|
||||
public void startPlayVideo(){
|
||||
startButton.performClick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
super.onStopTrackingTouch(seekBar);
|
||||
startDismissControlViewTimer();
|
||||
}
|
||||
|
||||
public void startVideo() {
|
||||
prepareMediaPlayer();
|
||||
onEvent(JCUserActionStandard.ON_CLICK_START_THUMB);
|
||||
}
|
||||
|
||||
public void onClickUiToggle() {
|
||||
if (currentState == CURRENT_STATE_PREPARING) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPreparingClear();
|
||||
} else {
|
||||
changeUiToPreparingShow();
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_PLAYING) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPlayingClear();
|
||||
} else {
|
||||
changeUiToPlayingShow();
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_PAUSE) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPauseClear();
|
||||
} else {
|
||||
changeUiToPauseShow();
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_AUTO_COMPLETE) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToCompleteClear();
|
||||
} else {
|
||||
changeUiToCompleteShow();
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_PLAYING_BUFFERING_START) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPlayingBufferingClear();
|
||||
} else {
|
||||
changeUiToPlayingBufferingShow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onCLickUiToggleToClear() {
|
||||
if (currentState == CURRENT_STATE_PREPARING) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPreparingClear();
|
||||
} else {
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_PLAYING) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPlayingClear();
|
||||
} else {
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_PAUSE) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPauseClear();
|
||||
} else {
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_AUTO_COMPLETE) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToCompleteClear();
|
||||
} else {
|
||||
}
|
||||
} else if (currentState == CURRENT_STATE_PLAYING_BUFFERING_START) {
|
||||
if (bottomContainer.getVisibility() == View.VISIBLE) {
|
||||
changeUiToPlayingBufferingClear();
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgressAndText() {
|
||||
super.setProgressAndText();
|
||||
int position = getCurrentPositionWhenPlaying();
|
||||
int duration = getDuration();
|
||||
int progress = position * 100 / (duration == 0 ? 1 : duration);
|
||||
if (progress != 0) bottomProgressBar.setProgress(progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBufferProgress(int bufferProgress) {
|
||||
super.setBufferProgress(bufferProgress);
|
||||
if (bufferProgress != 0) bottomProgressBar.setSecondaryProgress(bufferProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetProgressAndTime() {
|
||||
super.resetProgressAndTime();
|
||||
bottomProgressBar.setProgress(0);
|
||||
bottomProgressBar.setSecondaryProgress(0);
|
||||
}
|
||||
|
||||
//Unified management Ui
|
||||
public void changeUiToNormal() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.VISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.VISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void changeUiToPreparingShow() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.VISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.VISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToPreparingClear() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.VISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.VISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//JustPreparedUi
|
||||
@Override
|
||||
public void onPrepared() {
|
||||
super.onPrepared();
|
||||
setAllControlsVisible(View.VISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
startDismissControlViewTimer();
|
||||
}
|
||||
|
||||
public void changeUiToPlayingShow() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToPlayingClear() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToPauseShow() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToPauseClear() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToPlayingBufferingShow() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.INVISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToPlayingBufferingClear() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.INVISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.INVISIBLE,
|
||||
View.VISIBLE, View.INVISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToCompleteShow() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.VISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.VISIBLE, View.VISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.VISIBLE, View.INVISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToCompleteClear() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.VISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.VISIBLE, View.INVISIBLE, View.VISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void changeUiToError() {
|
||||
switch (currentScreen) {
|
||||
case SCREEN_LAYOUT_NORMAL:
|
||||
case SCREEN_LAYOUT_LIST:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_FULLSCREEN:
|
||||
setAllControlsVisible(View.INVISIBLE, View.INVISIBLE, View.VISIBLE,
|
||||
View.INVISIBLE, View.INVISIBLE, View.VISIBLE, View.INVISIBLE);
|
||||
updateStartImage();
|
||||
break;
|
||||
case SCREEN_WINDOW_TINY:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setAllControlsVisible(int topCon, int bottomCon, int startBtn, int loadingPro,
|
||||
int thumbImg, int coverImg, int bottomPro) {
|
||||
topContainer.setVisibility(topCon);
|
||||
bottomContainer.setVisibility(bottomCon);
|
||||
startButton.setVisibility(startBtn);
|
||||
loadingProgressBar.setVisibility(loadingPro);
|
||||
thumbImageView.setVisibility(thumbImg);
|
||||
bottomProgressBar.setVisibility(bottomPro);
|
||||
}
|
||||
|
||||
public void updateStartImage() {
|
||||
if (currentState == CURRENT_STATE_PLAYING) {
|
||||
startButton.setImageResource(R.drawable.jc_click_pause_selector);
|
||||
} else if (currentState == CURRENT_STATE_ERROR) {
|
||||
startButton.setImageResource(R.drawable.jc_click_error_selector);
|
||||
} else {
|
||||
startButton.setImageResource(R.drawable.jc_click_play_selector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Dialog mProgressDialog;
|
||||
protected ProgressBar mDialogProgressBar;
|
||||
protected TextView mDialogSeekTime;
|
||||
protected TextView mDialogTotalTime;
|
||||
protected ImageView mDialogIcon;
|
||||
|
||||
@Override
|
||||
public void showProgressDialog(float deltaX, String seekTime, int seekTimePosition, String totalTime, int totalTimeDuration) {
|
||||
super.showProgressDialog(deltaX, seekTime, seekTimePosition, totalTime, totalTimeDuration);
|
||||
if (mProgressDialog == null) {
|
||||
View localView = LayoutInflater.from(getContext()).inflate(R.layout.jc_dialog_progress, null);
|
||||
mDialogProgressBar = ((ProgressBar) localView.findViewById(R.id.duration_progressbar));
|
||||
mDialogSeekTime = ((TextView) localView.findViewById(R.id.tv_current));
|
||||
mDialogTotalTime = ((TextView) localView.findViewById(R.id.tv_duration));
|
||||
mDialogIcon = ((ImageView) localView.findViewById(R.id.duration_image_tip));
|
||||
mProgressDialog = new Dialog(getContext(), R.style.jc_style_dialog_progress);
|
||||
mProgressDialog.setContentView(localView);
|
||||
mProgressDialog.getWindow().addFlags(Window.FEATURE_ACTION_BAR);
|
||||
mProgressDialog.getWindow().addFlags(32);
|
||||
mProgressDialog.getWindow().addFlags(16);
|
||||
mProgressDialog.getWindow().setLayout(-2, -2);
|
||||
WindowManager.LayoutParams localLayoutParams = mProgressDialog.getWindow().getAttributes();
|
||||
localLayoutParams.gravity = Gravity.CENTER;
|
||||
mProgressDialog.getWindow().setAttributes(localLayoutParams);
|
||||
}
|
||||
if (!mProgressDialog.isShowing()) {
|
||||
mProgressDialog.show();
|
||||
}
|
||||
|
||||
mDialogSeekTime.setText(seekTime);
|
||||
mDialogTotalTime.setText(" / " + totalTime);
|
||||
mDialogProgressBar.setProgress(totalTimeDuration <= 0 ? 0 : (seekTimePosition * 100 / totalTimeDuration));
|
||||
if (deltaX > 0) {
|
||||
mDialogIcon.setBackgroundResource(R.drawable.jc_forward_icon);
|
||||
} else {
|
||||
mDialogIcon.setBackgroundResource(R.drawable.jc_backward_icon);
|
||||
}
|
||||
onCLickUiToggleToClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissProgressDialog() {
|
||||
super.dismissProgressDialog();
|
||||
if (mProgressDialog != null) {
|
||||
mProgressDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
protected Dialog mVolumeDialog;
|
||||
protected ProgressBar mDialogVolumeProgressBar;
|
||||
protected TextView mDialogVolumeTextView;
|
||||
protected ImageView mDialogVolumeImageView;
|
||||
|
||||
@Override
|
||||
public void showVolumeDialog(float deltaY, int volumePercent) {
|
||||
super.showVolumeDialog(deltaY, volumePercent);
|
||||
if (mVolumeDialog == null) {
|
||||
View localView = LayoutInflater.from(getContext()).inflate(R.layout.jc_dialog_volume, null);
|
||||
mDialogVolumeImageView = ((ImageView) localView.findViewById(R.id.volume_image_tip));
|
||||
mDialogVolumeTextView = ((TextView) localView.findViewById(R.id.tv_volume));
|
||||
mDialogVolumeProgressBar = ((ProgressBar) localView.findViewById(R.id.volume_progressbar));
|
||||
mVolumeDialog = new Dialog(getContext(), R.style.jc_style_dialog_progress);
|
||||
mVolumeDialog.setContentView(localView);
|
||||
mVolumeDialog.getWindow().addFlags(8);
|
||||
mVolumeDialog.getWindow().addFlags(32);
|
||||
mVolumeDialog.getWindow().addFlags(16);
|
||||
mVolumeDialog.getWindow().setLayout(-2, -2);
|
||||
WindowManager.LayoutParams localLayoutParams = mVolumeDialog.getWindow().getAttributes();
|
||||
localLayoutParams.gravity = Gravity.CENTER;
|
||||
mVolumeDialog.getWindow().setAttributes(localLayoutParams);
|
||||
}
|
||||
if (!mVolumeDialog.isShowing()) {
|
||||
mVolumeDialog.show();
|
||||
}
|
||||
if (volumePercent <= 0) {
|
||||
mDialogVolumeImageView.setBackgroundResource(R.drawable.jc_close_volume);
|
||||
} else {
|
||||
mDialogVolumeImageView.setBackgroundResource(R.drawable.jc_add_volume);
|
||||
}
|
||||
if (volumePercent > 100) {
|
||||
volumePercent = 100;
|
||||
} else if (volumePercent < 0) {
|
||||
volumePercent = 0;
|
||||
}
|
||||
mDialogVolumeTextView.setText(volumePercent + "%");
|
||||
mDialogVolumeProgressBar.setProgress(volumePercent);
|
||||
onCLickUiToggleToClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissVolumeDialog() {
|
||||
super.dismissVolumeDialog();
|
||||
if (mVolumeDialog != null) {
|
||||
mVolumeDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
protected Dialog mBrightnessDialog;
|
||||
protected ProgressBar mDialogBrightnessProgressBar;
|
||||
protected TextView mDialogBrightnessTextView;
|
||||
|
||||
@Override
|
||||
public void showBrightnessDialog(int brightnessPercent) {
|
||||
super.showBrightnessDialog(brightnessPercent);
|
||||
if (mBrightnessDialog == null) {
|
||||
View localView = LayoutInflater.from(getContext()).inflate(R.layout.jc_dialog_brightness, null);
|
||||
mDialogBrightnessTextView = ((TextView) localView.findViewById(R.id.tv_brightness));
|
||||
mDialogBrightnessProgressBar = ((ProgressBar) localView.findViewById(R.id.brightness_progressbar));
|
||||
mBrightnessDialog = new Dialog(getContext(), R.style.jc_style_dialog_progress);
|
||||
mBrightnessDialog.setContentView(localView);
|
||||
mBrightnessDialog.getWindow().addFlags(Window.FEATURE_ACTION_BAR);
|
||||
mBrightnessDialog.getWindow().addFlags(32);
|
||||
mBrightnessDialog.getWindow().addFlags(16);
|
||||
mBrightnessDialog.getWindow().setLayout(-2, -2);
|
||||
WindowManager.LayoutParams localLayoutParams = mBrightnessDialog.getWindow().getAttributes();
|
||||
localLayoutParams.gravity = Gravity.CENTER;
|
||||
mBrightnessDialog.getWindow().setAttributes(localLayoutParams);
|
||||
|
||||
}
|
||||
if (!mBrightnessDialog.isShowing()) {
|
||||
mBrightnessDialog.show();
|
||||
}
|
||||
if (brightnessPercent > 100) {
|
||||
brightnessPercent = 100;
|
||||
} else if (brightnessPercent < 0) {
|
||||
brightnessPercent = 0;
|
||||
}
|
||||
mDialogBrightnessTextView.setText(brightnessPercent + "%");
|
||||
mDialogBrightnessProgressBar.setProgress(brightnessPercent);
|
||||
onCLickUiToggleToClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissBrightnessDialog() {
|
||||
super.dismissBrightnessDialog();
|
||||
if (mBrightnessDialog != null) {
|
||||
mBrightnessDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void startDismissControlViewTimer() {
|
||||
cancelDismissControlViewTimer();
|
||||
DISMISS_CONTROL_VIEW_TIMER = new Timer();
|
||||
mDismissControlViewTimerTask = new DismissControlViewTimerTask();
|
||||
DISMISS_CONTROL_VIEW_TIMER.schedule(mDismissControlViewTimerTask, 2500);
|
||||
}
|
||||
|
||||
public void cancelDismissControlViewTimer() {
|
||||
if (DISMISS_CONTROL_VIEW_TIMER != null) {
|
||||
DISMISS_CONTROL_VIEW_TIMER.cancel();
|
||||
}
|
||||
if (mDismissControlViewTimerTask != null) {
|
||||
mDismissControlViewTimerTask.cancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class DismissControlViewTimerTask extends TimerTask {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (currentState != CURRENT_STATE_NORMAL
|
||||
&& currentState != CURRENT_STATE_ERROR
|
||||
&& currentState != CURRENT_STATE_AUTO_COMPLETE) {
|
||||
if (getContext() != null && getContext() instanceof Activity) {
|
||||
((Activity) getContext()).runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
bottomContainer.setVisibility(View.INVISIBLE);
|
||||
topContainer.setVisibility(View.INVISIBLE);
|
||||
startButton.setVisibility(View.INVISIBLE);
|
||||
if (currentScreen != SCREEN_WINDOW_TINY) {
|
||||
bottomProgressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutoCompletion() {
|
||||
super.onAutoCompletion();
|
||||
cancelDismissControlViewTimer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompletion() {
|
||||
super.onCompletion();
|
||||
cancelDismissControlViewTimer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/linear_interpolator">
|
||||
<rotate
|
||||
android:duration="5"
|
||||
android:fromDegrees="0"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:toDegrees="-2" />
|
||||
</set>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/linear_interpolator">
|
||||
<rotate
|
||||
android:duration="20"
|
||||
android:fromDegrees="-2"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:toDegrees="0" />
|
||||
</set>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 260 B |
|
After Width: | Height: | Size: 317 B |
|
After Width: | Height: | Size: 531 B |
|
After Width: | Height: | Size: 486 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 717 B |
|
After Width: | Height: | Size: 167 B |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 958 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 922 B |
|
After Width: | Height: | Size: 946 B |
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<solid android:color="#a5ffffff" />
|
||||
<size android:height="4.0dip" />
|
||||
<corners android:radius="1.0dip" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/secondaryProgress">
|
||||
<clip>
|
||||
<shape>
|
||||
<solid android:color="#ffe0e0e0" />
|
||||
<size android:height="4.0dip" />
|
||||
<corners android:radius="1.0dip" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<solid android:color="#fff85959" />
|
||||
<size android:height="4.0dip" />
|
||||
<corners android:radius="1.0dip" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<solid android:color="#a5ffffff" />
|
||||
<size android:height="1.0dip" />
|
||||
<corners android:radius="1.5dip" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/secondaryProgress">
|
||||
<clip>
|
||||
<shape>
|
||||
<solid android:color="#ffffffff" />
|
||||
<size android:height="1.0dip" />
|
||||
<corners android:radius="1.5dip" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<solid android:color="#fff85959" />
|
||||
<size android:height="1.0dip" />
|
||||
<corners android:radius="1.5dip" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/jc_seek_thumb_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/jc_seek_thumb_normal" />
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/jc_back_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/jc_back_normal" />
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/jc_back_tiny_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/jc_back_tiny_normal" />
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/jc_error_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/jc_error_normal" />
|
||||
</selector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/jc_pause_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/jc_pause_normal" />
|
||||
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/jc_play_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/jc_play_normal" />
|
||||
</selector>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<solid android:color="#ffffffff" />
|
||||
<corners android:radius="2dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<solid android:color="#fff85959" />
|
||||
<corners android:radius="2dp" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#cc000000" />
|
||||
<corners
|
||||
android:bottomLeftRadius="6.0dip"
|
||||
android:bottomRightRadius="6.0dip"
|
||||
android:topLeftRadius="6.0dip"
|
||||
android:topRightRadius="6.0dip" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/jc_loading_bg"
|
||||
android:fromDegrees="0.0"
|
||||
android:pivotX="50.0%"
|
||||
android:pivotY="50.0%"
|
||||
android:toDegrees="360.0" />
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape android:shape="oval"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#ffffffff" />
|
||||
<size
|
||||
android:height="15.0dip"
|
||||
android:width="15.0dip" />
|
||||
</shape>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape android:shape="oval"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#fff0f0f0" />
|
||||
<size
|
||||
android:height="15.0dip"
|
||||
android:width="15.0dip" />
|
||||
</shape>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<solid android:color="#ffffffff" />
|
||||
<corners android:radius="2.0dip" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip
|
||||
android:clipOrientation="vertical"
|
||||
android:gravity="bottom">
|
||||
<shape>
|
||||
<solid android:color="#fff85959" />
|
||||
<corners android:radius="2.0dip" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/jc_dialog_progress_bg"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="155dp"
|
||||
android:layout_height="120dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="20dp"
|
||||
android:src="@drawable/jc_brightness_video" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_brightness"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/brightness_progressbar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="3dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:max="100"
|
||||
android:progressDrawable="@drawable/jc_dialog_progress" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/jc_dialog_progress_bg"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="152dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/duration_image_tip"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="27dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_current"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#fff85959"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/duration_progressbar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:max="100"
|
||||
android:progressDrawable="@drawable/jc_dialog_progress" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/jc_dialog_progress_bg"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="155dp"
|
||||
android:layout_height="120dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/volume_image_tip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="20dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_volume"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/volume_progressbar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="3dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:max="100"
|
||||
android:progressDrawable="@drawable/jc_dialog_progress" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/surface_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="#99000000"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:text="00:00"
|
||||
android:textColor="#ffffff" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/bottom_seek_progress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1.0"
|
||||
android:background="@null"
|
||||
android:max="100"
|
||||
android:maxHeight="4dp"
|
||||
android:minHeight="4dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:progressDrawable="@drawable/jc_bottom_seek_progress"
|
||||
android:thumb="@drawable/jc_bottom_seek_thumb" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="00:00"
|
||||
android:textColor="#ffffff" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fullscreen"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingRight="16dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/jc_enlarge" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/jc_title_bg"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:indeterminateDrawable="@drawable/jc_loading"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/start"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/jc_click_play_selector" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"
|
||||
android:descendantFocusability="blocksDescendants">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/surface_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="#000000"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="invisible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="14dp"
|
||||
android:text="00:00"
|
||||
android:textColor="#ffffff" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/bottom_seek_progress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1.0"
|
||||
android:background="@null"
|
||||
android:max="100"
|
||||
android:maxHeight="1.0dip"
|
||||
android:minHeight="1.0dip"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="22dp"
|
||||
android:paddingTop="8dp"
|
||||
android:progressDrawable="@drawable/jc_bottom_seek_progress"
|
||||
android:thumb="@drawable/jc_bottom_seek_thumb" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="00:00"
|
||||
android:textColor="#ffffff" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fullscreen"
|
||||
android:layout_width="24.5dp"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginLeft="14.0dip"
|
||||
android:layout_marginRight="14.0dip"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/jc_enlarge" />
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/bottom_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1.5dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:max="100"
|
||||
android:progressDrawable="@drawable/jc_bottom_progress" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_tiny"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/jc_click_back_tiny_selector"
|
||||
android:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="23dp"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="14dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/jc_click_back_selector" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading"
|
||||
android:layout_width="@dimen/jc_start_button_w_h_normal"
|
||||
android:layout_height="@dimen/jc_start_button_w_h_normal"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_below="@+id/layout_top"
|
||||
android:layout_marginTop="@dimen/top"
|
||||
android:indeterminateDrawable="@drawable/jc_loading"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/start"
|
||||
android:layout_width="@dimen/jc_start_button_w_h_normal"
|
||||
android:layout_height="@dimen/jc_start_button_w_h_normal"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_below="@+id/layout_top"
|
||||
android:layout_marginTop="@dimen/top"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/jc_click_play_selector" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="tips_not_wifi">Você está usando a rede móvel, você deseja mesmo ver o video?</string>
|
||||
<string name="tips_not_wifi_confirm">Continuar</string>
|
||||
<string name="tips_not_wifi_cancel">Parar</string>
|
||||
<string name="no_url">Sem Vídeo</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="tips_not_wifi">Şu anda mobil veriyi kullanıyorsunuz, yüksek veri kaybına yol açabilir</string>
|
||||
<string name="tips_not_wifi_confirm">Devam Et</string>
|
||||
<string name="tips_not_wifi_cancel">Durdur</string>
|
||||
<string name="no_url">URL Bulunamadı</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="tips_not_wifi">您当前正在使用移动网络,继续播放将消耗流量</string>
|
||||
<string name="tips_not_wifi_confirm">继续播放</string>
|
||||
<string name="tips_not_wifi_cancel">停止播放</string>
|
||||
<string name="no_url">播放地址无效</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<resources>
|
||||
<dimen name="jc_start_button_w_h_normal">45dp</dimen>
|
||||
<dimen name="jc_start_button_w_h_fullscreen">62dp</dimen>
|
||||
<dimen name="top">30dp</dimen>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="tips_not_wifi">You are currently using the mobile network, the player will continue to consume traffic</string>
|
||||
<string name="tips_not_wifi_confirm">Resume</string>
|
||||
<string name="tips_not_wifi_cancel">Stop play</string>
|
||||
<string name="no_url">No mUrl</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="jc_style_dialog_progress" parent="@android:style/Theme.Dialog">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowAnimationStyle">@style/jc_popup_toast_anim</item>
|
||||
<item name="android:backgroundDimEnabled">false</item>
|
||||
</style>
|
||||
|
||||
<style name="jc_popup_toast_anim" parent="@android:style/Animation">
|
||||
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
|
||||
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
|
||||
</style>
|
||||
|
||||
<style name="jc_vertical_progressBar">
|
||||
<item name="android:maxWidth">12dp</item>
|
||||
<item name="android:indeterminateOnly">false</item>
|
||||
<item name="android:indeterminateDrawable">
|
||||
@android:drawable/progress_indeterminate_horizontal
|
||||
</item>
|
||||
<item name="android:progressDrawable">@drawable/jc_volume_progress_bg</item>
|
||||
<item name="android:indeterminateDuration">3500</item>
|
||||
<item name="android:indeterminateBehavior">repeat</item>
|
||||
<item name="android:minWidth">1dp</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,15 @@
|
||||
package fm.jiecao.jcvideoplayer_lib;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* To work on unit tests, switch the Test Artifact in the Build Variants view.
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||