/... which would
76 | // conflict with src/ being used by the main source set.
77 | // Adding new build types or product flavors should be accompanied
78 | // by a similar customization.
79 | debug.setRoot('build-types/debug')
80 | release.setRoot('build-types/release')
81 | }
82 |
83 | lintOptions {
84 | checkReleaseBuilds false
85 | abortOnError false
86 | // if true, only report errors
87 | ignoreWarnings true
88 | }
89 | }
90 |
91 |
92 |
93 | dependencies {
94 | implementation fileTree(dir: 'libs', include: ['*.jar'])
95 | // 基础库
96 | implementation project(':videoplayer')
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/app/keystore/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/app/keystore/keystore.jks
--------------------------------------------------------------------------------
/app/libs/Baidu_MobAds_SDK.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/app/libs/Baidu_MobAds_SDK.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Develop\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/res/layout/activity_player.xml:
--------------------------------------------------------------------------------
1 |
18 |
22 |
23 |
24 |
28 |
29 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/app/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/app/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 | #3F51B5
21 | #303F9F
22 | #FF4081
23 |
24 |
--------------------------------------------------------------------------------
/app/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 | 16dp
21 | 16dp
22 |
23 |
--------------------------------------------------------------------------------
/app/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 | VideoPlayerSample
20 |
21 |
--------------------------------------------------------------------------------
/app/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/com/ishow/sample/videoplayer/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.ishow.sample.videoplayer;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.widget.RelativeLayout;
8 |
9 | import com.baidu.mobads.SplashAd;
10 | import com.baidu.mobads.SplashAdListener;
11 | import com.ishow.sample.videoplayer.constant.Configure;
12 |
13 | /**
14 | * 实时开屏,广告实时请求并且立即展现
15 | */
16 | public class SplashActivity extends Activity {
17 | private static final String TAG = "SplashActivity";
18 |
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 |
23 | if (!Configure.SHOW_BAIDU_AD) {
24 | Intent intent = new Intent(SplashActivity.this, VideoActivity.class);
25 | startActivity(intent);
26 | SplashActivity.this.finish();
27 | finish();
28 | return;
29 | }
30 |
31 | setContentView(R.layout.activity_splash);
32 | RelativeLayout adContent = (RelativeLayout) this.findViewById(R.id.ad);
33 | new SplashAd(this, adContent, mSplashAdListener, Configure.BAIDU_SPLASH_ID, true);
34 | }
35 |
36 | /**
37 | * 监听
38 | */
39 | private SplashAdListener mSplashAdListener = new SplashAdListener() {
40 | @Override
41 | public void onAdDismissed() {
42 | Log.i(TAG, "onAdDismissed");
43 | Intent intent = new Intent(SplashActivity.this, VideoActivity.class);
44 | startActivity(intent);
45 | SplashActivity.this.finish();
46 | }
47 |
48 | @Override
49 | public void onAdFailed(String arg0) {
50 | Log.i(TAG, "onAdFailed");
51 | Intent intent = new Intent(SplashActivity.this, VideoActivity.class);
52 | startActivity(intent);
53 | SplashActivity.this.finish();
54 | }
55 |
56 | @Override
57 | public void onAdPresent() {
58 | Log.i(TAG, "onAdPresent");
59 | }
60 |
61 | @Override
62 | public void onAdClick() {
63 | Log.i("SplashActivity", "onAdClick");
64 | // 设置开屏可接受点击时,该回调可用
65 | }
66 | };
67 |
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/com/ishow/sample/videoplayer/VideoActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.sample.videoplayer;
20 |
21 | import android.content.res.Configuration;
22 | import android.os.Bundle;
23 | import android.os.Handler;
24 | import android.support.v7.app.AppCompatActivity;
25 | import android.util.Log;
26 | import android.view.View;
27 |
28 | import com.baidu.mobads.AdSize;
29 | import com.baidu.mobads.InterstitialAd;
30 | import com.ishow.sample.videoplayer.constant.Configure;
31 | import com.ishow.sample.videoplayer.listener.VideoBeforeListener;
32 | import com.ishow.sample.videoplayer.listener.VideoPauseListener;
33 | import com.ishow.videoplayer.utils.ScreenOrientationUtils;
34 | import com.ishow.videoplayer.widget.MediaController;
35 | import com.ishow.videoplayer.widget.media.VideoView;
36 |
37 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
38 |
39 | public class VideoActivity extends AppCompatActivity {
40 | private static final String TAG = "VideoActivity";
41 | private MediaController mMediaController;
42 | private VideoView mVideoView;
43 | private InterstitialAd mBaiduBeforeAd;
44 | private InterstitialAd mBaiduPauseAd;
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | setContentView(R.layout.activity_player);
50 |
51 | // init UI
52 | mMediaController = new MediaController(this);
53 | mMediaController.setCallBack(mCallBack);
54 | mMediaController.setPlayNextVisibility(View.GONE);
55 | mMediaController.setTitle("加勒比海盗4");
56 |
57 | mVideoView = (VideoView) findViewById(R.id.video_view);
58 | mVideoView.setMediaController(mMediaController);
59 | // prefer mVideoPath
60 | //mVideoView.setVideoPath("http://wx.pinet.cc:8081/plife2/vieos/加勒比海盗4惊涛怪浪/playlist.m3u8");
61 | mVideoView.setVideoPath("http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear4/prog_index.m3u8");
62 |
63 | mVideoView.start();
64 | createAd();
65 | }
66 |
67 | @Override
68 | protected void onResume() {
69 | super.onResume();
70 |
71 | if (!Configure.SHOW_BAIDU_AD) {
72 | Log.i(TAG, "onResume: Configure.SHOW_BAIDU_AD is false");
73 | return;
74 | }
75 |
76 | mHandler.postDelayed(new Runnable() {
77 | @Override
78 | public void run() {
79 | Log.i(TAG, "run: postDelayed");
80 | mBaiduBeforeAd.loadAdForVideoApp(mVideoView.getWidth(), mVideoView.getHeight());
81 | mBaiduPauseAd.loadAdForVideoApp(mVideoView.getWidth(), mVideoView.getHeight());
82 | }
83 | }, 500);
84 | }
85 |
86 | private Handler mHandler = new Handler() {
87 | };
88 |
89 | @Override
90 | protected void onStop() {
91 | super.onStop();
92 | if (mVideoView.canPause()) {
93 | mVideoView.pause();
94 | }
95 | }
96 |
97 | @Override
98 | public void onBackPressed() {
99 | if (ScreenOrientationUtils.isLandscape(this)) {
100 | mMediaController.changePortrait(false);
101 | } else {
102 | super.onBackPressed();
103 | }
104 | }
105 |
106 | @Override
107 | protected void onDestroy() {
108 | mVideoView.stopPlayback();
109 | mVideoView.release(true);
110 | IjkMediaPlayer.native_profileEnd();
111 | super.onDestroy();
112 | }
113 |
114 | @Override
115 | public void onConfigurationChanged(Configuration newConfig) {
116 | super.onConfigurationChanged(newConfig);
117 | // 切换到横屏
118 | if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
119 | mMediaController.changeLand(true);
120 | } else {
121 | mMediaController.changePortrait(true);
122 | }
123 | }
124 |
125 |
126 | private MediaController.CallBack mCallBack = new MediaController.CallBack() {
127 | @Override
128 | public void onPlay(boolean isPlaying) {
129 | if (!isPlaying && Configure.SHOW_BAIDU_AD) {
130 | mBaiduPauseAd.showAdInParentForVideoApp(VideoActivity.this, mMediaController.getAdView());
131 | }
132 | }
133 |
134 | @Override
135 | public void onComplete() {
136 |
137 | }
138 |
139 | @Override
140 | public void onPlayNext() {
141 |
142 | }
143 | };
144 |
145 | private void createAd() {
146 | if (!Configure.SHOW_BAIDU_AD) {
147 | Log.i(TAG, "createAd: Configure.SHOW_BAIDU_AD is false");
148 | return;
149 | }
150 | mBaiduBeforeAd = new InterstitialAd(this, AdSize.InterstitialForVideoBeforePlay, Configure.BAIDU_VIDEO_ID);
151 | mBaiduBeforeAd.setListener(new VideoBeforeListener(this, mMediaController, mBaiduBeforeAd, mVideoView));
152 |
153 | mBaiduPauseAd = new InterstitialAd(this, AdSize.InterstitialForVideoPausePlay, Configure.BAIDU_VIDEO_ID);
154 | mBaiduPauseAd.setListener(new VideoPauseListener(mBaiduPauseAd, mVideoView));
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/app/src/com/ishow/sample/videoplayer/constant/Configure.java:
--------------------------------------------------------------------------------
1 | package com.ishow.sample.videoplayer.constant;
2 |
3 | /**
4 | * Created by Bright.Yu on 2016/3/17.
5 | */
6 | public class Configure {
7 | /**
8 | * 百度广告 是否打开使用
9 | */
10 | public static final boolean SHOW_BAIDU_AD = true;
11 | /**
12 | * 百度Demo中的ID:2058622,个人ID:2431064
13 | */
14 | public static final String BAIDU_SPLASH_ID = "2058622";
15 |
16 | /**
17 | * 百度Demo中的ID:2058626 ,个人ID:2431069
18 | */
19 | public static final String BAIDU_VIDEO_ID = "2058626";
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/com/ishow/sample/videoplayer/listener/VideoBeforeListener.java:
--------------------------------------------------------------------------------
1 | package com.ishow.sample.videoplayer.listener;
2 |
3 | import android.app.Activity;
4 | import android.util.Log;
5 |
6 | import com.baidu.mobads.InterstitialAd;
7 | import com.baidu.mobads.InterstitialAdListener;
8 | import com.ishow.videoplayer.widget.MediaController;
9 | import com.ishow.videoplayer.widget.media.VideoView;
10 |
11 | /**
12 | * Created by yuhaiyang on 2016/3/8.
13 | */
14 | public class VideoBeforeListener implements InterstitialAdListener {
15 | private static final String TAG = "VideoBeforeListener";
16 | private InterstitialAd mBaiduAd;
17 | private VideoView mVideoView;
18 | private Activity mActivity;
19 | private MediaController mMediaController;
20 |
21 | public VideoBeforeListener(Activity activity, MediaController controller, InterstitialAd ad, VideoView videoView) {
22 | mBaiduAd = ad;
23 | mVideoView = videoView;
24 |
25 | mActivity = activity;
26 | mMediaController = controller;
27 | if(!mBaiduAd.isAdReady()) {
28 | mBaiduAd.loadAdForVideoApp(mVideoView.getWidth(), mVideoView.getHeight());
29 | }else{
30 | mBaiduAd.showAdInParentForVideoApp(mActivity, mMediaController.getAdView());
31 | }
32 | }
33 |
34 | @Override
35 | public void onAdReady() {
36 | Log.i(TAG, "onAdReady: ");
37 | mBaiduAd.showAdInParentForVideoApp(mActivity, mMediaController.getAdView());
38 | }
39 |
40 | @Override
41 | public void onAdPresent() {
42 | Log.i(TAG, "onAdPresent: ");
43 | mVideoView.pause();
44 | }
45 |
46 | @Override
47 | public void onAdClick(InterstitialAd interstitialAd) {
48 | Log.i(TAG, "onAdClick: ");
49 | }
50 |
51 | @Override
52 | public void onAdDismissed() {
53 | Log.i(TAG, "onAdDismissed: ");
54 | mVideoView.start();
55 | }
56 |
57 | @Override
58 | public void onAdFailed(String s) {
59 | Log.i(TAG, "onAdFailed: ");
60 | mVideoView.start();
61 | mBaiduAd.loadAdForVideoApp(mVideoView.getWidth(), mVideoView.getHeight());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/com/ishow/sample/videoplayer/listener/VideoPauseListener.java:
--------------------------------------------------------------------------------
1 | package com.ishow.sample.videoplayer.listener;
2 |
3 | import android.util.Log;
4 |
5 | import com.baidu.mobads.InterstitialAd;
6 | import com.baidu.mobads.InterstitialAdListener;
7 | import com.ishow.videoplayer.widget.media.VideoView;
8 |
9 | /**
10 | * Created by yuhaiyang on 2016/3/8.
11 | */
12 | public class VideoPauseListener implements InterstitialAdListener {
13 | private static final String TAG = "VideoPauseListener";
14 | private InterstitialAd mBaiduAd;
15 | private VideoView mVideoView;
16 |
17 | public VideoPauseListener(InterstitialAd ad, VideoView videoView) {
18 | mBaiduAd = ad;
19 | mVideoView = videoView;
20 | }
21 |
22 | @Override
23 | public void onAdReady() {
24 | Log.i(TAG, "onAdReady: ");
25 | }
26 |
27 | @Override
28 | public void onAdPresent() {
29 | Log.i(TAG, "onAdPresent: ");
30 | }
31 |
32 | @Override
33 | public void onAdClick(InterstitialAd interstitialAd) {
34 | Log.i(TAG, "onAdClick: ");
35 | }
36 |
37 | @Override
38 | public void onAdDismissed() {
39 | Log.i(TAG, "onAdDismissed: ");
40 | mVideoView.setShowAction();
41 | mBaiduAd.loadAdForVideoApp(mVideoView.getWidth(), mVideoView.getHeight());
42 | }
43 |
44 | @Override
45 | public void onAdFailed(String s) {
46 | Log.i(TAG, "onAdFailed: ");
47 | mBaiduAd.loadAdForVideoApp(mVideoView.getWidth(), mVideoView.getHeight());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
20 |
21 | buildscript {
22 | repositories {
23 | jcenter()
24 | google()
25 | }
26 | dependencies {
27 | classpath 'com.android.tools.build:gradle:3.1.1'
28 | }
29 | }
30 |
31 | allprojects {
32 | repositories {
33 | jcenter()
34 | google()
35 | }
36 |
37 | // Javadoc设定为UTF-8了
38 | tasks.withType(Javadoc) {
39 | options.addStringOption('Xdoclint:none', '-quiet')
40 | options.addStringOption('encoding', 'UTF-8')
41 | }
42 | }
43 |
44 | task clean(type: Delete) {
45 | delete rootProject.buildDir
46 | }
47 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2016 The yuhaiyang Android Source Project
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # @author: y.haiyang@qq.com
17 | #
18 |
19 | # Project-wide Gradle settings.
20 |
21 | # IDE (e.g. Android Studio) users:
22 | # Gradle settings configured through the IDE *will override*
23 | # any settings specified in this file.
24 |
25 | # For more details on how to configure your build environment visit
26 | # http://www.gradle.org/docs/current/userguide/build_environment.html
27 |
28 | # Specifies the JVM arguments used for the daemon process.
29 | # The setting is particularly useful for tweaking memory settings.
30 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
31 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
32 |
33 | # When configured, Gradle will run in incubating parallel mode.
34 | # This option should only be used with decoupled projects. More details, visit
35 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
36 | # org.gradle.parallel=true
37 | #############################################################################
38 | # 通用 配置
39 | #############################################################################
40 | # 版本号 **************************重要配置一定要长****************************
41 | JCENTER_VERSION=0.0.3
42 |
43 | VERSION_NAME=0.0.3
44 | # 最低SDK版本
45 | MIN_SDK_VERSION=15
46 | # 目标编译版本
47 | TARGET_SDK_VERSION=22
48 | #编译版本
49 | COMPILE_SDK_VERSION=27
50 | # 编译工具版本
51 | BUILD_TOOLS_VERSION=27.0.3
52 | # Android 版本包(去除V4和V7 其他的暂用这一个)
53 | ANDOID_SUPPORT_VERSION=27.1.1
54 | # Android V4包的版本
55 | SUPPORT_V4_VERSION=27.1.1
56 | # Android V7包的版本
57 | SUPPORT_V7_VERSION=27.1.1
58 | #############################################################################
59 | # 正式发布版本 配置
60 | #############################################################################
61 | # 签名配置
62 | RELEASE_STOREFILE=keystore/keystore.jks
63 | RELEASE_STORE_PASSWORD=123456789
64 | RELEASE_KEY_ALIAS=yuhaiyang
65 | RELEASE_KEY_PASSWORD=123456789
66 |
67 | # applicationId
68 | RELEASE_APPLICATION_ID=com.ishow.sample.videoplayer
69 | #############################################################################
70 | # 测试发布版本 配置
71 | #############################################################################
72 | # applicationId
73 | DEV_APPLICATION_ID=com.ishow.sample.videoplayer
74 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 16 18:15:26 GMT+08:00 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/images/01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/images/01.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | include ':videoplayer'
20 | include ':app'
21 |
22 |
--------------------------------------------------------------------------------
/videoplayer/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
--------------------------------------------------------------------------------
/videoplayer/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | apply plugin: 'com.android.library'
20 |
21 | android {
22 | compileSdkVersion COMPILE_SDK_VERSION as int
23 | buildToolsVersion BUILD_TOOLS_VERSION
24 |
25 | defaultConfig {
26 | minSdkVersion MIN_SDK_VERSION as int
27 | targetSdkVersion TARGET_SDK_VERSION as int
28 | }
29 |
30 |
31 | sourceSets {
32 | main {
33 | manifest.srcFile 'AndroidManifest.xml'
34 | java.srcDirs = ['src']
35 | resources.srcDirs = ['src']
36 | aidl.srcDirs = ['src']
37 | renderscript.srcDirs = ['src']
38 | res.srcDirs = ['res']
39 | assets.srcDirs = ['assets']
40 | jniLibs.srcDirs = ['libs']
41 | }
42 |
43 | debug.setRoot('build-types/debug')
44 | release.setRoot('build-types/release')
45 | }
46 | buildToolsVersion '27.0.3'
47 | }
48 |
49 | // 编译的时候使用UTF-8
50 | tasks.withType(JavaCompile) {
51 | options.encoding = "UTF-8"
52 | }
53 |
54 | dependencies {
55 | api fileTree(dir: 'libs', include: ['*.jar'])
56 |
57 | api "com.android.support:appcompat-v7:${SUPPORT_V7_VERSION}"
58 | api "com.android.support:support-annotations:${SUPPORT_V7_VERSION}"
59 |
60 | api 'tv.danmaku.ijk.media:ijkplayer-exo:0.5.1'
61 | // required, enough for most devices.
62 | api 'tv.danmaku.ijk.media:ijkplayer-java:0.5.1'
63 | api 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.5.1'
64 | // Other ABIs: optional
65 | //compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.4.5.1'
66 | //compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.4.5.1'
67 | //compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.4.5.1'
68 | }
69 |
--------------------------------------------------------------------------------
/videoplayer/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /opt/android/ADK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_backward.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_backward.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_forward.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_forward.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_play_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_play_pause.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_play_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_play_play.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_to_fullscreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_to_fullscreen.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_to_smallscreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_to_smallscreen.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_video_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_video_back.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_video_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_video_loading.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/ic_vidoe_play_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/ic_vidoe_play_next.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/normal_panel_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/normal_panel_bg.9.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable-xhdpi/progress_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-show/android-IJKplayerSample/a02ba1a4bc838ed028d97dc51a2d6b1ed7bed623/videoplayer/res/drawable-xhdpi/progress_thumb.png
--------------------------------------------------------------------------------
/videoplayer/res/drawable/progress_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 | -
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | -
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | -
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/videoplayer/res/drawable/video_loading.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
25 |
--------------------------------------------------------------------------------
/videoplayer/res/layout/media_controller.xml:
--------------------------------------------------------------------------------
1 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/videoplayer/res/layout/media_controller_ad.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
25 |
--------------------------------------------------------------------------------
/videoplayer/res/layout/media_controller_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
27 |
28 |
29 |
36 |
37 |
--------------------------------------------------------------------------------
/videoplayer/res/layout/media_controller_normal.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
25 |
26 |
32 |
33 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
59 |
60 |
69 |
70 |
76 |
77 |
82 |
83 |
84 |
93 |
94 |
107 |
108 |
117 |
118 |
127 |
128 |
--------------------------------------------------------------------------------
/videoplayer/res/layout/media_controller_slide.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
22 |
23 |
24 |
29 |
30 |
38 |
39 |
45 |
46 |
51 |
52 |
58 |
59 |
67 |
68 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/videoplayer/res/values-sw240dp/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 0.67dp
20 | 1.33dp
21 | 2.00dp
22 | 2.67dp
23 | 3.33dp
24 | 4.00dp
25 | 4.67dp
26 | 5.33dp
27 | 6.00dp
28 | 6.67dp
29 | 7.33dp
30 | 8.00dp
31 | 8.67dp
32 | 9.33dp
33 | 10.00dp
34 | 10.67dp
35 | 11.33dp
36 | 12.00dp
37 | 12.67dp
38 | 13.33dp
39 | 14.00dp
40 | 14.67dp
41 | 15.33dp
42 | 16.00dp
43 | 16.67dp
44 | 17.33dp
45 | 18.00dp
46 | 18.67dp
47 | 19.33dp
48 | 20.00dp
49 | 20.67dp
50 | 21.33dp
51 | 22.00dp
52 | 22.67dp
53 | 23.33dp
54 | 24.00dp
55 | 24.67dp
56 | 25.33dp
57 | 26.00dp
58 | 26.67dp
59 | 27.33dp
60 | 28.00dp
61 | 28.67dp
62 | 29.33dp
63 | 30.00dp
64 | 30.67dp
65 | 31.33dp
66 | 32.00dp
67 | 32.67dp
68 | 33.33dp
69 | 34.00dp
70 | 34.67dp
71 | 35.33dp
72 | 36.00dp
73 | 36.67dp
74 | 37.33dp
75 | 38.00dp
76 | 38.67dp
77 | 39.33dp
78 | 40.00dp
79 | 40.67dp
80 | 41.33dp
81 | 42.00dp
82 | 42.67dp
83 | 43.33dp
84 | 44.00dp
85 | 44.67dp
86 | 45.33dp
87 | 46.00dp
88 | 46.67dp
89 | 47.33dp
90 | 48.00dp
91 | 48.67dp
92 | 49.33dp
93 | 50.00dp
94 | 50.67dp
95 | 51.33dp
96 | 52.00dp
97 | 52.67dp
98 | 53.33dp
99 | 54.00dp
100 | 54.67dp
101 | 55.33dp
102 | 56.00dp
103 | 56.67dp
104 | 57.33dp
105 | 58.00dp
106 | 58.67dp
107 | 59.33dp
108 | 60.00dp
109 | 60.67dp
110 | 61.33dp
111 | 62.00dp
112 | 62.67dp
113 | 63.33dp
114 | 64.00dp
115 | 64.67dp
116 | 65.33dp
117 | 66.00dp
118 | 66.67dp
119 | 67.33dp
120 | 68.00dp
121 | 68.67dp
122 | 69.33dp
123 | 70.00dp
124 | 70.67dp
125 | 71.33dp
126 | 72.00dp
127 | 72.67dp
128 | 73.33dp
129 | 74.00dp
130 | 74.67dp
131 | 75.33dp
132 | 76.00dp
133 | 76.67dp
134 | 77.33dp
135 | 78.00dp
136 | 78.67dp
137 | 79.33dp
138 | 80.00dp
139 | 80.67dp
140 | 81.33dp
141 | 82.00dp
142 | 82.67dp
143 | 83.33dp
144 | 84.00dp
145 | 84.67dp
146 | 85.33dp
147 | 86.00dp
148 | 86.67dp
149 | 87.33dp
150 | 88.00dp
151 | 88.67dp
152 | 89.33dp
153 | 90.00dp
154 | 90.67dp
155 | 91.33dp
156 | 92.00dp
157 | 92.67dp
158 | 93.33dp
159 | 94.00dp
160 | 94.67dp
161 | 95.33dp
162 | 96.00dp
163 | 96.67dp
164 | 97.33dp
165 | 98.00dp
166 | 98.67dp
167 | 99.33dp
168 | 100.00dp
169 | 100.67dp
170 | 101.33dp
171 | 102.00dp
172 | 102.67dp
173 | 103.33dp
174 | 104.00dp
175 | 104.67dp
176 | 105.33dp
177 | 106.00dp
178 | 106.67dp
179 | 107.33dp
180 | 108.00dp
181 | 108.67dp
182 | 109.33dp
183 | 110.00dp
184 | 110.67dp
185 | 111.33dp
186 | 112.00dp
187 | 112.67dp
188 | 113.33dp
189 | 114.00dp
190 | 114.67dp
191 | 115.33dp
192 | 116.00dp
193 | 116.67dp
194 | 117.33dp
195 | 118.00dp
196 | 118.67dp
197 | 119.33dp
198 | 120.00dp
199 | 120.67dp
200 | 121.33dp
201 | 122.00dp
202 | 122.67dp
203 | 123.33dp
204 | 124.00dp
205 | 124.67dp
206 | 125.33dp
207 | 126.00dp
208 | 126.67dp
209 | 127.33dp
210 | 128.00dp
211 | 128.67dp
212 | 129.33dp
213 | 130.00dp
214 | 130.67dp
215 | 131.33dp
216 | 132.00dp
217 | 132.67dp
218 | 133.33dp
219 | 134.00dp
220 | 134.67dp
221 | 135.33dp
222 | 136.00dp
223 | 136.67dp
224 | 137.33dp
225 | 138.00dp
226 | 138.67dp
227 | 139.33dp
228 | 140.00dp
229 | 140.67dp
230 | 141.33dp
231 | 142.00dp
232 | 142.67dp
233 | 143.33dp
234 | 144.00dp
235 | 144.67dp
236 | 145.33dp
237 | 146.00dp
238 | 146.67dp
239 | 147.33dp
240 | 148.00dp
241 | 148.67dp
242 | 149.33dp
243 | 150.00dp
244 | 150.67dp
245 | 151.33dp
246 | 152.00dp
247 | 152.67dp
248 | 153.33dp
249 | 154.00dp
250 | 154.67dp
251 | 155.33dp
252 | 156.00dp
253 | 156.67dp
254 | 157.33dp
255 | 158.00dp
256 | 158.67dp
257 | 159.33dp
258 | 160.00dp
259 | 160.67dp
260 | 161.33dp
261 | 162.00dp
262 | 162.67dp
263 | 163.33dp
264 | 164.00dp
265 | 164.67dp
266 | 165.33dp
267 | 166.00dp
268 | 166.67dp
269 | 167.33dp
270 | 168.00dp
271 | 168.67dp
272 | 169.33dp
273 | 170.00dp
274 | 170.67dp
275 | 171.33dp
276 | 172.00dp
277 | 172.67dp
278 | 173.33dp
279 | 174.00dp
280 | 174.67dp
281 | 175.33dp
282 | 176.00dp
283 | 176.67dp
284 | 177.33dp
285 | 178.00dp
286 | 178.67dp
287 | 179.33dp
288 | 180.00dp
289 | 180.67dp
290 | 181.33dp
291 | 182.00dp
292 | 182.67dp
293 | 183.33dp
294 | 184.00dp
295 | 184.67dp
296 | 185.33dp
297 | 186.00dp
298 | 186.67dp
299 | 187.33dp
300 | 188.00dp
301 | 188.67dp
302 | 189.33dp
303 | 190.00dp
304 | 190.67dp
305 | 191.33dp
306 | 192.00dp
307 | 192.67dp
308 | 193.33dp
309 | 194.00dp
310 | 194.67dp
311 | 195.33dp
312 | 196.00dp
313 | 196.67dp
314 | 197.33dp
315 | 198.00dp
316 | 198.67dp
317 | 199.33dp
318 | 200.00dp
319 | 200.67dp
320 | 201.33dp
321 | 202.00dp
322 | 202.67dp
323 | 203.33dp
324 | 204.00dp
325 | 204.67dp
326 | 205.33dp
327 | 206.00dp
328 | 206.67dp
329 | 207.33dp
330 | 208.00dp
331 | 208.67dp
332 | 209.33dp
333 | 210.00dp
334 | 210.67dp
335 | 211.33dp
336 | 212.00dp
337 | 212.67dp
338 | 213.33dp
339 | 214.00dp
340 | 214.67dp
341 | 215.33dp
342 | 216.00dp
343 | 216.67dp
344 | 217.33dp
345 | 218.00dp
346 | 218.67dp
347 | 219.33dp
348 | 220.00dp
349 | 220.67dp
350 | 221.33dp
351 | 222.00dp
352 | 222.67dp
353 | 223.33dp
354 | 224.00dp
355 | 224.67dp
356 | 225.33dp
357 | 226.00dp
358 | 226.67dp
359 | 227.33dp
360 | 228.00dp
361 | 228.67dp
362 | 229.33dp
363 | 230.00dp
364 | 230.67dp
365 | 231.33dp
366 | 232.00dp
367 | 232.67dp
368 | 233.33dp
369 | 234.00dp
370 | 234.67dp
371 | 235.33dp
372 | 236.00dp
373 | 236.67dp
374 | 237.33dp
375 | 238.00dp
376 | 238.67dp
377 | 239.33dp
378 | 240.00dp
379 | 240.67dp
380 | 241.33dp
381 | 242.00dp
382 | 242.67dp
383 | 243.33dp
384 | 244.00dp
385 | 244.67dp
386 | 245.33dp
387 | 246.00dp
388 | 246.67dp
389 | 247.33dp
390 | 248.00dp
391 | 248.67dp
392 | 249.33dp
393 | 250.00dp
394 | 250.67dp
395 | 251.33dp
396 | 252.00dp
397 | 252.67dp
398 | 253.33dp
399 | 254.00dp
400 | 254.67dp
401 | 255.33dp
402 | 256.00dp
403 | 256.67dp
404 | 257.33dp
405 | 258.00dp
406 | 258.67dp
407 | 259.33dp
408 | 260.00dp
409 | 260.67dp
410 | 261.33dp
411 | 262.00dp
412 | 262.67dp
413 | 263.33dp
414 | 264.00dp
415 | 264.67dp
416 | 265.33dp
417 | 266.00dp
418 | 266.67dp
419 | 267.33dp
420 | 268.00dp
421 | 268.67dp
422 | 269.33dp
423 | 270.00dp
424 | 270.67dp
425 | 271.33dp
426 | 272.00dp
427 | 272.67dp
428 | 273.33dp
429 | 274.00dp
430 | 274.67dp
431 | 275.33dp
432 | 276.00dp
433 | 276.67dp
434 | 277.33dp
435 | 278.00dp
436 | 278.67dp
437 | 279.33dp
438 | 280.00dp
439 | 280.67dp
440 | 281.33dp
441 | 282.00dp
442 | 282.67dp
443 | 283.33dp
444 | 284.00dp
445 | 284.67dp
446 | 285.33dp
447 | 286.00dp
448 | 286.67dp
449 | 287.33dp
450 | 288.00dp
451 | 288.67dp
452 | 289.33dp
453 | 290.00dp
454 | 290.67dp
455 | 291.33dp
456 | 292.00dp
457 | 292.67dp
458 | 293.33dp
459 | 294.00dp
460 | 294.67dp
461 | 295.33dp
462 | 296.00dp
463 | 296.67dp
464 | 297.33dp
465 | 298.00dp
466 | 298.67dp
467 | 299.33dp
468 | 300.00dp
469 | 300.67dp
470 | 301.33dp
471 | 302.00dp
472 | 302.67dp
473 | 303.33dp
474 | 304.00dp
475 | 304.67dp
476 | 305.33dp
477 | 306.00dp
478 | 306.67dp
479 | 307.33dp
480 | 308.00dp
481 | 308.67dp
482 | 309.33dp
483 | 310.00dp
484 | 310.67dp
485 | 311.33dp
486 | 312.00dp
487 | 312.67dp
488 | 313.33dp
489 | 314.00dp
490 | 314.67dp
491 | 315.33dp
492 | 316.00dp
493 | 316.67dp
494 | 317.33dp
495 | 318.00dp
496 | 318.67dp
497 | 319.33dp
498 | 320.00dp
499 | 320.67dp
500 | 321.33dp
501 | 322.00dp
502 | 322.67dp
503 | 323.33dp
504 | 324.00dp
505 | 324.67dp
506 | 325.33dp
507 | 326.00dp
508 | 326.67dp
509 | 327.33dp
510 | 328.00dp
511 | 328.67dp
512 | 329.33dp
513 | 330.00dp
514 | 330.67dp
515 | 331.33dp
516 | 332.00dp
517 | 332.67dp
518 | 333.33dp
519 |
--------------------------------------------------------------------------------
/videoplayer/res/values-sw320dp/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 0.89dp
20 | 1.78dp
21 | 2.67dp
22 | 3.56dp
23 | 4.44dp
24 | 5.33dp
25 | 6.22dp
26 | 7.11dp
27 | 8.00dp
28 | 8.89dp
29 | 9.78dp
30 | 10.67dp
31 | 11.56dp
32 | 12.44dp
33 | 13.33dp
34 | 14.22dp
35 | 15.11dp
36 | 16.00dp
37 | 16.89dp
38 | 17.78dp
39 | 18.67dp
40 | 19.56dp
41 | 20.44dp
42 | 21.33dp
43 | 22.22dp
44 | 23.11dp
45 | 24.00dp
46 | 24.89dp
47 | 25.78dp
48 | 26.67dp
49 | 27.56dp
50 | 28.44dp
51 | 29.33dp
52 | 30.22dp
53 | 31.11dp
54 | 32.00dp
55 | 32.89dp
56 | 33.78dp
57 | 34.67dp
58 | 35.56dp
59 | 36.44dp
60 | 37.33dp
61 | 38.22dp
62 | 39.11dp
63 | 40.00dp
64 | 40.89dp
65 | 41.78dp
66 | 42.67dp
67 | 43.56dp
68 | 44.44dp
69 | 45.33dp
70 | 46.22dp
71 | 47.11dp
72 | 48.00dp
73 | 48.89dp
74 | 49.78dp
75 | 50.67dp
76 | 51.56dp
77 | 52.44dp
78 | 53.33dp
79 | 54.22dp
80 | 55.11dp
81 | 56.00dp
82 | 56.89dp
83 | 57.78dp
84 | 58.67dp
85 | 59.56dp
86 | 60.44dp
87 | 61.33dp
88 | 62.22dp
89 | 63.11dp
90 | 64.00dp
91 | 64.89dp
92 | 65.78dp
93 | 66.67dp
94 | 67.56dp
95 | 68.44dp
96 | 69.33dp
97 | 70.22dp
98 | 71.11dp
99 | 72.00dp
100 | 72.89dp
101 | 73.78dp
102 | 74.67dp
103 | 75.56dp
104 | 76.44dp
105 | 77.33dp
106 | 78.22dp
107 | 79.11dp
108 | 80.00dp
109 | 80.89dp
110 | 81.78dp
111 | 82.67dp
112 | 83.56dp
113 | 84.44dp
114 | 85.33dp
115 | 86.22dp
116 | 87.11dp
117 | 88.00dp
118 | 88.89dp
119 | 89.78dp
120 | 90.67dp
121 | 91.56dp
122 | 92.44dp
123 | 93.33dp
124 | 94.22dp
125 | 95.11dp
126 | 96.00dp
127 | 96.89dp
128 | 97.78dp
129 | 98.67dp
130 | 99.56dp
131 | 100.44dp
132 | 101.33dp
133 | 102.22dp
134 | 103.11dp
135 | 104.00dp
136 | 104.89dp
137 | 105.78dp
138 | 106.67dp
139 | 107.56dp
140 | 108.44dp
141 | 109.33dp
142 | 110.22dp
143 | 111.11dp
144 | 112.00dp
145 | 112.89dp
146 | 113.78dp
147 | 114.67dp
148 | 115.56dp
149 | 116.44dp
150 | 117.33dp
151 | 118.22dp
152 | 119.11dp
153 | 120.00dp
154 | 120.89dp
155 | 121.78dp
156 | 122.67dp
157 | 123.56dp
158 | 124.44dp
159 | 125.33dp
160 | 126.22dp
161 | 127.11dp
162 | 128.00dp
163 | 128.89dp
164 | 129.78dp
165 | 130.67dp
166 | 131.56dp
167 | 132.44dp
168 | 133.33dp
169 | 134.22dp
170 | 135.11dp
171 | 136.00dp
172 | 136.89dp
173 | 137.78dp
174 | 138.67dp
175 | 139.56dp
176 | 140.44dp
177 | 141.33dp
178 | 142.22dp
179 | 143.11dp
180 | 144.00dp
181 | 144.89dp
182 | 145.78dp
183 | 146.67dp
184 | 147.56dp
185 | 148.44dp
186 | 149.33dp
187 | 150.22dp
188 | 151.11dp
189 | 152.00dp
190 | 152.89dp
191 | 153.78dp
192 | 154.67dp
193 | 155.56dp
194 | 156.44dp
195 | 157.33dp
196 | 158.22dp
197 | 159.11dp
198 | 160.00dp
199 | 160.89dp
200 | 161.78dp
201 | 162.67dp
202 | 163.56dp
203 | 164.44dp
204 | 165.33dp
205 | 166.22dp
206 | 167.11dp
207 | 168.00dp
208 | 168.89dp
209 | 169.78dp
210 | 170.67dp
211 | 171.56dp
212 | 172.44dp
213 | 173.33dp
214 | 174.22dp
215 | 175.11dp
216 | 176.00dp
217 | 176.89dp
218 | 177.78dp
219 | 178.67dp
220 | 179.56dp
221 | 180.44dp
222 | 181.33dp
223 | 182.22dp
224 | 183.11dp
225 | 184.00dp
226 | 184.89dp
227 | 185.78dp
228 | 186.67dp
229 | 187.56dp
230 | 188.44dp
231 | 189.33dp
232 | 190.22dp
233 | 191.11dp
234 | 192.00dp
235 | 192.89dp
236 | 193.78dp
237 | 194.67dp
238 | 195.56dp
239 | 196.44dp
240 | 197.33dp
241 | 198.22dp
242 | 199.11dp
243 | 200.00dp
244 | 200.89dp
245 | 201.78dp
246 | 202.67dp
247 | 203.56dp
248 | 204.44dp
249 | 205.33dp
250 | 206.22dp
251 | 207.11dp
252 | 208.00dp
253 | 208.89dp
254 | 209.78dp
255 | 210.67dp
256 | 211.56dp
257 | 212.44dp
258 | 213.33dp
259 | 214.22dp
260 | 215.11dp
261 | 216.00dp
262 | 216.89dp
263 | 217.78dp
264 | 218.67dp
265 | 219.56dp
266 | 220.44dp
267 | 221.33dp
268 | 222.22dp
269 | 223.11dp
270 | 224.00dp
271 | 224.89dp
272 | 225.78dp
273 | 226.67dp
274 | 227.56dp
275 | 228.44dp
276 | 229.33dp
277 | 230.22dp
278 | 231.11dp
279 | 232.00dp
280 | 232.89dp
281 | 233.78dp
282 | 234.67dp
283 | 235.56dp
284 | 236.44dp
285 | 237.33dp
286 | 238.22dp
287 | 239.11dp
288 | 240.00dp
289 | 240.89dp
290 | 241.78dp
291 | 242.67dp
292 | 243.56dp
293 | 244.44dp
294 | 245.33dp
295 | 246.22dp
296 | 247.11dp
297 | 248.00dp
298 | 248.89dp
299 | 249.78dp
300 | 250.67dp
301 | 251.56dp
302 | 252.44dp
303 | 253.33dp
304 | 254.22dp
305 | 255.11dp
306 | 256.00dp
307 | 256.89dp
308 | 257.78dp
309 | 258.67dp
310 | 259.56dp
311 | 260.44dp
312 | 261.33dp
313 | 262.22dp
314 | 263.11dp
315 | 264.00dp
316 | 264.89dp
317 | 265.78dp
318 | 266.67dp
319 | 267.56dp
320 | 268.44dp
321 | 269.33dp
322 | 270.22dp
323 | 271.11dp
324 | 272.00dp
325 | 272.89dp
326 | 273.78dp
327 | 274.67dp
328 | 275.56dp
329 | 276.44dp
330 | 277.33dp
331 | 278.22dp
332 | 279.11dp
333 | 280.00dp
334 | 280.89dp
335 | 281.78dp
336 | 282.67dp
337 | 283.56dp
338 | 284.44dp
339 | 285.33dp
340 | 286.22dp
341 | 287.11dp
342 | 288.00dp
343 | 288.89dp
344 | 289.78dp
345 | 290.67dp
346 | 291.56dp
347 | 292.44dp
348 | 293.33dp
349 | 294.22dp
350 | 295.11dp
351 | 296.00dp
352 | 296.89dp
353 | 297.78dp
354 | 298.67dp
355 | 299.56dp
356 | 300.44dp
357 | 301.33dp
358 | 302.22dp
359 | 303.11dp
360 | 304.00dp
361 | 304.89dp
362 | 305.78dp
363 | 306.67dp
364 | 307.56dp
365 | 308.44dp
366 | 309.33dp
367 | 310.22dp
368 | 311.11dp
369 | 312.00dp
370 | 312.89dp
371 | 313.78dp
372 | 314.67dp
373 | 315.56dp
374 | 316.44dp
375 | 317.33dp
376 | 318.22dp
377 | 319.11dp
378 | 320.00dp
379 | 320.89dp
380 | 321.78dp
381 | 322.67dp
382 | 323.56dp
383 | 324.44dp
384 | 325.33dp
385 | 326.22dp
386 | 327.11dp
387 | 328.00dp
388 | 328.89dp
389 | 329.78dp
390 | 330.67dp
391 | 331.56dp
392 | 332.44dp
393 | 333.33dp
394 | 334.22dp
395 | 335.11dp
396 | 336.00dp
397 | 336.89dp
398 | 337.78dp
399 | 338.67dp
400 | 339.56dp
401 | 340.44dp
402 | 341.33dp
403 | 342.22dp
404 | 343.11dp
405 | 344.00dp
406 | 344.89dp
407 | 345.78dp
408 | 346.67dp
409 | 347.56dp
410 | 348.44dp
411 | 349.33dp
412 | 350.22dp
413 | 351.11dp
414 | 352.00dp
415 | 352.89dp
416 | 353.78dp
417 | 354.67dp
418 | 355.56dp
419 | 356.44dp
420 | 357.33dp
421 | 358.22dp
422 | 359.11dp
423 | 360.00dp
424 | 360.89dp
425 | 361.78dp
426 | 362.67dp
427 | 363.56dp
428 | 364.44dp
429 | 365.33dp
430 | 366.22dp
431 | 367.11dp
432 | 368.00dp
433 | 368.89dp
434 | 369.78dp
435 | 370.67dp
436 | 371.56dp
437 | 372.44dp
438 | 373.33dp
439 | 374.22dp
440 | 375.11dp
441 | 376.00dp
442 | 376.89dp
443 | 377.78dp
444 | 378.67dp
445 | 379.56dp
446 | 380.44dp
447 | 381.33dp
448 | 382.22dp
449 | 383.11dp
450 | 384.00dp
451 | 384.89dp
452 | 385.78dp
453 | 386.67dp
454 | 387.56dp
455 | 388.44dp
456 | 389.33dp
457 | 390.22dp
458 | 391.11dp
459 | 392.00dp
460 | 392.89dp
461 | 393.78dp
462 | 394.67dp
463 | 395.56dp
464 | 396.44dp
465 | 397.33dp
466 | 398.22dp
467 | 399.11dp
468 | 400.00dp
469 | 400.89dp
470 | 401.78dp
471 | 402.67dp
472 | 403.56dp
473 | 404.44dp
474 | 405.33dp
475 | 406.22dp
476 | 407.11dp
477 | 408.00dp
478 | 408.89dp
479 | 409.78dp
480 | 410.67dp
481 | 411.56dp
482 | 412.44dp
483 | 413.33dp
484 | 414.22dp
485 | 415.11dp
486 | 416.00dp
487 | 416.89dp
488 | 417.78dp
489 | 418.67dp
490 | 419.56dp
491 | 420.44dp
492 | 421.33dp
493 | 422.22dp
494 | 423.11dp
495 | 424.00dp
496 | 424.89dp
497 | 425.78dp
498 | 426.67dp
499 | 427.56dp
500 | 428.44dp
501 | 429.33dp
502 | 430.22dp
503 | 431.11dp
504 | 432.00dp
505 | 432.89dp
506 | 433.78dp
507 | 434.67dp
508 | 435.56dp
509 | 436.44dp
510 | 437.33dp
511 | 438.22dp
512 | 439.11dp
513 | 440.00dp
514 | 440.89dp
515 | 441.78dp
516 | 442.67dp
517 | 443.56dp
518 | 444.44dp
519 |
--------------------------------------------------------------------------------
/videoplayer/res/values-sw360dp/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 1.00dp
20 | 2.00dp
21 | 3.00dp
22 | 4.00dp
23 | 5.00dp
24 | 6.00dp
25 | 7.00dp
26 | 8.00dp
27 | 9.00dp
28 | 10.00dp
29 | 11.00dp
30 | 12.00dp
31 | 13.00dp
32 | 14.00dp
33 | 15.00dp
34 | 16.00dp
35 | 17.00dp
36 | 18.00dp
37 | 19.00dp
38 | 20.00dp
39 | 21.00dp
40 | 22.00dp
41 | 23.00dp
42 | 24.00dp
43 | 25.00dp
44 | 26.00dp
45 | 27.00dp
46 | 28.00dp
47 | 29.00dp
48 | 30.00dp
49 | 31.00dp
50 | 32.00dp
51 | 33.00dp
52 | 34.00dp
53 | 35.00dp
54 | 36.00dp
55 | 37.00dp
56 | 38.00dp
57 | 39.00dp
58 | 40.00dp
59 | 41.00dp
60 | 42.00dp
61 | 43.00dp
62 | 44.00dp
63 | 45.00dp
64 | 46.00dp
65 | 47.00dp
66 | 48.00dp
67 | 49.00dp
68 | 50.00dp
69 | 51.00dp
70 | 52.00dp
71 | 53.00dp
72 | 54.00dp
73 | 55.00dp
74 | 56.00dp
75 | 57.00dp
76 | 58.00dp
77 | 59.00dp
78 | 60.00dp
79 | 61.00dp
80 | 62.00dp
81 | 63.00dp
82 | 64.00dp
83 | 65.00dp
84 | 66.00dp
85 | 67.00dp
86 | 68.00dp
87 | 69.00dp
88 | 70.00dp
89 | 71.00dp
90 | 72.00dp
91 | 73.00dp
92 | 74.00dp
93 | 75.00dp
94 | 76.00dp
95 | 77.00dp
96 | 78.00dp
97 | 79.00dp
98 | 80.00dp
99 | 81.00dp
100 | 82.00dp
101 | 83.00dp
102 | 84.00dp
103 | 85.00dp
104 | 86.00dp
105 | 87.00dp
106 | 88.00dp
107 | 89.00dp
108 | 90.00dp
109 | 91.00dp
110 | 92.00dp
111 | 93.00dp
112 | 94.00dp
113 | 95.00dp
114 | 96.00dp
115 | 97.00dp
116 | 98.00dp
117 | 99.00dp
118 | 100.00dp
119 | 101.00dp
120 | 102.00dp
121 | 103.00dp
122 | 104.00dp
123 | 105.00dp
124 | 106.00dp
125 | 107.00dp
126 | 108.00dp
127 | 109.00dp
128 | 110.00dp
129 | 111.00dp
130 | 112.00dp
131 | 113.00dp
132 | 114.00dp
133 | 115.00dp
134 | 116.00dp
135 | 117.00dp
136 | 118.00dp
137 | 119.00dp
138 | 120.00dp
139 | 121.00dp
140 | 122.00dp
141 | 123.00dp
142 | 124.00dp
143 | 125.00dp
144 | 126.00dp
145 | 127.00dp
146 | 128.00dp
147 | 129.00dp
148 | 130.00dp
149 | 131.00dp
150 | 132.00dp
151 | 133.00dp
152 | 134.00dp
153 | 135.00dp
154 | 136.00dp
155 | 137.00dp
156 | 138.00dp
157 | 139.00dp
158 | 140.00dp
159 | 141.00dp
160 | 142.00dp
161 | 143.00dp
162 | 144.00dp
163 | 145.00dp
164 | 146.00dp
165 | 147.00dp
166 | 148.00dp
167 | 149.00dp
168 | 150.00dp
169 | 151.00dp
170 | 152.00dp
171 | 153.00dp
172 | 154.00dp
173 | 155.00dp
174 | 156.00dp
175 | 157.00dp
176 | 158.00dp
177 | 159.00dp
178 | 160.00dp
179 | 161.00dp
180 | 162.00dp
181 | 163.00dp
182 | 164.00dp
183 | 165.00dp
184 | 166.00dp
185 | 167.00dp
186 | 168.00dp
187 | 169.00dp
188 | 170.00dp
189 | 171.00dp
190 | 172.00dp
191 | 173.00dp
192 | 174.00dp
193 | 175.00dp
194 | 176.00dp
195 | 177.00dp
196 | 178.00dp
197 | 179.00dp
198 | 180.00dp
199 | 181.00dp
200 | 182.00dp
201 | 183.00dp
202 | 184.00dp
203 | 185.00dp
204 | 186.00dp
205 | 187.00dp
206 | 188.00dp
207 | 189.00dp
208 | 190.00dp
209 | 191.00dp
210 | 192.00dp
211 | 193.00dp
212 | 194.00dp
213 | 195.00dp
214 | 196.00dp
215 | 197.00dp
216 | 198.00dp
217 | 199.00dp
218 | 200.00dp
219 | 201.00dp
220 | 202.00dp
221 | 203.00dp
222 | 204.00dp
223 | 205.00dp
224 | 206.00dp
225 | 207.00dp
226 | 208.00dp
227 | 209.00dp
228 | 210.00dp
229 | 211.00dp
230 | 212.00dp
231 | 213.00dp
232 | 214.00dp
233 | 215.00dp
234 | 216.00dp
235 | 217.00dp
236 | 218.00dp
237 | 219.00dp
238 | 220.00dp
239 | 221.00dp
240 | 222.00dp
241 | 223.00dp
242 | 224.00dp
243 | 225.00dp
244 | 226.00dp
245 | 227.00dp
246 | 228.00dp
247 | 229.00dp
248 | 230.00dp
249 | 231.00dp
250 | 232.00dp
251 | 233.00dp
252 | 234.00dp
253 | 235.00dp
254 | 236.00dp
255 | 237.00dp
256 | 238.00dp
257 | 239.00dp
258 | 240.00dp
259 | 241.00dp
260 | 242.00dp
261 | 243.00dp
262 | 244.00dp
263 | 245.00dp
264 | 246.00dp
265 | 247.00dp
266 | 248.00dp
267 | 249.00dp
268 | 250.00dp
269 | 251.00dp
270 | 252.00dp
271 | 253.00dp
272 | 254.00dp
273 | 255.00dp
274 | 256.00dp
275 | 257.00dp
276 | 258.00dp
277 | 259.00dp
278 | 260.00dp
279 | 261.00dp
280 | 262.00dp
281 | 263.00dp
282 | 264.00dp
283 | 265.00dp
284 | 266.00dp
285 | 267.00dp
286 | 268.00dp
287 | 269.00dp
288 | 270.00dp
289 | 271.00dp
290 | 272.00dp
291 | 273.00dp
292 | 274.00dp
293 | 275.00dp
294 | 276.00dp
295 | 277.00dp
296 | 278.00dp
297 | 279.00dp
298 | 280.00dp
299 | 281.00dp
300 | 282.00dp
301 | 283.00dp
302 | 284.00dp
303 | 285.00dp
304 | 286.00dp
305 | 287.00dp
306 | 288.00dp
307 | 289.00dp
308 | 290.00dp
309 | 291.00dp
310 | 292.00dp
311 | 293.00dp
312 | 294.00dp
313 | 295.00dp
314 | 296.00dp
315 | 297.00dp
316 | 298.00dp
317 | 299.00dp
318 | 300.00dp
319 | 301.00dp
320 | 302.00dp
321 | 303.00dp
322 | 304.00dp
323 | 305.00dp
324 | 306.00dp
325 | 307.00dp
326 | 308.00dp
327 | 309.00dp
328 | 310.00dp
329 | 311.00dp
330 | 312.00dp
331 | 313.00dp
332 | 314.00dp
333 | 315.00dp
334 | 316.00dp
335 | 317.00dp
336 | 318.00dp
337 | 319.00dp
338 | 320.00dp
339 | 321.00dp
340 | 322.00dp
341 | 323.00dp
342 | 324.00dp
343 | 325.00dp
344 | 326.00dp
345 | 327.00dp
346 | 328.00dp
347 | 329.00dp
348 | 330.00dp
349 | 331.00dp
350 | 332.00dp
351 | 333.00dp
352 | 334.00dp
353 | 335.00dp
354 | 336.00dp
355 | 337.00dp
356 | 338.00dp
357 | 339.00dp
358 | 340.00dp
359 | 341.00dp
360 | 342.00dp
361 | 343.00dp
362 | 344.00dp
363 | 345.00dp
364 | 346.00dp
365 | 347.00dp
366 | 348.00dp
367 | 349.00dp
368 | 350.00dp
369 | 351.00dp
370 | 352.00dp
371 | 353.00dp
372 | 354.00dp
373 | 355.00dp
374 | 356.00dp
375 | 357.00dp
376 | 358.00dp
377 | 359.00dp
378 | 360.00dp
379 | 361.00dp
380 | 362.00dp
381 | 363.00dp
382 | 364.00dp
383 | 365.00dp
384 | 366.00dp
385 | 367.00dp
386 | 368.00dp
387 | 369.00dp
388 | 370.00dp
389 | 371.00dp
390 | 372.00dp
391 | 373.00dp
392 | 374.00dp
393 | 375.00dp
394 | 376.00dp
395 | 377.00dp
396 | 378.00dp
397 | 379.00dp
398 | 380.00dp
399 | 381.00dp
400 | 382.00dp
401 | 383.00dp
402 | 384.00dp
403 | 385.00dp
404 | 386.00dp
405 | 387.00dp
406 | 388.00dp
407 | 389.00dp
408 | 390.00dp
409 | 391.00dp
410 | 392.00dp
411 | 393.00dp
412 | 394.00dp
413 | 395.00dp
414 | 396.00dp
415 | 397.00dp
416 | 398.00dp
417 | 399.00dp
418 | 400.00dp
419 | 401.00dp
420 | 402.00dp
421 | 403.00dp
422 | 404.00dp
423 | 405.00dp
424 | 406.00dp
425 | 407.00dp
426 | 408.00dp
427 | 409.00dp
428 | 410.00dp
429 | 411.00dp
430 | 412.00dp
431 | 413.00dp
432 | 414.00dp
433 | 415.00dp
434 | 416.00dp
435 | 417.00dp
436 | 418.00dp
437 | 419.00dp
438 | 420.00dp
439 | 421.00dp
440 | 422.00dp
441 | 423.00dp
442 | 424.00dp
443 | 425.00dp
444 | 426.00dp
445 | 427.00dp
446 | 428.00dp
447 | 429.00dp
448 | 430.00dp
449 | 431.00dp
450 | 432.00dp
451 | 433.00dp
452 | 434.00dp
453 | 435.00dp
454 | 436.00dp
455 | 437.00dp
456 | 438.00dp
457 | 439.00dp
458 | 440.00dp
459 | 441.00dp
460 | 442.00dp
461 | 443.00dp
462 | 444.00dp
463 | 445.00dp
464 | 446.00dp
465 | 447.00dp
466 | 448.00dp
467 | 449.00dp
468 | 450.00dp
469 | 451.00dp
470 | 452.00dp
471 | 453.00dp
472 | 454.00dp
473 | 455.00dp
474 | 456.00dp
475 | 457.00dp
476 | 458.00dp
477 | 459.00dp
478 | 460.00dp
479 | 461.00dp
480 | 462.00dp
481 | 463.00dp
482 | 464.00dp
483 | 465.00dp
484 | 466.00dp
485 | 467.00dp
486 | 468.00dp
487 | 469.00dp
488 | 470.00dp
489 | 471.00dp
490 | 472.00dp
491 | 473.00dp
492 | 474.00dp
493 | 475.00dp
494 | 476.00dp
495 | 477.00dp
496 | 478.00dp
497 | 479.00dp
498 | 480.00dp
499 | 481.00dp
500 | 482.00dp
501 | 483.00dp
502 | 484.00dp
503 | 485.00dp
504 | 486.00dp
505 | 487.00dp
506 | 488.00dp
507 | 489.00dp
508 | 490.00dp
509 | 491.00dp
510 | 492.00dp
511 | 493.00dp
512 | 494.00dp
513 | 495.00dp
514 | 496.00dp
515 | 497.00dp
516 | 498.00dp
517 | 499.00dp
518 | 500.00dp
519 |
--------------------------------------------------------------------------------
/videoplayer/res/values/font.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | @dimen/dp_30
20 | @dimen/dp_27
21 | @dimen/dp_24
22 | @dimen/dp_22
23 | @dimen/dp_20
24 | @dimen/dp_18
25 | @dimen/dp_16
26 | @dimen/dp_14
27 | @dimen/dp_12
28 | @dimen/dp_10
29 | @dimen/dp_8
30 | @dimen/dp_6
31 |
32 | @dimen/F_title
33 | @dimen/H_title
34 |
35 |
--------------------------------------------------------------------------------
/videoplayer/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 | IJKplayerDemo
22 |
23 | N/A
24 | Close
25 | Exit
26 | Sample
27 | Recent
28 | Settings
29 | Tracks
30 | Player
31 | Render
32 | Scale
33 | Info
34 | vdec
35 | fps
36 | v-cache
37 | a-cache
38 |
39 | Media Information
40 | Player
41 | Media
42 | Profile level
43 | Pixel format
44 | Resolution
45 | Length
46 | Stream #%d
47 | Type
48 | Language
49 | Codec
50 | Frame rate
51 | Bit rate
52 | Sample rate
53 | Channels
54 | *
55 | *
56 |
57 | Video
58 | Audio
59 | Subtitle
60 | Timed text
61 | Meta data
62 | Unknown
63 |
64 | 未找到服务器!
65 | 未找到服务器!
66 | 确定
67 |
68 | Aspect / Fit parent
69 | Aspect / Fill parent
70 | Aspect / Wrap content
71 | Free / Fill parent
72 | 16:9 / Fit parent
73 | 4:3 / Fit parent
74 |
75 | Render: None
76 | Render: SurfaceView
77 | Render: TextureView
78 |
79 | Player: None
80 | Player: AndroidMediaPlayer
81 | Player: IjkMediaPlayer
82 | Player: IjkExoMediaPlayer
83 |
84 |
85 |
--------------------------------------------------------------------------------
/videoplayer/res/values/strings_pref.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 | General
22 |
23 | pref.enable_background_play
24 | Enable background play
25 | need Android 4.0+
26 |
27 | pref.using_android_player
28 | Using system player
29 |
30 |
31 | pref.player
32 | Choose Player
33 |
34 | - Auto Select
35 | - AndroidMediaPlayer
36 | - IjkMediaPlayer
37 | - IjkExoMediaPlayer
38 |
39 |
40 | - 0
41 | - 1
42 | - 2
43 | - 3
44 |
45 |
46 | - Auto Select
47 | - AndroidMediaPlayer
48 | - IjkMediaPlayer
49 | - IjkExoMediaPlayer
50 |
51 |
52 |
53 | Video: ijkplayer
54 |
55 | pref.using_media_codec
56 | Using MediaCodec
57 |
58 |
59 | pref.using_media_codec_auto_rotate
60 | Using MediaCodec auto rotate
61 |
62 |
63 | pref.pixel_format
64 | Pixel Format
65 |
66 | - Auto Select
67 | - RGB 565
68 | - RGB 888X
69 | - YV12
70 |
71 |
72 |
73 | - fcc-rv16
74 | - fcc-rv32
75 | - fcc-yv12
76 |
77 |
78 | - Auto Select
79 | - RGB 565
80 | - RGB 888X
81 | - YV12
82 |
83 |
84 |
85 | Audio: ijkplayer
86 |
87 | pref.using_opensl_es
88 | Using OpenSL ES
89 |
90 |
91 |
92 | RenderView
93 |
94 | pref.enable_no_view
95 | Enable NoView
96 |
97 |
98 | pref.enable_surface_view
99 | Enable SurfaceView
100 |
101 |
102 | pref.enable_texture_view
103 | Enable TextureView
104 |
105 |
106 | pref.enable_detached_surface_texture
107 | Enable detached SurfaceTexture
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/settings/Settings.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.settings;
20 |
21 | public class Settings {
22 |
23 | /**
24 | * 是否使用 opensles
25 | */
26 | public static final boolean USING_OPEN_SLES = false;
27 | /**
28 | * 使用硬解还是软解
29 | */
30 | public static final int MEDIA_CODE = 0;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/utils/ScreenOrientationUtils.java:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Copyright (C) 2016 The yuhaiyang Android Source Project
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | * @author: y.haiyang@qq.com
18 | */
19 |
20 | package com.ishow.videoplayer.utils;
21 |
22 | import android.app.Activity;
23 | import android.content.Context;
24 | import android.content.pm.ActivityInfo;
25 | import android.content.res.Configuration;
26 | import android.util.Log;
27 | import android.view.WindowManager;
28 |
29 | public class ScreenOrientationUtils {
30 | private static final String TAG = "ScreenOrientationUtils";
31 |
32 | /**
33 | * 如果 当前activity 是非sensor默认则进行横屏
34 | */
35 | public static void setLandscape(Context context) {
36 | setLandscape(context, false);
37 | }
38 |
39 | /**
40 | * 如果 当前activity 是非sensor默认则进行横屏
41 | */
42 | public static void setLandscape(Context context, boolean force) {
43 | if (context == null || !(context instanceof Activity)) {
44 | Log.i(TAG, "setLandscape: context is null or context is not activity");
45 | return;
46 | }
47 | Activity activity = (Activity) context;
48 | if (activity.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_SENSOR && !force) {
49 | return;
50 | }
51 |
52 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
53 | }
54 |
55 | /**
56 | * 如果 当前activity 是非sensor默认则进行竖屏
57 | */
58 | public static void setPortrait(Context context) {
59 | setPortrait(context, false);
60 | }
61 |
62 | /**
63 | * 如果 当前activity 是非sensor默认则进行竖屏
64 | */
65 | public static void setPortrait(Context context, boolean force) {
66 | if (context == null || !(context instanceof Activity)) {
67 | Log.i(TAG, "setPortrait: context is null or context is not activity");
68 | return;
69 | }
70 | Activity activity = (Activity) context;
71 | if (activity.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_SENSOR && !force) {
72 | return;
73 | }
74 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
75 | }
76 |
77 | /**
78 | * 如果 当前activity 是非sensor默认则进行竖屏
79 | */
80 | public static void setSensor(Context context) {
81 | if (context == null || !(context instanceof Activity)) {
82 | Log.i(TAG, "setPortrait: context is null or context is not activity");
83 | return;
84 | }
85 | Activity activity = (Activity) context;
86 |
87 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
88 | }
89 |
90 | /**
91 | * 是否是横屏
92 | */
93 | public static boolean isLandscape(Context context) {
94 | if (context == null) {
95 | Log.i(TAG, "isPortrait: context is null ");
96 | return false;
97 | }
98 | return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
99 | }
100 |
101 | /**
102 | * 是否是竖屏
103 | */
104 | public static boolean isPortrait(Context context) {
105 | if (context == null) {
106 | Log.i(TAG, "isPortrait: context is null ");
107 | return false;
108 | }
109 | return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
110 | }
111 |
112 | /**
113 | * 设置状态栏是否可见
114 | */
115 | public static void setStatusBarVisible(Context context, boolean isVisible) {
116 | if (context == null || !(context instanceof Activity)) {
117 | Log.i(TAG, "setStatusBarVisible: context is null or context is not activity");
118 | return;
119 | }
120 | Activity activity = (Activity) context;
121 | WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
122 | if (isVisible) {
123 | lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
124 | activity.getWindow().setAttributes(lp);
125 | } else {
126 | lp.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
127 | activity.getWindow().setAttributes(lp);
128 | activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/utils/VideoUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.utils;
20 |
21 | import android.annotation.SuppressLint;
22 | import android.content.Context;
23 | import android.content.pm.PackageInfo;
24 | import android.content.pm.PackageManager;
25 | import android.content.pm.PackageManager.NameNotFoundException;
26 | import android.os.Build;
27 | import android.os.Environment;
28 | import android.os.StatFs;
29 | import android.util.Log;
30 |
31 | import java.io.BufferedReader;
32 | import java.io.IOException;
33 | import java.io.InputStreamReader;
34 | import java.text.SimpleDateFormat;
35 | import java.util.Date;
36 | import java.util.Locale;
37 |
38 | import dalvik.system.PathClassLoader;
39 |
40 | public class VideoUtils {
41 |
42 | public enum eAndroidOS {
43 | UNKNOWN, MIUI, EmotionUI, Flyme, NubiaUI, Nokia_X, ColorOS, HTC, ZTE, FuntouchOS,
44 | }
45 |
46 | public static final String FORMAT_ALL_DATE = "yyyy-MM-dd HH:mm:ss.SSS";
47 | public static final String FORMAT_TIME = "HH:mm:ss";
48 | public static final String FORMAT_DATE = "yyyy-MM-dd";
49 | public static final String FORMAT_SIMPLE_DATE = "yyyyMMdd";
50 |
51 | private final static SimpleDateFormat sFORMAT = new SimpleDateFormat(
52 | FORMAT_ALL_DATE, Locale.CHINA);
53 |
54 | private static String mSystemProperty = getSystemProperty();
55 |
56 | private final static String TAG = "VideoUtils";
57 |
58 | public static String getAppVersion(Context context) {
59 | return "";
60 | }
61 |
62 | public static String getAppName(Context context) {
63 | return "";
64 | }
65 |
66 | public static String getDocumentPath(Context context) {
67 | return context.getFilesDir().getAbsolutePath();
68 | }
69 |
70 | public static String getSDCardDataPath(Context context) {
71 | if (Environment.getExternalStorageState().equals(
72 | Environment.MEDIA_MOUNTED)) {
73 | return Environment.getExternalStorageDirectory().getAbsolutePath();
74 | }
75 | return null;
76 | }
77 |
78 | @SuppressWarnings("deprecation")
79 | @SuppressLint("NewApi")
80 | public static boolean getSDCardRemainCanWrite(Context context,
81 | long remainSize) {
82 | String path = getSDCardDataPath(context);
83 | StatFs statFS = new StatFs(path);
84 | long blockSize = 0L;
85 | if (getSDKInt() >= 18) {
86 | blockSize = statFS.getBlockCountLong();
87 | } else {
88 | blockSize = statFS.getBlockSize();
89 | }
90 | long availableBlock = 0L;
91 | if (getSDKInt() >= 18) {
92 | availableBlock = statFS.getAvailableBlocksLong();
93 | } else {
94 | availableBlock = statFS.getAvailableBlocks();
95 | }
96 | long size = blockSize * availableBlock;
97 | if (size > remainSize) {
98 | return true;
99 | }
100 |
101 | return false;
102 | }
103 |
104 | public static String getSDKVersion(Context context) {
105 | PackageManager pm = context.getPackageManager();
106 | String pkgName = context.getPackageName();
107 | PackageInfo pkgInfo = null;
108 | String ret = "";
109 | try {
110 | pkgInfo = pm.getPackageInfo(pkgName,
111 | PackageManager.GET_CONFIGURATIONS);
112 | ret = pkgInfo.versionName;
113 | } catch (NameNotFoundException ex) {
114 |
115 | }
116 | return ret;
117 | }
118 |
119 | public static String generatePlayTime(long time) {
120 | if (time % 1000 >= 500) {
121 | time += 1000;
122 | }
123 | int totalSeconds = (int) (time / 1000);
124 | int seconds = totalSeconds % 60;
125 | int minutes = (totalSeconds / 60) % 60;
126 | int hours = totalSeconds / 3600;
127 |
128 | return hours > 0 ?
129 | String.format(Locale.CHINA, "%02d:%02d:%02d", hours, minutes, seconds)
130 | :
131 | String.format(Locale.CHINA, "%02d:%02d", minutes, seconds);
132 | }
133 |
134 | /**
135 | * 用反射方式加载类
136 | *
137 | * @param context
138 | * @param path
139 | * @return
140 | */
141 | public static Object loadClass(Context context, String path) {
142 | try {
143 | String dexPath = context.getApplicationInfo().sourceDir;
144 | PathClassLoader pathClassLoader = new PathClassLoader(dexPath,
145 | context.getClassLoader());
146 | Class> c = Class.forName(path, true, pathClassLoader);
147 | Object ret = c.newInstance();
148 | return ret;
149 | } catch (InstantiationException ex1) {
150 | ex1.printStackTrace();
151 | } catch (IllegalAccessException ex2) {
152 | ex2.printStackTrace();
153 | } catch (ClassNotFoundException ex3) {
154 | ex3.printStackTrace();
155 | }
156 |
157 | return null;
158 | }
159 |
160 | public static String generateTime(long time, boolean isLong) {
161 | Date date = new Date(time);
162 | sFORMAT.applyPattern(isLong ? FORMAT_ALL_DATE : FORMAT_TIME);
163 | String LgTime = null;
164 | try {
165 | LgTime = sFORMAT.format(date);
166 | } catch (Exception e) {
167 | try {
168 | SimpleDateFormat format = new SimpleDateFormat(
169 | isLong ? FORMAT_ALL_DATE : FORMAT_TIME, Locale.CHINA);
170 | LgTime = format.format(new Date());
171 | e.printStackTrace();
172 | } catch (Exception e1) {
173 | e1.printStackTrace();
174 | LgTime = "";
175 | }
176 | }
177 | return LgTime;
178 | }
179 |
180 | public static String getOSVersionInfo() {
181 | return Build.VERSION.RELEASE;
182 | }
183 |
184 | /**
185 | * Get mobile model, like GT-i9500 etc.
186 | *
187 | * @return
188 | */
189 | public static String getMobileModel() {
190 | return Build.MODEL;
191 | }
192 |
193 | public static String getSystemProperty(String propName) {
194 | String line = "";
195 | BufferedReader input = null;
196 | try {
197 | Process p = Runtime.getRuntime().exec("getprop " + propName);
198 | input = new BufferedReader(
199 | new InputStreamReader(p.getInputStream()), 1024);
200 | line = input.readLine();
201 | input.close();
202 | } catch (IOException ex) {
203 | Log.e(TAG, "Unable to read sysprop " + propName, ex);
204 | return null;
205 | } finally {
206 | if (input != null) {
207 | try {
208 | input.close();
209 | } catch (IOException e) {
210 | Log.e(TAG, "Exception while closing InputStream", e);
211 | }
212 | }
213 | }
214 | return line;
215 | }
216 |
217 | private static String getSystemProperty() {
218 | String line = "";
219 | BufferedReader input = null;
220 | try {
221 | Process p = Runtime.getRuntime().exec("getprop");
222 | input = new BufferedReader(
223 | new InputStreamReader(p.getInputStream()), 2048);
224 | String ret = input.readLine();
225 | while (ret != null) {
226 | line += ret + "\n";
227 | ret = input.readLine();
228 | }
229 | input.close();
230 | } catch (IOException ex) {
231 | Log.e(TAG, "Unable to read sysprop", ex);
232 | return null;
233 | } finally {
234 | if (input != null) {
235 | try {
236 | input.close();
237 | } catch (IOException e) {
238 | Log.e(TAG, "Exception while closing InputStream", e);
239 | }
240 | }
241 | }
242 | return line;
243 | }
244 |
245 | public static eAndroidOS filterOS() {
246 | String prop = mSystemProperty;
247 | if (prop.contains("miui")) {
248 | return eAndroidOS.MIUI;
249 | } else if (prop.contains("EmotionUI")) {
250 | return eAndroidOS.EmotionUI;
251 | } else if (prop.contains("flyme")) {
252 | return eAndroidOS.Flyme;
253 | } else if (prop.contains("[ro.build.user]: [nubia]")) {
254 | return eAndroidOS.NubiaUI;
255 | } else if (prop.contains("Nokia_X")) {
256 | return eAndroidOS.Nokia_X;
257 | } else if (prop.contains("[ro.build.soft.version]: [A.")) {
258 | return eAndroidOS.ColorOS;
259 | } else if (prop.contains("ro.htc.")) {
260 | return eAndroidOS.HTC;
261 | } else if (prop.contains("[ro.build.user]: [zte")) {
262 | return eAndroidOS.ZTE;
263 | } else if (prop.contains("[ro.product.brand]: [vivo")) {
264 | return eAndroidOS.FuntouchOS;
265 | }
266 | return eAndroidOS.UNKNOWN;
267 | }
268 |
269 | public static String getBrand() {
270 | return Build.BRAND;
271 | }
272 |
273 | public static String getModel() {
274 | return Build.MODEL;
275 | }
276 |
277 | public static String getSDKRelease() {
278 | return Build.VERSION.RELEASE;
279 | }
280 |
281 | public static int getSDKInt() {
282 | return Build.VERSION.SDK_INT;
283 | }
284 |
285 | public static eAndroidOS getOS() {
286 | return filterOS();
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/widget/MediaController.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.widget;
20 |
21 | import android.annotation.SuppressLint;
22 | import android.app.Activity;
23 | import android.content.Context;
24 | import android.database.ContentObserver;
25 | import android.net.Uri;
26 | import android.os.Handler;
27 | import android.os.Message;
28 | import android.provider.Settings;
29 | import android.util.AttributeSet;
30 | import android.util.Log;
31 | import android.view.LayoutInflater;
32 | import android.view.View;
33 | import android.view.ViewGroup;
34 | import android.view.ViewParent;
35 | import android.widget.FrameLayout;
36 | import android.widget.ImageView;
37 | import android.widget.MediaController.MediaPlayerControl;
38 | import android.widget.RelativeLayout;
39 | import android.widget.SeekBar;
40 | import android.widget.TextView;
41 |
42 | import com.ishow.videoplayer.R;
43 | import com.ishow.videoplayer.utils.ScreenOrientationUtils;
44 | import com.ishow.videoplayer.utils.VideoUtils;
45 | import com.ishow.videoplayer.widget.media.IMediaController;
46 | import com.ishow.videoplayer.widget.media.VideoView;
47 |
48 | import tv.danmaku.ijk.media.player.IMediaPlayer;
49 |
50 |
51 | public class MediaController extends FrameLayout implements IMediaController, View.OnClickListener {
52 | private static final String TAG = "MediaController";
53 |
54 | /**
55 | * 更新进度条
56 | */
57 | private static final int HANDLER_UPDATE_PROGRESS = 1003;
58 | /**
59 | * 设置Activity位sensor控制
60 | */
61 | private static final int HANDLER_SCREEN_SENSOR = 1004;
62 | /**
63 | * 隐藏
64 | */
65 | private static final int HANDLER_HIDE_NAVIGATION = 1005;
66 | /**
67 | * 多长时间后重新设置为sensor控制
68 | */
69 | private static final int DEFAULT_DELAY_TIME_SET_SENSOR = 5000;
70 | private boolean mDragging;
71 |
72 | private VideoView mVideoView;
73 | /**
74 | * 普通功能的包裹区域
75 | */
76 | private View mNormalFeaturesContent;
77 | // Top panel 中包裹的
78 | private TextView mTitle;
79 | // 进度条
80 | private SeekBar mProgress;
81 | // 当前时间和总共多长时间
82 | private TextView mCurrentTime, mEndTime;
83 |
84 | private ImageView mFullScreenView;
85 | private ImageView mStartOrPauseView;
86 | private View mPlayNextView;
87 | /**
88 | * 加载功能的包裹区域
89 | */
90 | private View mLoadingContent;
91 | /**
92 | * 滑动功能区
93 | */
94 | private View mSlideContent;
95 | private ImageView mSlideIcon;
96 | private TextView mSlideTargetTime;
97 | private TextView mSlideTotleTime;
98 | /**
99 | * 广告区
100 | */
101 | private RelativeLayout mADContent;
102 |
103 | private ViewGroup mPortraitVideoRootView;
104 | private ViewGroup mLandVideoRootView;
105 | private MediaPlayerControl mPlayer;
106 |
107 | private CallBack mCallBack;
108 |
109 | private Handler mHandler = new Handler() {
110 | @Override
111 | public void handleMessage(Message msg) {
112 | super.handleMessage(msg);
113 | switch (msg.what) {
114 | case HANDLER_UPDATE_PROGRESS:
115 | int pos = setProgress();
116 | Log.i(TAG, "isPlaying = " + mPlayer.isPlaying());
117 | if (mPlayer.isPlaying()) {
118 | msg = obtainMessage(HANDLER_UPDATE_PROGRESS);
119 | sendMessageDelayed(msg, 1000 - (pos % 1000));
120 | }
121 |
122 | break;
123 | case HANDLER_SCREEN_SENSOR:
124 | Log.i(TAG, "handleMessage: HANDLER_SCREEN_SENSOR = " + isCanAutoRotation());
125 | if (isCanAutoRotation()) {
126 | ScreenOrientationUtils.setSensor(getContext());
127 | } else if (ScreenOrientationUtils.isLandscape(getContext())) {
128 | ScreenOrientationUtils.setLandscape(getContext(), true);
129 | } else {
130 | ScreenOrientationUtils.setPortrait(getContext(), true);
131 | }
132 | break;
133 | case HANDLER_HIDE_NAVIGATION:
134 | if (ScreenOrientationUtils.isLandscape(getContext())) {
135 | hideSystemBar();
136 | }
137 | break;
138 | }
139 | }
140 | };
141 |
142 | public MediaController(Context context) {
143 | this(context, null);
144 | }
145 |
146 | public MediaController(Context context, AttributeSet attrs) {
147 | this(context, attrs, 0);
148 | }
149 |
150 | public MediaController(Context context, AttributeSet attrs, int defStyleAttr) {
151 | super(context, attrs, defStyleAttr);
152 | init();
153 | }
154 |
155 | private void init() {
156 | LayoutInflater layoutInflater = LayoutInflater.from(getContext());
157 | layoutInflater.inflate(R.layout.media_controller, this, true);
158 |
159 | mNormalFeaturesContent = findViewById(R.id.normal_content);
160 | ImageView back = (ImageView) findViewById(R.id.back);
161 | back.setOnClickListener(this);
162 | mTitle = (TextView) findViewById(R.id.title);
163 |
164 | mFullScreenView = (ImageView) findViewById(R.id.full_screen);
165 | mFullScreenView.setOnClickListener(this);
166 |
167 | mStartOrPauseView = (ImageView) findViewById(R.id.start_or_pause);
168 | mStartOrPauseView.setOnClickListener(this);
169 |
170 | mPlayNextView = findViewById(R.id.play_next);
171 | mPlayNextView.setOnClickListener(this);
172 |
173 | mProgress = (SeekBar) findViewById(R.id.progress);
174 | mProgress.setOnSeekBarChangeListener(mSeekListener);
175 | mProgress.setMax(1000);
176 |
177 | mCurrentTime = (TextView) findViewById(R.id.current_time);
178 | mEndTime = (TextView) findViewById(R.id.end_time);
179 |
180 | // Loading 区域
181 | mLoadingContent = findViewById(R.id.loading_content);
182 |
183 | mSlideContent = findViewById(R.id.slide_content);
184 | mSlideIcon = (ImageView) findViewById(R.id.slide_icon);
185 | mSlideTargetTime = (TextView) findViewById(R.id.slide_time_target);
186 | mSlideTotleTime = (TextView) findViewById(R.id.slide_time_totle);
187 |
188 | mADContent = (RelativeLayout) findViewById(R.id.ad_content);
189 | }
190 |
191 | @Override
192 | public void hide() {
193 | Log.i(TAG, "timeout hide");
194 | mNormalFeaturesContent.setVisibility(GONE);
195 | mHandler.removeMessages(HANDLER_UPDATE_PROGRESS);
196 |
197 | mHandler.removeMessages(HANDLER_HIDE_NAVIGATION);
198 | mHandler.sendEmptyMessage(HANDLER_HIDE_NAVIGATION);
199 | }
200 |
201 | @Override
202 | public void show() {
203 | Log.i(TAG, "show");
204 | /**
205 | * 1. 先进性设置播放状态
206 | * 2. 更新进度条
207 | * 3. 显示
208 | */
209 | showSystemBar();
210 | mHandler.sendEmptyMessage(HANDLER_UPDATE_PROGRESS);
211 | syncPlayStatus();
212 | mNormalFeaturesContent.setVisibility(VISIBLE);
213 | }
214 |
215 | @Override
216 | public boolean isShowing() {
217 | return mNormalFeaturesContent.getVisibility() == View.VISIBLE;
218 | }
219 |
220 | @Override
221 | public void showLoading() {
222 | if (mLoadingContent.getVisibility() == VISIBLE) {
223 | return;
224 | }
225 | mLoadingContent.setVisibility(VISIBLE);
226 | }
227 |
228 | @Override
229 | public void hideLoading() {
230 | mLoadingContent.setVisibility(GONE);
231 | }
232 |
233 | @Override
234 | public void showSlideView(long position, float distance) {
235 | mSlideContent.setVisibility(VISIBLE);
236 | int duration = mPlayer.getDuration();
237 |
238 | if (distance > 0) {
239 | mSlideIcon.setImageResource(R.drawable.ic_forward);
240 | } else {
241 | mSlideIcon.setImageResource(R.drawable.ic_backward);
242 | }
243 |
244 | mSlideTargetTime.setText(VideoUtils.generatePlayTime(position));
245 | mSlideTotleTime.setText(VideoUtils.generatePlayTime(duration));
246 | }
247 |
248 | @Override
249 | public void hideSlideView() {
250 | mSlideContent.setVisibility(GONE);
251 | }
252 |
253 | @Override
254 | public void effectiveSlide(long position) {
255 | mPlayer.seekTo((int) (position));
256 | }
257 |
258 | @Override
259 | public RelativeLayout getAdView() {
260 | return mADContent;
261 | }
262 |
263 | @Override
264 | public void setAnchorView(View view) {
265 | if (view == null) {
266 | return;
267 | }
268 | // 如果已经设置了 那么就直接退出就好
269 | if (mVideoView != null) {
270 | return;
271 | }
272 |
273 | // 如果有父类 那么先移除
274 | ViewParent parent = getParent();
275 | if (parent != null) {
276 | ((ViewGroup) parent).removeView(this);
277 | }
278 |
279 | mVideoView = (VideoView) view;
280 | mVideoView.addView(this);
281 | mVideoView.bringChildToFront(this);
282 | mVideoView.setOnCompletionListener(mCompletionListener);
283 |
284 | mPortraitVideoRootView = (ViewGroup) mVideoView.getParent();
285 |
286 | mHandler.sendEmptyMessage(HANDLER_SCREEN_SENSOR);
287 | registerContentObservers();
288 | }
289 |
290 | /**
291 | * 设置横屏时候的RootView
292 | */
293 | public void setLandVideoRootView(ViewGroup root) {
294 | mLandVideoRootView = root;
295 | }
296 |
297 | @Override
298 | public void setMediaPlayer(android.widget.MediaController.MediaPlayerControl player) {
299 | mPlayer = player;
300 | }
301 |
302 | public void setTitle(String title) {
303 | mTitle.setText(title);
304 | }
305 |
306 |
307 | public void setPlayNextVisibility(int visiablilty) {
308 | mPlayNextView.setVisibility(visiablilty);
309 | }
310 |
311 |
312 | @Override
313 | public void onClick(View v) {
314 | int id = v.getId();
315 | if (id == R.id.full_screen) {
316 | if (ScreenOrientationUtils.isLandscape(getContext())) {
317 | changePortrait(false);
318 | } else {
319 | changeLand(false);
320 | }
321 | } else if (id == R.id.start_or_pause) {
322 |
323 | if (mCallBack != null) {
324 | mCallBack.onPlay(!mPlayer.isPlaying());
325 | }
326 |
327 | if (mPlayer.isPlaying()) {
328 | mStartOrPauseView.setImageResource(R.drawable.ic_play_play);
329 | mPlayer.pause();
330 | } else {
331 | mStartOrPauseView.setImageResource(R.drawable.ic_play_pause);
332 | mPlayer.start();
333 | mHandler.sendEmptyMessageDelayed(HANDLER_UPDATE_PROGRESS, 1000);
334 | }
335 | } else if (id == R.id.play_next) {
336 | if (mCallBack != null) {
337 | mCallBack.onPlayNext();
338 | }
339 | } else if (id == R.id.back) {
340 | if (ScreenOrientationUtils.isLandscape(getContext())) {
341 | changePortrait(false);
342 | } else {
343 | Activity activity = (Activity) getContext();
344 | activity.finish();
345 | }
346 | }
347 | }
348 |
349 |
350 | /**
351 | * 切换成横屏模式
352 | *
353 | * @param bySensor 是否是通过sensor来切换的
354 | */
355 | public void changeLand(boolean bySensor) {
356 |
357 | Activity activity = (Activity) getContext();
358 | mPortraitVideoRootView.removeView(mVideoView);
359 | mFullScreenView.setImageResource(R.drawable.ic_to_smallscreen);
360 | ViewGroup root;
361 | if (mLandVideoRootView != null) {
362 | root = mLandVideoRootView;
363 | } else {
364 | root = (ViewGroup) activity.findViewById(android.R.id.content);
365 | }
366 | if (root != null) {
367 | try {
368 | // 如果是通过sensor来切换的那么非强制更换
369 | ScreenOrientationUtils.setLandscape(activity, !bySensor);
370 | ScreenOrientationUtils.setStatusBarVisible(activity, true);
371 | mHandler.removeMessages(HANDLER_SCREEN_SENSOR);
372 | mHandler.sendEmptyMessageDelayed(HANDLER_SCREEN_SENSOR, DEFAULT_DELAY_TIME_SET_SENSOR);
373 | ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
374 | ViewGroup.LayoutParams.MATCH_PARENT,
375 | ViewGroup.LayoutParams.MATCH_PARENT);
376 | root.addView(mVideoView, lp);
377 |
378 | } catch (Exception ex) {
379 | ex.printStackTrace();
380 | }
381 | }
382 | mHandler.removeMessages(HANDLER_HIDE_NAVIGATION);
383 | mHandler.sendEmptyMessage(HANDLER_HIDE_NAVIGATION);
384 | }
385 |
386 | /**
387 | * 切换成竖屏模式
388 | *
389 | * @param bySensor 是否是通过sensor来切换的
390 | */
391 | public void changePortrait(boolean bySensor) {
392 | Activity activity = (Activity) getContext();
393 | ViewGroup root;
394 | if (mLandVideoRootView != null) {
395 | root = mLandVideoRootView;
396 | } else {
397 | root = (ViewGroup) activity.findViewById(android.R.id.content);
398 | }
399 | root.removeView(mVideoView);
400 | mFullScreenView.setImageResource(R.drawable.ic_to_fullscreen);
401 | try {
402 | ScreenOrientationUtils.setPortrait(activity, !bySensor);
403 | ScreenOrientationUtils.setStatusBarVisible(activity, false);
404 | mHandler.removeMessages(HANDLER_SCREEN_SENSOR);
405 | mHandler.sendEmptyMessageDelayed(HANDLER_SCREEN_SENSOR, DEFAULT_DELAY_TIME_SET_SENSOR);
406 | ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
407 | ViewGroup.LayoutParams.MATCH_PARENT,
408 | ViewGroup.LayoutParams.MATCH_PARENT);
409 | mPortraitVideoRootView.addView(mVideoView, lp);
410 | } catch (Exception ex) {
411 | ex.printStackTrace();
412 | }
413 |
414 | showSystemBar();
415 | }
416 |
417 | /**
418 | * 同步播放状态
419 | */
420 | private void syncPlayStatus() {
421 | if (mPlayer.isPlaying()) {
422 | mStartOrPauseView.setImageResource(R.drawable.ic_play_pause);
423 | } else {
424 | mStartOrPauseView.setImageResource(R.drawable.ic_play_play);
425 | }
426 | }
427 |
428 | /**
429 | * 设置进度
430 | */
431 | private int setProgress() {
432 | if (mPlayer == null || mDragging) {
433 | return 0;
434 | }
435 | int position = mPlayer.getCurrentPosition();
436 | int duration = mPlayer.getDuration();
437 | if (mNormalFeaturesContent == null) {
438 | return position;
439 | }
440 |
441 | if (duration > 0) {
442 | // use long to avoid overflow
443 | long pos = 1000L * position / duration;
444 | mProgress.setProgress((int) pos);
445 | }
446 | int percent = mPlayer.getBufferPercentage();
447 | mProgress.setSecondaryProgress(percent * 10);
448 |
449 | mEndTime.setText(VideoUtils.generatePlayTime(duration));
450 | mCurrentTime.setText(VideoUtils.generatePlayTime(position));
451 | return position;
452 | }
453 |
454 | /**
455 | * 设置进度
456 | */
457 | public void setProgress(int position) {
458 | if (position < 0) {
459 | return;
460 | }
461 | mPlayer.seekTo(position);
462 | }
463 |
464 | // There are two scenarios that can trigger the seekbar listener to trigger:
465 | //
466 | // The first is the user using the touchpad to adjust the posititon of the
467 | // seekbar's thumb. In this case onStartTrackingTouch is called followed by
468 | // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
469 | // We're setting the field "mDragging" to true for the duration of the dragging
470 | // session to avoid jumps in the position in case of ongoing playback.
471 | //
472 | // The second scenario involves the user operating the scroll ball, in this
473 | // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
474 | // we will simply apply the updated position without suspending regular updates.
475 | private final SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
476 | @Override
477 | public void onStartTrackingTouch(SeekBar bar) {
478 | mDragging = true;
479 |
480 | // By removing these pending progress messages we make sure
481 | // that a) we won't update the progress while the user adjusts
482 | // the seekbar and b) once the user is done dragging the thumb
483 | // we will post one of these messages to the queue again and
484 | // this ensures that there will be exactly one message queued up.
485 | mHandler.removeMessages(HANDLER_UPDATE_PROGRESS);
486 | mVideoView.removeHideAction();
487 | }
488 |
489 | @Override
490 | public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
491 |
492 | if (!fromuser) {
493 | // We're not interested in programmatically generated changes to
494 | // the progress bar's position.
495 | return;
496 | }
497 |
498 | long duration = mPlayer.getDuration();
499 | long newposition = (duration * progress) / 1000L;
500 |
501 | if (mCurrentTime != null) {
502 | mCurrentTime.setText(VideoUtils.generatePlayTime(newposition));
503 | }
504 | }
505 |
506 | @Override
507 | public void onStopTrackingTouch(SeekBar bar) {
508 | mDragging = false;
509 |
510 | long duration = mPlayer.getDuration();
511 | long newposition = (duration * bar.getProgress()) / 1000L;
512 | mPlayer.seekTo((int) newposition);
513 |
514 | mVideoView.setShowAction();
515 | }
516 | };
517 |
518 |
519 | private IMediaPlayer.OnCompletionListener mCompletionListener = new IMediaPlayer.OnCompletionListener() {
520 | public void onCompletion(IMediaPlayer mp) {
521 | if (mCallBack != null) {
522 | mCallBack.onComplete();
523 | }
524 | }
525 | };
526 |
527 |
528 | private void hideSystemBar() {
529 | // Schedule a runnable to remove the status and navigation bar after a delay
530 | mHandler.postDelayed(mHideSystemBarRunnable, 300);
531 | }
532 |
533 | private final Runnable mHideSystemBarRunnable = new Runnable() {
534 | @SuppressLint("InlinedApi")
535 | @Override
536 | public void run() {
537 | // Delayed removal of status and navigation bar
538 |
539 | // Note that some of these constants are new as of API 16 (Jelly Bean)
540 | // and API 19 (KitKat). It is safe to use them, as they are inlined
541 | // at compile-time and do nothing on earlier devices.
542 | setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
543 | | View.SYSTEM_UI_FLAG_FULLSCREEN
544 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
545 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
546 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
547 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
548 | }
549 | };
550 |
551 | @SuppressLint("InlinedApi")
552 | private void showSystemBar() {
553 | // Show the system bar
554 | //setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
555 | setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
556 |
557 | // Schedule a runnable to display UI elements after a delay
558 | mHandler.removeCallbacks(mHideSystemBarRunnable);
559 | }
560 |
561 |
562 | public void setCallBack(CallBack callBack) {
563 | mCallBack = callBack;
564 | }
565 |
566 |
567 | public interface CallBack {
568 | void onPlay(boolean isPlaying);
569 |
570 | void onComplete();
571 |
572 | void onPlayNext();
573 | }
574 |
575 |
576 | private void registerContentObservers() {
577 | // 通过调用getUriFor
578 | Uri airplaneUri = Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION);
579 | // 注册内容观察者
580 | // 第二个参数false 为精确匹配
581 | getContext().getContentResolver().registerContentObserver(airplaneUri, false, mObserver);
582 | }
583 |
584 |
585 | private void unregisterContentObservers() {
586 | getContext().getContentResolver().unregisterContentObserver(mObserver);
587 | }
588 |
589 | @Override
590 | protected void onAttachedToWindow() {
591 | super.onAttachedToWindow();
592 | Log.i(TAG, "onAttachedToWindow: mVideoView = " + mVideoView);
593 | if (mVideoView != null) {
594 | registerContentObservers();
595 | mHandler.sendEmptyMessage(HANDLER_SCREEN_SENSOR);
596 | }
597 | }
598 |
599 | @Override
600 | protected void onDetachedFromWindow() {
601 | super.onDetachedFromWindow();
602 | Log.i(TAG, "onDetachedFromWindow: ");
603 | unregisterContentObservers();
604 | }
605 |
606 |
607 | private ContentObserver mObserver = new ContentObserver(null) {
608 | @Override
609 | public void onChange(boolean selfChange) {
610 | super.onChange(selfChange);
611 | mHandler.sendEmptyMessage(HANDLER_SCREEN_SENSOR);
612 | }
613 | };
614 |
615 | private boolean isCanAutoRotation() {
616 | int acc = Settings.System.getInt(getContext().getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0);
617 | return acc == 1;
618 | }
619 | }
620 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/widget/media/IMediaController.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.widget.media;
20 |
21 | import android.view.View;
22 | import android.widget.MediaController;
23 | import android.widget.RelativeLayout;
24 |
25 | public interface IMediaController {
26 | /**
27 | * 显示普通功能区
28 | */
29 | void hide();
30 |
31 | /**
32 | * 隐藏普通功能区
33 | */
34 | void show();
35 |
36 | /**
37 | * 普通功能区是否显示
38 | */
39 | boolean isShowing();
40 |
41 | /**
42 | * 显示Loading
43 | */
44 | void showLoading();
45 |
46 | /**
47 | * 隐藏loading
48 | */
49 | void hideLoading();
50 |
51 | /**
52 | * 显示滑动的View
53 | */
54 | void showSlideView(long position, float distance);
55 |
56 | /**
57 | * 隐藏滑动的View
58 | */
59 | void hideSlideView();
60 |
61 | /**
62 | * 生效距离
63 | */
64 | void effectiveSlide(long position);
65 |
66 | /**
67 | * 获取广告View
68 | */
69 | RelativeLayout getAdView();
70 |
71 | void setAnchorView(View view);
72 |
73 | void setEnabled(boolean enabled);
74 |
75 | void setMediaPlayer(MediaController.MediaPlayerControl player);
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/widget/media/IRenderView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.widget.media;
20 |
21 | import android.graphics.SurfaceTexture;
22 | import android.support.annotation.NonNull;
23 | import android.support.annotation.Nullable;
24 | import android.view.Surface;
25 | import android.view.SurfaceHolder;
26 | import android.view.View;
27 |
28 | import tv.danmaku.ijk.media.player.IMediaPlayer;
29 |
30 | public interface IRenderView {
31 | int AR_ASPECT_FIT_PARENT = 0; // without clip
32 | int AR_ASPECT_FILL_PARENT = 1; // may clip
33 | int AR_ASPECT_WRAP_CONTENT = 2;
34 | int AR_MATCH_PARENT = 3;
35 | int AR_16_9_FIT_PARENT = 4;
36 | int AR_4_3_FIT_PARENT = 5;
37 |
38 | View getView();
39 |
40 | boolean shouldWaitForResize();
41 |
42 | void setVideoSize(int videoWidth, int videoHeight);
43 |
44 | void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen);
45 |
46 | void setVideoRotation(int degree);
47 |
48 | void setAspectRatio(int aspectRatio);
49 |
50 | void addRenderCallback(@NonNull IRenderCallback callback);
51 |
52 | void removeRenderCallback(@NonNull IRenderCallback callback);
53 |
54 | interface ISurfaceHolder {
55 | void bindToMediaPlayer(IMediaPlayer mp);
56 |
57 | @NonNull
58 | IRenderView getRenderView();
59 |
60 | @Nullable
61 | SurfaceHolder getSurfaceHolder();
62 |
63 | @Nullable
64 | Surface openSurface();
65 |
66 | @Nullable
67 | SurfaceTexture getSurfaceTexture();
68 | }
69 |
70 | interface IRenderCallback {
71 | /**
72 | * @param holder
73 | * @param width could be 0
74 | * @param height could be 0
75 | */
76 | void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height);
77 |
78 | /**
79 | * @param holder
80 | * @param format could be 0
81 | * @param width
82 | * @param height
83 | */
84 | void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height);
85 |
86 | void onSurfaceDestroyed(@NonNull ISurfaceHolder holder);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/widget/media/MeasureHelper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.widget.media;
20 |
21 | import android.content.Context;
22 | import android.support.annotation.NonNull;
23 | import android.view.View;
24 |
25 | import com.ishow.videoplayer.R;
26 |
27 | import java.lang.ref.WeakReference;
28 |
29 | public final class MeasureHelper {
30 | private WeakReference mWeakView;
31 |
32 | private int mVideoWidth;
33 | private int mVideoHeight;
34 | private int mVideoSarNum;
35 | private int mVideoSarDen;
36 |
37 | private int mVideoRotationDegree;
38 |
39 | private int mMeasuredWidth;
40 | private int mMeasuredHeight;
41 |
42 | private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT;
43 |
44 | public MeasureHelper(View view) {
45 | mWeakView = new WeakReference(view);
46 | }
47 |
48 | public View getView() {
49 | if (mWeakView == null)
50 | return null;
51 | return mWeakView.get();
52 | }
53 |
54 | public void setVideoSize(int videoWidth, int videoHeight) {
55 | mVideoWidth = videoWidth;
56 | mVideoHeight = videoHeight;
57 | }
58 |
59 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
60 | mVideoSarNum = videoSarNum;
61 | mVideoSarDen = videoSarDen;
62 | }
63 |
64 | public void setVideoRotation(int videoRotationDegree) {
65 | mVideoRotationDegree = videoRotationDegree;
66 | }
67 |
68 | /**
69 | * Must be called by View.onMeasure(int, int)
70 | *
71 | * @param widthMeasureSpec
72 | * @param heightMeasureSpec
73 | */
74 | public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
75 | //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
76 | // + MeasureSpec.toString(heightMeasureSpec) + ")");
77 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
78 | int tempSpec = widthMeasureSpec;
79 | widthMeasureSpec = heightMeasureSpec;
80 | heightMeasureSpec = tempSpec;
81 | }
82 |
83 | int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
84 | int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
85 | if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) {
86 | width = widthMeasureSpec;
87 | height = heightMeasureSpec;
88 | } else if (mVideoWidth > 0 && mVideoHeight > 0) {
89 | int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
90 | int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
91 | int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
92 | int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
93 |
94 | if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) {
95 | float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;
96 | float displayAspectRatio;
97 | switch (mCurrentAspectRatio) {
98 | case IRenderView.AR_16_9_FIT_PARENT:
99 | displayAspectRatio = 16.0f / 9.0f;
100 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
101 | displayAspectRatio = 1.0f / displayAspectRatio;
102 | break;
103 | case IRenderView.AR_4_3_FIT_PARENT:
104 | displayAspectRatio = 4.0f / 3.0f;
105 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
106 | displayAspectRatio = 1.0f / displayAspectRatio;
107 | break;
108 | case IRenderView.AR_ASPECT_FIT_PARENT:
109 | case IRenderView.AR_ASPECT_FILL_PARENT:
110 | case IRenderView.AR_ASPECT_WRAP_CONTENT:
111 | default:
112 | displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;
113 | if (mVideoSarNum > 0 && mVideoSarDen > 0)
114 | displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;
115 | break;
116 | }
117 | boolean shouldBeWider = displayAspectRatio > specAspectRatio;
118 |
119 | switch (mCurrentAspectRatio) {
120 | case IRenderView.AR_ASPECT_FIT_PARENT:
121 | case IRenderView.AR_16_9_FIT_PARENT:
122 | case IRenderView.AR_4_3_FIT_PARENT:
123 | if (shouldBeWider) {
124 | // too wide, fix width
125 | width = widthSpecSize;
126 | height = (int) (width / displayAspectRatio);
127 | } else {
128 | // too high, fix height
129 | height = heightSpecSize;
130 | width = (int) (height * displayAspectRatio);
131 | }
132 | break;
133 | case IRenderView.AR_ASPECT_FILL_PARENT:
134 | if (shouldBeWider) {
135 | // not high enough, fix height
136 | height = heightSpecSize;
137 | width = (int) (height * displayAspectRatio);
138 | } else {
139 | // not wide enough, fix width
140 | width = widthSpecSize;
141 | height = (int) (width / displayAspectRatio);
142 | }
143 | break;
144 | case IRenderView.AR_ASPECT_WRAP_CONTENT:
145 | default:
146 | if (shouldBeWider) {
147 | // too wide, fix width
148 | width = Math.min(mVideoWidth, widthSpecSize);
149 | height = (int) (width / displayAspectRatio);
150 | } else {
151 | // too high, fix height
152 | height = Math.min(mVideoHeight, heightSpecSize);
153 | width = (int) (height * displayAspectRatio);
154 | }
155 | break;
156 | }
157 | } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
158 | // the size is fixed
159 | width = widthSpecSize;
160 | height = heightSpecSize;
161 |
162 | // for compatibility, we adjust size based on aspect ratio
163 | if (mVideoWidth * height < width * mVideoHeight) {
164 | //Log.i("@@@", "image too wide, correcting");
165 | width = height * mVideoWidth / mVideoHeight;
166 | } else if (mVideoWidth * height > width * mVideoHeight) {
167 | //Log.i("@@@", "image too tall, correcting");
168 | height = width * mVideoHeight / mVideoWidth;
169 | }
170 | } else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
171 | // only the width is fixed, adjust the height to match aspect ratio if possible
172 | width = widthSpecSize;
173 | height = width * mVideoHeight / mVideoWidth;
174 | if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
175 | // couldn't match aspect ratio within the constraints
176 | height = heightSpecSize;
177 | }
178 | } else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
179 | // only the height is fixed, adjust the width to match aspect ratio if possible
180 | height = heightSpecSize;
181 | width = height * mVideoWidth / mVideoHeight;
182 | if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
183 | // couldn't match aspect ratio within the constraints
184 | width = widthSpecSize;
185 | }
186 | } else {
187 | // neither the width nor the height are fixed, try to use actual video size
188 | width = mVideoWidth;
189 | height = mVideoHeight;
190 | if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
191 | // too tall, decrease both width and height
192 | height = heightSpecSize;
193 | width = height * mVideoWidth / mVideoHeight;
194 | }
195 | if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
196 | // too wide, decrease both width and height
197 | width = widthSpecSize;
198 | height = width * mVideoHeight / mVideoWidth;
199 | }
200 | }
201 | } else {
202 | // no size yet, just adopt the given spec sizes
203 | }
204 |
205 | mMeasuredWidth = width;
206 | mMeasuredHeight = height;
207 | }
208 |
209 | public int getMeasuredWidth() {
210 | return mMeasuredWidth;
211 | }
212 |
213 | public int getMeasuredHeight() {
214 | return mMeasuredHeight;
215 | }
216 |
217 | public void setAspectRatio(int aspectRatio) {
218 | mCurrentAspectRatio = aspectRatio;
219 | }
220 |
221 | @NonNull
222 | public static String getAspectRatioText(Context context, int aspectRatio) {
223 | String text;
224 | switch (aspectRatio) {
225 | case IRenderView.AR_ASPECT_FIT_PARENT:
226 | text = context.getString(R.string.VideoView_ar_aspect_fit_parent);
227 | break;
228 | case IRenderView.AR_ASPECT_FILL_PARENT:
229 | text = context.getString(R.string.VideoView_ar_aspect_fill_parent);
230 | break;
231 | case IRenderView.AR_ASPECT_WRAP_CONTENT:
232 | text = context.getString(R.string.VideoView_ar_aspect_wrap_content);
233 | break;
234 | case IRenderView.AR_MATCH_PARENT:
235 | text = context.getString(R.string.VideoView_ar_match_parent);
236 | break;
237 | case IRenderView.AR_16_9_FIT_PARENT:
238 | text = context.getString(R.string.VideoView_ar_16_9_fit_parent);
239 | break;
240 | case IRenderView.AR_4_3_FIT_PARENT:
241 | text = context.getString(R.string.VideoView_ar_4_3_fit_parent);
242 | break;
243 | default:
244 | text = context.getString(R.string.N_A);
245 | break;
246 | }
247 | return text;
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/videoplayer/src/com/ishow/videoplayer/widget/media/SurfaceRenderView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 The yuhaiyang Android Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author: y.haiyang@qq.com
17 | */
18 |
19 | package com.ishow.videoplayer.widget.media;
20 |
21 | import android.annotation.TargetApi;
22 | import android.content.Context;
23 | import android.graphics.SurfaceTexture;
24 | import android.os.Build;
25 | import android.support.annotation.NonNull;
26 | import android.support.annotation.Nullable;
27 | import android.util.AttributeSet;
28 | import android.util.Log;
29 | import android.view.Surface;
30 | import android.view.SurfaceHolder;
31 | import android.view.SurfaceView;
32 | import android.view.View;
33 | import android.view.accessibility.AccessibilityEvent;
34 | import android.view.accessibility.AccessibilityNodeInfo;
35 |
36 | import java.lang.ref.WeakReference;
37 | import java.util.Map;
38 | import java.util.concurrent.ConcurrentHashMap;
39 |
40 | import tv.danmaku.ijk.media.player.IMediaPlayer;
41 | import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
42 |
43 | public class SurfaceRenderView extends SurfaceView implements IRenderView {
44 | private MeasureHelper mMeasureHelper;
45 |
46 | public SurfaceRenderView(Context context) {
47 | super(context);
48 | initView(context);
49 | }
50 |
51 | public SurfaceRenderView(Context context, AttributeSet attrs) {
52 | super(context, attrs);
53 | initView(context);
54 | }
55 |
56 | public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
57 | super(context, attrs, defStyleAttr);
58 | initView(context);
59 | }
60 |
61 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
62 | public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
63 | super(context, attrs, defStyleAttr, defStyleRes);
64 | initView(context);
65 | }
66 |
67 | private void initView(Context context) {
68 | mMeasureHelper = new MeasureHelper(this);
69 | mSurfaceCallback = new SurfaceCallback(this);
70 | getHolder().addCallback(mSurfaceCallback);
71 | //noinspection deprecation
72 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
73 | }
74 |
75 | @Override
76 | public View getView() {
77 | return this;
78 | }
79 |
80 | @Override
81 | public boolean shouldWaitForResize() {
82 | return true;
83 | }
84 |
85 | //--------------------
86 | // Layout & Measure
87 | //--------------------
88 | @Override
89 | public void setVideoSize(int videoWidth, int videoHeight) {
90 | if (videoWidth > 0 && videoHeight > 0) {
91 | mMeasureHelper.setVideoSize(videoWidth, videoHeight);
92 | getHolder().setFixedSize(videoWidth, videoHeight);
93 | requestLayout();
94 | }
95 | }
96 |
97 | @Override
98 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
99 | if (videoSarNum > 0 && videoSarDen > 0) {
100 | mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
101 | requestLayout();
102 | }
103 | }
104 |
105 | @Override
106 | public void setVideoRotation(int degree) {
107 | Log.e("", "SurfaceView doesn't support rotation (" + degree + ")!\n");
108 | }
109 |
110 | @Override
111 | public void setAspectRatio(int aspectRatio) {
112 | mMeasureHelper.setAspectRatio(aspectRatio);
113 | requestLayout();
114 | }
115 |
116 | @Override
117 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
118 | mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
119 | setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
120 | }
121 |
122 | //--------------------
123 | // SurfaceViewHolder
124 | //--------------------
125 |
126 | private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder {
127 | private SurfaceRenderView mSurfaceView;
128 | private SurfaceHolder mSurfaceHolder;
129 |
130 | public InternalSurfaceHolder(@NonNull SurfaceRenderView surfaceView,
131 | @Nullable SurfaceHolder surfaceHolder) {
132 | mSurfaceView = surfaceView;
133 | mSurfaceHolder = surfaceHolder;
134 | }
135 |
136 | public void bindToMediaPlayer(IMediaPlayer mp) {
137 | if (mp != null) {
138 | if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
139 | (mp instanceof ISurfaceTextureHolder)) {
140 | ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
141 | textureHolder.setSurfaceTexture(null);
142 | }
143 | mp.setDisplay(mSurfaceHolder);
144 | }
145 | }
146 |
147 | @NonNull
148 | @Override
149 | public IRenderView getRenderView() {
150 | return mSurfaceView;
151 | }
152 |
153 | @Nullable
154 | @Override
155 | public SurfaceHolder getSurfaceHolder() {
156 | return mSurfaceHolder;
157 | }
158 |
159 | @Nullable
160 | @Override
161 | public SurfaceTexture getSurfaceTexture() {
162 | return null;
163 | }
164 |
165 | @Nullable
166 | @Override
167 | public Surface openSurface() {
168 | if (mSurfaceHolder == null)
169 | return null;
170 | return mSurfaceHolder.getSurface();
171 | }
172 | }
173 |
174 | //-------------------------
175 | // SurfaceHolder.Callback
176 | //-------------------------
177 |
178 | @Override
179 | public void addRenderCallback(IRenderCallback callback) {
180 | mSurfaceCallback.addRenderCallback(callback);
181 | }
182 |
183 | @Override
184 | public void removeRenderCallback(IRenderCallback callback) {
185 | mSurfaceCallback.removeRenderCallback(callback);
186 | }
187 |
188 | private SurfaceCallback mSurfaceCallback;
189 |
190 | private static final class SurfaceCallback implements SurfaceHolder.Callback {
191 | private SurfaceHolder mSurfaceHolder;
192 | private boolean mIsFormatChanged;
193 | private int mFormat;
194 | private int mWidth;
195 | private int mHeight;
196 |
197 | private WeakReference mWeakSurfaceView;
198 | private Map mRenderCallbackMap = new ConcurrentHashMap();
199 |
200 | public SurfaceCallback(@NonNull SurfaceRenderView surfaceView) {
201 | mWeakSurfaceView = new WeakReference(surfaceView);
202 | }
203 |
204 | public void addRenderCallback(@NonNull IRenderCallback callback) {
205 | mRenderCallbackMap.put(callback, callback);
206 |
207 | ISurfaceHolder surfaceHolder = null;
208 | if (mSurfaceHolder != null) {
209 | if (surfaceHolder == null)
210 | surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
211 | callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
212 | }
213 |
214 | if (mIsFormatChanged) {
215 | if (surfaceHolder == null)
216 | surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
217 | callback.onSurfaceChanged(surfaceHolder, mFormat, mWidth, mHeight);
218 | }
219 | }
220 |
221 | public void removeRenderCallback(@NonNull IRenderCallback callback) {
222 | mRenderCallbackMap.remove(callback);
223 | }
224 |
225 | @Override
226 | public void surfaceCreated(SurfaceHolder holder) {
227 | mSurfaceHolder = holder;
228 | mIsFormatChanged = false;
229 | mFormat = 0;
230 | mWidth = 0;
231 | mHeight = 0;
232 |
233 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
234 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
235 | renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
236 | }
237 | }
238 |
239 | @Override
240 | public void surfaceDestroyed(SurfaceHolder holder) {
241 | mSurfaceHolder = null;
242 | mIsFormatChanged = false;
243 | mFormat = 0;
244 | mWidth = 0;
245 | mHeight = 0;
246 |
247 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
248 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
249 | renderCallback.onSurfaceDestroyed(surfaceHolder);
250 | }
251 | }
252 |
253 | @Override
254 | public void surfaceChanged(SurfaceHolder holder, int format,
255 | int width, int height) {
256 | mSurfaceHolder = holder;
257 | mIsFormatChanged = true;
258 | mFormat = format;
259 | mWidth = width;
260 | mHeight = height;
261 |
262 | // mMeasureHelper.setVideoSize(width, height);
263 |
264 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
265 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
266 | renderCallback.onSurfaceChanged(surfaceHolder, format, width, height);
267 | }
268 | }
269 | }
270 |
271 | //--------------------
272 | // Accessibility
273 | //--------------------
274 |
275 | @Override
276 | public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
277 | super.onInitializeAccessibilityEvent(event);
278 | event.setClassName(SurfaceRenderView.class.getName());
279 | }
280 |
281 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
282 | @Override
283 | public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
284 | super.onInitializeAccessibilityNodeInfo(info);
285 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
286 | info.setClassName(SurfaceRenderView.class.getName());
287 | }
288 | }
289 | }
290 |
--------------------------------------------------------------------------------