Commit 46f3a709817f5e22fe9b10708ce2dbdffb881b11
1 parent
889f3c14
Vitamio...
Showing
83 changed files
with
2100 additions
and
4 deletions
VitamioBundle/.classpath
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<classpath> | |
3 | + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> | |
4 | + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> | |
5 | + <classpathentry kind="src" path="src"/> | |
6 | + <classpathentry kind="src" path="gen"/> | |
7 | + <classpathentry kind="output" path="bin/classes"/> | |
8 | +</classpath> | ... | ... |
VitamioBundle/.gitignore
0 → 100644
1 | +# built application files | |
2 | +*.apk | |
3 | +*.ap_ | |
4 | + | |
5 | +# files for the dex VM | |
6 | +*.dex | |
7 | + | |
8 | +# Java class files | |
9 | +*.class | |
10 | + | |
11 | +# generated files | |
12 | +bin/ | |
13 | +gen/ | |
14 | +obj/ | |
15 | + | |
16 | +# Local configuration file (sdk path, etc) | |
17 | +local.properties | |
18 | + | |
19 | +# Eclipse project files | |
20 | +.classpath | |
21 | +.project | ... | ... |
VitamioBundle/.project
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<projectDescription> | |
3 | + <name>io.vov.vitamio.activity.InitActivity</name> | |
4 | + <comment></comment> | |
5 | + <projects> | |
6 | + </projects> | |
7 | + <buildSpec> | |
8 | + <buildCommand> | |
9 | + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> | |
10 | + <arguments> | |
11 | + </arguments> | |
12 | + </buildCommand> | |
13 | + <buildCommand> | |
14 | + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> | |
15 | + <arguments> | |
16 | + </arguments> | |
17 | + </buildCommand> | |
18 | + <buildCommand> | |
19 | + <name>org.eclipse.jdt.core.javabuilder</name> | |
20 | + <arguments> | |
21 | + </arguments> | |
22 | + </buildCommand> | |
23 | + <buildCommand> | |
24 | + <name>com.android.ide.eclipse.adt.ApkBuilder</name> | |
25 | + <arguments> | |
26 | + </arguments> | |
27 | + </buildCommand> | |
28 | + </buildSpec> | |
29 | + <natures> | |
30 | + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> | |
31 | + <nature>org.eclipse.jdt.core.javanature</nature> | |
32 | + </natures> | |
33 | +</projectDescription> | ... | ... |
VitamioBundle/.settings/org.eclipse.jdt.core.prefs
0 → 100644
1 | +eclipse.preferences.version=1 | |
2 | +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | |
3 | +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 | |
4 | +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve | |
5 | +org.eclipse.jdt.core.compiler.compliance=1.6 | |
6 | +org.eclipse.jdt.core.compiler.debug.lineNumber=generate | |
7 | +org.eclipse.jdt.core.compiler.debug.localVariable=generate | |
8 | +org.eclipse.jdt.core.compiler.debug.sourceFile=generate | |
9 | +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | |
10 | +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | |
11 | +org.eclipse.jdt.core.compiler.source=1.6 | ... | ... |
VitamioBundle/AndroidManifest.xml
0 → 100644
1 | +<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
2 | + package="io.vov.vitamio" | |
3 | + android:versionCode="300" | |
4 | + android:versionName="3.0" > | |
5 | + | |
6 | + <uses-sdk | |
7 | + android:minSdkVersion="7" | |
8 | + android:targetSdkVersion="16" /> | |
9 | + | |
10 | + <application | |
11 | + android:icon="@drawable/ic_launcher" | |
12 | + android:label="@string/vitamio_name" > | |
13 | + <activity | |
14 | + android:name="io.vov.vitamio.activity.InitActivity" | |
15 | + android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation" | |
16 | + android:launchMode="singleTop" | |
17 | + android:theme="@android:style/Theme.NoTitleBar" | |
18 | + android:windowSoftInputMode="stateAlwaysHidden" /> | |
19 | + </application> | |
20 | + | |
21 | +</manifest> | |
0 | 22 | \ No newline at end of file | ... | ... |
VitamioBundle/README.md
0 → 100644
VitamioBundle/VitamioBundle.tar.gz
0 → 100644
No preview for this file type
VitamioBundle/bin/AndroidManifest.xml
0 → 100644
1 | +<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
2 | + package="io.vov.vitamio" | |
3 | + android:versionCode="300" | |
4 | + android:versionName="3.0" > | |
5 | + | |
6 | + <uses-sdk | |
7 | + android:minSdkVersion="7" | |
8 | + android:targetSdkVersion="16" /> | |
9 | + | |
10 | + <application | |
11 | + android:icon="@drawable/ic_launcher" | |
12 | + android:label="@string/vitamio_name" > | |
13 | + <activity | |
14 | + android:name="io.vov.vitamio.activity.InitActivity" | |
15 | + android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation" | |
16 | + android:launchMode="singleTop" | |
17 | + android:theme="@android:style/Theme.NoTitleBar" | |
18 | + android:windowSoftInputMode="stateAlwaysHidden" /> | |
19 | + </application> | |
20 | + | |
21 | +</manifest> | |
0 | 22 | \ No newline at end of file | ... | ... |
VitamioBundle/bin/classes/io/vov/vitamio/BuildConfig.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$attr.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$drawable.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$id.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$layout.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$raw.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$string.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R$style.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/R.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$1.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$UIHandler.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout$LayoutParams.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$1.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$2.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$3.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$MediaPlayerControl.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnHiddenListener.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnShownListener.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/OutlineTextView.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$1.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$2.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$3.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4$1.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$5.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$6.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$7.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$8.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$9.class
0 → 100644
No preview for this file type
VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView.class
0 → 100644
No preview for this file type
VitamioBundle/bin/io.vov.vitamio.activity.initactivity.jar
0 → 100644
No preview for this file type
VitamioBundle/bin/jarlist.cache
0 → 100644
VitamioBundle/bin/res/drawable-hdpi/ic_launcher.png
0 → 100644
791 Bytes
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_bg.png
0 → 100644
129 Bytes
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause01.png
0 → 100644
599 Bytes
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause02.png
0 → 100644
710 Bytes
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play01.png
0 → 100644
922 Bytes
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play02.png
0 → 100644
1.04 KB
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar01.png
0 → 100644
456 Bytes
VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar02.png
0 → 100644
103 Bytes
VitamioBundle/bin/res/drawable-xhdpi/ic_launcher.png
0 → 100644
973 Bytes
VitamioBundle/build.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<project name="VitamioBundle" default="help"> | |
3 | + | |
4 | + <!-- The local.properties file is created and updated by the 'android' tool. | |
5 | + It contains the path to the SDK. It should *NOT* be checked into | |
6 | + Version Control Systems. --> | |
7 | + <property file="local.properties" /> | |
8 | + | |
9 | + <!-- The ant.properties file can be created by you. It is only edited by the | |
10 | + 'android' tool to add properties to it. | |
11 | + This is the place to change some Ant specific build properties. | |
12 | + Here are some properties you may want to change/update: | |
13 | + | |
14 | + source.dir | |
15 | + The name of the source directory. Default is 'src'. | |
16 | + out.dir | |
17 | + The name of the output directory. Default is 'bin'. | |
18 | + | |
19 | + For other overridable properties, look at the beginning of the rules | |
20 | + files in the SDK, at tools/ant/build.xml | |
21 | + | |
22 | + Properties related to the SDK location or the project target should | |
23 | + be updated using the 'android' tool with the 'update' action. | |
24 | + | |
25 | + This file is an integral part of the build system for your | |
26 | + application and should be checked into Version Control Systems. | |
27 | + | |
28 | + --> | |
29 | + <property file="ant.properties" /> | |
30 | + | |
31 | + <!-- if sdk.dir was not set from one of the property file, then | |
32 | + get it from the ANDROID_HOME env var. | |
33 | + This must be done before we load project.properties since | |
34 | + the proguard config can use sdk.dir --> | |
35 | + <property environment="env" /> | |
36 | + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> | |
37 | + <isset property="env.ANDROID_HOME" /> | |
38 | + </condition> | |
39 | + | |
40 | + <!-- The project.properties file is created and updated by the 'android' | |
41 | + tool, as well as ADT. | |
42 | + | |
43 | + This contains project specific properties such as project target, and library | |
44 | + dependencies. Lower level build properties are stored in ant.properties | |
45 | + (or in .classpath for Eclipse projects). | |
46 | + | |
47 | + This file is an integral part of the build system for your | |
48 | + application and should be checked into Version Control Systems. --> | |
49 | + <loadproperties srcFile="project.properties" /> | |
50 | + | |
51 | + <!-- quick check on sdk.dir --> | |
52 | + <fail | |
53 | + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." | |
54 | + unless="sdk.dir" | |
55 | + /> | |
56 | + | |
57 | + <!-- | |
58 | + Import per project custom build rules if present at the root of the project. | |
59 | + This is the place to put custom intermediary targets such as: | |
60 | + -pre-build | |
61 | + -pre-compile | |
62 | + -post-compile (This is typically used for code obfuscation. | |
63 | + Compiled code location: ${out.classes.absolute.dir} | |
64 | + If this is not done in place, override ${out.dex.input.absolute.dir}) | |
65 | + -post-package | |
66 | + -post-build | |
67 | + -pre-clean | |
68 | + --> | |
69 | + <import file="custom_rules.xml" optional="true" /> | |
70 | + | |
71 | + <!-- Import the actual build file. | |
72 | + | |
73 | + To customize existing targets, there are two options: | |
74 | + - Customize only one target: | |
75 | + - copy/paste the target into this file, *before* the | |
76 | + <import> task. | |
77 | + - customize it to your needs. | |
78 | + - Customize the whole content of build.xml | |
79 | + - copy/paste the content of the rules files (minus the top node) | |
80 | + into this file, replacing the <import> task. | |
81 | + - customize to your needs. | |
82 | + | |
83 | + *********************** | |
84 | + ****** IMPORTANT ****** | |
85 | + *********************** | |
86 | + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, | |
87 | + in order to avoid having your file be overridden by tools such as "android update project" | |
88 | + --> | |
89 | + <!-- version-tag: 1 --> | |
90 | + <import file="${sdk.dir}/tools/ant/build.xml" /> | |
91 | + | |
92 | +</project> | ... | ... |
VitamioBundle/gen/io/vov/vitamio/BuildConfig.java
0 → 100644
VitamioBundle/gen/io/vov/vitamio/R.java
0 → 100644
1 | +/* AUTO-GENERATED FILE. DO NOT MODIFY. | |
2 | + * | |
3 | + * This class was automatically generated by the | |
4 | + * aapt tool from the resource data it found. It | |
5 | + * should not be modified by hand. | |
6 | + */ | |
7 | + | |
8 | +package io.vov.vitamio; | |
9 | + | |
10 | +public final class R { | |
11 | + public static final class attr { | |
12 | + } | |
13 | + public static final class drawable { | |
14 | + public static int ic_launcher=0x7f020000; | |
15 | + public static int mediacontroller_bg=0x7f020001; | |
16 | + public static int mediacontroller_pause01=0x7f020002; | |
17 | + public static int mediacontroller_pause02=0x7f020003; | |
18 | + public static int mediacontroller_pause_button=0x7f020004; | |
19 | + public static int mediacontroller_play01=0x7f020005; | |
20 | + public static int mediacontroller_play02=0x7f020006; | |
21 | + public static int mediacontroller_play_button=0x7f020007; | |
22 | + public static int mediacontroller_seekbar=0x7f020008; | |
23 | + public static int mediacontroller_seekbar01=0x7f020009; | |
24 | + public static int mediacontroller_seekbar02=0x7f02000a; | |
25 | + public static int mediacontroller_seekbar_thumb=0x7f02000b; | |
26 | + } | |
27 | + public static final class id { | |
28 | + public static int mediacontroller_file_name=0x7f070004; | |
29 | + public static int mediacontroller_play_pause=0x7f070000; | |
30 | + public static int mediacontroller_seekbar=0x7f070003; | |
31 | + public static int mediacontroller_time_current=0x7f070001; | |
32 | + public static int mediacontroller_time_total=0x7f070002; | |
33 | + } | |
34 | + public static final class layout { | |
35 | + public static int mediacontroller=0x7f030000; | |
36 | + } | |
37 | + public static final class raw { | |
38 | + public static int libarm=0x7f040000; | |
39 | + } | |
40 | + public static final class string { | |
41 | + public static int mediacontroller_play_pause=0x7f050006; | |
42 | + public static int vitamio_init_decoders=0x7f050001; | |
43 | + public static int vitamio_name=0x7f050000; | |
44 | + public static int vitamio_videoview_error_button=0x7f050005; | |
45 | + public static int vitamio_videoview_error_text_invalid_progressive_playback=0x7f050003; | |
46 | + public static int vitamio_videoview_error_text_unknown=0x7f050004; | |
47 | + public static int vitamio_videoview_error_title=0x7f050002; | |
48 | + } | |
49 | + public static final class style { | |
50 | + public static int MediaController_SeekBar=0x7f060000; | |
51 | + public static int MediaController_Text=0x7f060001; | |
52 | + } | |
53 | +} | ... | ... |
VitamioBundle/ic_launcher-web.png
0 → 100644
14 KB
VitamioBundle/libs/vitamio.jar
0 → 100644
No preview for this file type
VitamioBundle/proguard-project.txt
0 → 100644
1 | +# To enable ProGuard in your project, edit project.properties | |
2 | +# to define the proguard.config property as described in that file. | |
3 | +# | |
4 | +# Add project specific ProGuard rules here. | |
5 | +# By default, the flags in this file are appended to flags specified | |
6 | +# in ${sdk.dir}/tools/proguard/proguard-android.txt | |
7 | +# You can edit the include path and order by changing the ProGuard | |
8 | +# include property in project.properties. | |
9 | +# | |
10 | +# For more details, see | |
11 | +# http://developer.android.com/guide/developing/tools/proguard.html | |
12 | + | |
13 | +# Add any project specific keep options here: | |
14 | + | |
15 | +# If your project uses WebView with JS, uncomment the following | |
16 | +# and specify the fully qualified class name to the JavaScript interface | |
17 | +# class: | |
18 | +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | |
19 | +# public *; | |
20 | +#} | ... | ... |
VitamioBundle/project.properties
0 → 100644
1 | +# This file is automatically generated by Android Tools. | |
2 | +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! | |
3 | +# | |
4 | +# This file must be checked in Version Control Systems. | |
5 | +# | |
6 | +# To customize properties used by the Ant build system edit | |
7 | +# "ant.properties", and override values to adapt the script to your | |
8 | +# project structure. | |
9 | +# | |
10 | +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): | |
11 | +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt | |
12 | + | |
13 | +# Project target. | |
14 | +target=android-15 | |
15 | +android.library=true | ... | ... |
VitamioBundle/res/drawable-hdpi/ic_launcher.png
0 → 100644
2.74 KB
VitamioBundle/res/drawable-hdpi/mediacontroller_bg.png
0 → 100644
3.66 KB
VitamioBundle/res/drawable-hdpi/mediacontroller_pause01.png
0 → 100644
4.6 KB
VitamioBundle/res/drawable-hdpi/mediacontroller_pause02.png
0 → 100644
4.93 KB
VitamioBundle/res/drawable-hdpi/mediacontroller_play01.png
0 → 100644
5.06 KB
VitamioBundle/res/drawable-hdpi/mediacontroller_play02.png
0 → 100644
5.32 KB
VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar01.png
0 → 100644
894 Bytes
VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar02.png
0 → 100644
932 Bytes
VitamioBundle/res/drawable-xhdpi/ic_launcher.png
0 → 100644
3.29 KB
VitamioBundle/res/drawable/mediacontroller_pause_button.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
3 | + | |
4 | + <item android:drawable="@drawable/mediacontroller_pause02" android:state_focused="true" android:state_pressed="false"/> | |
5 | + <item android:drawable="@drawable/mediacontroller_pause02" android:state_focused="true" android:state_pressed="true"/> | |
6 | + <item android:drawable="@drawable/mediacontroller_pause02" android:state_focused="false" android:state_pressed="true"/> | |
7 | + <item android:drawable="@drawable/mediacontroller_pause01"/> | |
8 | + | |
9 | +</selector> | |
0 | 10 | \ No newline at end of file | ... | ... |
VitamioBundle/res/drawable/mediacontroller_play_button.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
3 | + | |
4 | + <item android:drawable="@drawable/mediacontroller_play02" android:state_focused="true" android:state_pressed="false"/> | |
5 | + <item android:drawable="@drawable/mediacontroller_play02" android:state_focused="true" android:state_pressed="true"/> | |
6 | + <item android:drawable="@drawable/mediacontroller_play02" android:state_focused="false" android:state_pressed="true"/> | |
7 | + <item android:drawable="@drawable/mediacontroller_play01"/> | |
8 | + | |
9 | +</selector> | |
0 | 10 | \ No newline at end of file | ... | ... |
VitamioBundle/res/drawable/mediacontroller_seekbar.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > | |
3 | + | |
4 | + <item | |
5 | + android:id="@android:id/background" | |
6 | + android:drawable="@drawable/mediacontroller_seekbar02"/> | |
7 | + <item android:id="@android:id/secondaryProgress"> | |
8 | + <clip> | |
9 | + <shape> | |
10 | + <solid android:color="#00000000" /> | |
11 | + </shape> | |
12 | + </clip> | |
13 | + </item> | |
14 | + <item android:id="@android:id/progress"> | |
15 | + <clip> | |
16 | + <layer-list> | |
17 | + <item | |
18 | + android:bottom="2.0dip" | |
19 | + android:left="2.0dip" | |
20 | + android:right="2.0dip" | |
21 | + android:top="2.0dip"> | |
22 | + <bitmap | |
23 | + android:gravity="center_vertical|fill_vertical|left" | |
24 | + android:src="@drawable/mediacontroller_seekbar01" | |
25 | + android:tileMode="disabled" /> | |
26 | + </item> | |
27 | + </layer-list> | |
28 | + </clip> | |
29 | + </item> | |
30 | + | |
31 | +</layer-list> | |
0 | 32 | \ No newline at end of file | ... | ... |
VitamioBundle/res/drawable/mediacontroller_seekbar_thumb.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | |
3 | + android:shape="ring" > | |
4 | + | |
5 | + <solid android:color="#00000000" /> | |
6 | + | |
7 | + <size | |
8 | + android:height="40dip" | |
9 | + android:width="40dip" /> | |
10 | + | |
11 | +</shape> | |
0 | 12 | \ No newline at end of file | ... | ... |
VitamioBundle/res/layout/mediacontroller.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
3 | + android:layout_width="match_parent" | |
4 | + android:layout_height="74dip" | |
5 | + android:layout_alignParentBottom="true" | |
6 | + android:layout_marginBottom="0.0dip" | |
7 | + android:layout_marginLeft="0.0dip" | |
8 | + android:layout_marginRight="0.0dip" | |
9 | + android:background="@drawable/mediacontroller_bg" | |
10 | + android:orientation="horizontal" > | |
11 | + | |
12 | + <ImageButton | |
13 | + android:id="@+id/mediacontroller_play_pause" | |
14 | + android:layout_width="54.6dip" | |
15 | + android:layout_height="32dip" | |
16 | + android:layout_alignParentRight="true" | |
17 | + android:layout_centerHorizontal="true" | |
18 | + android:layout_centerVertical="true" | |
19 | + android:layout_marginRight="7.0dip" | |
20 | + android:background="#00000000" | |
21 | + android:contentDescription="@string/mediacontroller_play_pause" | |
22 | + android:gravity="center" | |
23 | + android:src="@drawable/mediacontroller_pause_button" /> | |
24 | + | |
25 | + <RelativeLayout | |
26 | + android:layout_width="match_parent" | |
27 | + android:layout_height="wrap_content" | |
28 | + android:layout_marginBottom="2dip" | |
29 | + android:layout_marginLeft="7.0dip" | |
30 | + android:layout_marginRight="7.0dip" | |
31 | + android:layout_marginTop="2dip" | |
32 | + android:layout_toLeftOf="@+id/mediacontroller_play_pause" > | |
33 | + | |
34 | + <RelativeLayout | |
35 | + android:layout_width="match_parent" | |
36 | + android:layout_height="wrap_content" > | |
37 | + | |
38 | + <TextView | |
39 | + android:id="@+id/mediacontroller_time_current" | |
40 | + style="@style/MediaController_Text" | |
41 | + android:layout_width="wrap_content" | |
42 | + android:layout_height="wrap_content" | |
43 | + android:layout_alignParentLeft="true" | |
44 | + android:layout_alignParentTop="true" /> | |
45 | + | |
46 | + <TextView | |
47 | + android:id="@+id/mediacontroller_time_total" | |
48 | + style="@style/MediaController_Text" | |
49 | + android:layout_width="wrap_content" | |
50 | + android:layout_height="wrap_content" | |
51 | + android:layout_alignParentRight="true" | |
52 | + android:layout_alignParentTop="true" /> | |
53 | + </RelativeLayout> | |
54 | + | |
55 | + <SeekBar | |
56 | + android:id="@+id/mediacontroller_seekbar" | |
57 | + style="@style/MediaController_SeekBar" | |
58 | + android:layout_width="match_parent" | |
59 | + android:layout_height="wrap_content" | |
60 | + android:layout_centerVertical="true" | |
61 | + android:focusable="true" | |
62 | + android:max="1000" /> | |
63 | + | |
64 | + <TextView | |
65 | + android:id="@+id/mediacontroller_file_name" | |
66 | + style="@style/MediaController_Text" | |
67 | + android:layout_width="wrap_content" | |
68 | + android:layout_height="wrap_content" | |
69 | + android:layout_alignParentBottom="true" | |
70 | + android:ellipsize="marquee" | |
71 | + android:singleLine="true" /> | |
72 | + </RelativeLayout> | |
73 | + | |
74 | +</RelativeLayout> | |
0 | 75 | \ No newline at end of file | ... | ... |
VitamioBundle/res/values/strings.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<resources> | |
3 | + | |
4 | + <string name="vitamio_name">Vitamio</string> | |
5 | + <string name="vitamio_init_decoders">Initializing decoders…</string> | |
6 | + <string name="vitamio_videoview_error_title">Cannot play video</string> | |
7 | + <string name="vitamio_videoview_error_text_invalid_progressive_playback">Sorry, this video is not valid for streaming to | |
8 | + this device.</string> | |
9 | + <string name="vitamio_videoview_error_text_unknown">Sorry, this video cannot be played.</string> | |
10 | + <string name="vitamio_videoview_error_button">OK</string> | |
11 | + <string name="mediacontroller_play_pause">Play/Pause</string> | |
12 | + | |
13 | +</resources> | |
0 | 14 | \ No newline at end of file | ... | ... |
VitamioBundle/res/values/styles.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<resources> | |
3 | + | |
4 | + <style name="MediaController_SeekBar"> | |
5 | + <item name="android:minHeight">16dip</item> | |
6 | + <item name="android:maxHeight">16dip</item> | |
7 | + <item name="android:progressDrawable">@drawable/mediacontroller_seekbar</item> | |
8 | + <item name="android:thumb">@drawable/mediacontroller_seekbar_thumb</item> | |
9 | + </style> | |
10 | + | |
11 | + <style name="MediaController_Text"> | |
12 | + <item name="android:textColor">#ffffffff</item> | |
13 | + <item name="android:textSize">14sp</item> | |
14 | + <item name="android:textStyle">bold</item> | |
15 | + </style> | |
16 | + | |
17 | +</resources> | |
0 | 18 | \ No newline at end of file | ... | ... |
VitamioBundle/src/io/vov/vitamio/activity/InitActivity.java
0 → 100644
1 | +/* | |
2 | + * Copyright (C) 2012 YIXIA.COM | |
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 | + | |
17 | +package io.vov.vitamio.activity; | |
18 | + | |
19 | +import io.vov.vitamio.R; | |
20 | +import io.vov.vitamio.Vitamio; | |
21 | + | |
22 | +import java.lang.ref.WeakReference; | |
23 | + | |
24 | +import android.app.Activity; | |
25 | +import android.app.ProgressDialog; | |
26 | +import android.content.Context; | |
27 | +import android.content.Intent; | |
28 | +import android.os.AsyncTask; | |
29 | +import android.os.Bundle; | |
30 | +import android.os.Handler; | |
31 | +import android.os.Message; | |
32 | +import android.view.WindowManager; | |
33 | + | |
34 | +public class InitActivity extends Activity { | |
35 | + public static final String FROM_ME = "fromVitamioInitActivity"; | |
36 | + private ProgressDialog mPD; | |
37 | + private UIHandler uiHandler; | |
38 | + | |
39 | + protected void onCreate(Bundle savedInstanceState) { | |
40 | + super.onCreate(savedInstanceState); | |
41 | + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); | |
42 | + uiHandler = new UIHandler(this); | |
43 | + | |
44 | + new AsyncTask<Object, Object, Boolean>() { | |
45 | + @Override | |
46 | + protected void onPreExecute() { | |
47 | + mPD = new ProgressDialog(InitActivity.this); | |
48 | + mPD.setCancelable(false); | |
49 | + mPD.setMessage(getString(R.string.vitamio_init_decoders)); | |
50 | + mPD.show(); | |
51 | + } | |
52 | + | |
53 | + @Override | |
54 | + protected Boolean doInBackground(Object... params) { | |
55 | + return Vitamio.initialize(InitActivity.this); | |
56 | + } | |
57 | + | |
58 | + @Override | |
59 | + protected void onPostExecute(Boolean inited) { | |
60 | + if (inited) { | |
61 | + uiHandler.sendEmptyMessage(0); | |
62 | + } | |
63 | + } | |
64 | + | |
65 | + }.execute(); | |
66 | + } | |
67 | + | |
68 | + private static class UIHandler extends Handler { | |
69 | + private WeakReference<Context> mContext; | |
70 | + | |
71 | + public UIHandler(Context c) { | |
72 | + mContext = new WeakReference<Context>(c); | |
73 | + } | |
74 | + | |
75 | + public void handleMessage(Message msg) { | |
76 | + InitActivity ctx = (InitActivity) mContext.get(); | |
77 | + switch (msg.what) { | |
78 | + case 0: | |
79 | + ctx.mPD.dismiss(); | |
80 | + Intent src = ctx.getIntent(); | |
81 | + Intent i = new Intent(); | |
82 | + i.setClassName(src.getStringExtra("package"), src.getStringExtra("className")); | |
83 | + i.setData(src.getData()); | |
84 | + i.putExtras(src); | |
85 | + i.putExtra(FROM_ME, true); | |
86 | + ctx.startActivity(i); | |
87 | + ctx.finish(); | |
88 | + break; | |
89 | + } | |
90 | + } | |
91 | + }; | |
92 | +} | ... | ... |
VitamioBundle/src/io/vov/vitamio/widget/CenterLayout.java
0 → 100644
1 | +/* | |
2 | + * Copyright (C) 2012 YIXIA.COM | |
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 | + | |
17 | +package io.vov.vitamio.widget; | |
18 | + | |
19 | +import android.content.Context; | |
20 | +import android.util.AttributeSet; | |
21 | +import android.view.View; | |
22 | +import android.view.ViewGroup; | |
23 | +import android.widget.RemoteViews.RemoteView; | |
24 | + | |
25 | +@RemoteView | |
26 | +public class CenterLayout extends ViewGroup { | |
27 | + private int mPaddingLeft = 0; | |
28 | + private int mPaddingRight = 0; | |
29 | + private int mPaddingTop = 0; | |
30 | + private int mPaddingBottom = 0; | |
31 | + private int mWidth, mHeight; | |
32 | + | |
33 | + public CenterLayout(Context context) { | |
34 | + super(context); | |
35 | + } | |
36 | + | |
37 | + public CenterLayout(Context context, AttributeSet attrs) { | |
38 | + super(context, attrs); | |
39 | + } | |
40 | + | |
41 | + public CenterLayout(Context context, AttributeSet attrs, int defStyle) { | |
42 | + super(context, attrs, defStyle); | |
43 | + } | |
44 | + | |
45 | + @Override | |
46 | + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
47 | + int count = getChildCount(); | |
48 | + | |
49 | + int maxHeight = 0; | |
50 | + int maxWidth = 0; | |
51 | + | |
52 | + measureChildren(widthMeasureSpec, heightMeasureSpec); | |
53 | + | |
54 | + for (int i = 0; i < count; i++) { | |
55 | + View child = getChildAt(i); | |
56 | + if (child.getVisibility() != GONE) { | |
57 | + int childRight; | |
58 | + int childBottom; | |
59 | + | |
60 | + CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams(); | |
61 | + | |
62 | + childRight = lp.x + child.getMeasuredWidth(); | |
63 | + childBottom = lp.y + child.getMeasuredHeight(); | |
64 | + | |
65 | + maxWidth = Math.max(maxWidth, childRight); | |
66 | + maxHeight = Math.max(maxHeight, childBottom); | |
67 | + } | |
68 | + } | |
69 | + | |
70 | + maxWidth += mPaddingLeft + mPaddingRight; | |
71 | + maxHeight += mPaddingTop + mPaddingBottom; | |
72 | + | |
73 | + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); | |
74 | + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); | |
75 | + | |
76 | + setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec)); | |
77 | + } | |
78 | + | |
79 | + @Override | |
80 | + protected void onLayout(boolean changed, int l, int t, int r, int b) { | |
81 | + int count = getChildCount(); | |
82 | + mWidth = getMeasuredWidth(); | |
83 | + mHeight = getMeasuredHeight(); | |
84 | + for (int i = 0; i < count; i++) { | |
85 | + View child = getChildAt(i); | |
86 | + if (child.getVisibility() != GONE) { | |
87 | + CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams(); | |
88 | + int childLeft = mPaddingLeft + lp.x; | |
89 | + if (lp.width > 0) | |
90 | + childLeft += (int) ((mWidth - lp.width) / 2.0); | |
91 | + else | |
92 | + childLeft += (int) ((mWidth - child.getMeasuredWidth()) / 2.0); | |
93 | + int childTop = mPaddingTop + lp.y; | |
94 | + if (lp.height > 0) | |
95 | + childTop += (int) ((mHeight - lp.height) / 2.0); | |
96 | + else | |
97 | + childTop += (int) ((mHeight - child.getMeasuredHeight()) / 2.0); | |
98 | + child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); | |
99 | + } | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + @Override | |
104 | + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { | |
105 | + return p instanceof CenterLayout.LayoutParams; | |
106 | + } | |
107 | + | |
108 | + @Override | |
109 | + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { | |
110 | + return new LayoutParams(p); | |
111 | + } | |
112 | + | |
113 | + public static class LayoutParams extends ViewGroup.LayoutParams { | |
114 | + public int x; | |
115 | + public int y; | |
116 | + | |
117 | + public LayoutParams(int width, int height, int x, int y) { | |
118 | + super(width, height); | |
119 | + this.x = x; | |
120 | + this.y = y; | |
121 | + } | |
122 | + | |
123 | + public LayoutParams(ViewGroup.LayoutParams source) { | |
124 | + super(source); | |
125 | + } | |
126 | + } | |
127 | +} | ... | ... |
VitamioBundle/src/io/vov/vitamio/widget/MediaController.java
0 → 100644
1 | +/* | |
2 | + * Copyright (C) 2006 The Android Open Source Project | |
3 | + * Copyright (C) 2012 YIXIA.COM | |
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 | + | |
18 | +package io.vov.vitamio.widget; | |
19 | + | |
20 | +import io.vov.utils.Log; | |
21 | +import io.vov.utils.StringUtils; | |
22 | +import io.vov.vitamio.R; | |
23 | +import android.content.Context; | |
24 | +import android.graphics.Rect; | |
25 | +import android.media.AudioManager; | |
26 | +import android.os.Handler; | |
27 | +import android.os.Message; | |
28 | +import android.util.AttributeSet; | |
29 | +import android.view.Gravity; | |
30 | +import android.view.KeyEvent; | |
31 | +import android.view.LayoutInflater; | |
32 | +import android.view.MotionEvent; | |
33 | +import android.view.View; | |
34 | +import android.widget.FrameLayout; | |
35 | +import android.widget.ImageButton; | |
36 | +import android.widget.PopupWindow; | |
37 | +import android.widget.ProgressBar; | |
38 | +import android.widget.SeekBar; | |
39 | +import android.widget.SeekBar.OnSeekBarChangeListener; | |
40 | +import android.widget.TextView; | |
41 | + | |
42 | +/** | |
43 | + * A view containing controls for a MediaPlayer. Typically contains the buttons | |
44 | + * like "Play/Pause" and a progress slider. It takes care of synchronizing the | |
45 | + * controls with the state of the MediaPlayer. | |
46 | + * <p> | |
47 | + * The way to use this class is to a) instantiate it programatically or b) | |
48 | + * create it in your xml layout. | |
49 | + * | |
50 | + * a) The MediaController will create a default set of controls and put them in | |
51 | + * a window floating above your application. Specifically, the controls will | |
52 | + * float above the view specified with setAnchorView(). By default, the window | |
53 | + * will disappear if left idle for three seconds and reappear when the user | |
54 | + * touches the anchor view. To customize the MediaController's style, layout and | |
55 | + * controls you should extend MediaController and override the {#link | |
56 | + * {@link #makeControllerView()} method. | |
57 | + * | |
58 | + * b) The MediaController is a FrameLayout, you can put it in your layout xml | |
59 | + * and get it through {@link #findViewById(int)}. | |
60 | + * | |
61 | + * NOTES: In each way, if you want customize the MediaController, the SeekBar's | |
62 | + * id must be mediacontroller_progress, the Play/Pause's must be | |
63 | + * mediacontroller_pause, current time's must be mediacontroller_time_current, | |
64 | + * total time's must be mediacontroller_time_total, file name's must be | |
65 | + * mediacontroller_file_name. And your resources must have a pause_button | |
66 | + * drawable and a play_button drawable. | |
67 | + * <p> | |
68 | + * Functions like show() and hide() have no effect when MediaController is | |
69 | + * created in an xml layout. | |
70 | + */ | |
71 | +public class MediaController extends FrameLayout { | |
72 | + private MediaPlayerControl mPlayer; | |
73 | + private Context mContext; | |
74 | + private PopupWindow mWindow; | |
75 | + private int mAnimStyle; | |
76 | + private View mAnchor; | |
77 | + private View mRoot; | |
78 | + private ProgressBar mProgress; | |
79 | + private TextView mEndTime, mCurrentTime; | |
80 | + private TextView mFileName; | |
81 | + private OutlineTextView mInfoView; | |
82 | + private String mTitle; | |
83 | + private long mDuration; | |
84 | + private boolean mShowing; | |
85 | + private boolean mDragging; | |
86 | + private boolean mInstantSeeking = true; | |
87 | + private static final int sDefaultTimeout = 3000; | |
88 | + private static final int FADE_OUT = 1; | |
89 | + private static final int SHOW_PROGRESS = 2; | |
90 | + private boolean mFromXml = false; | |
91 | + private ImageButton mPauseButton; | |
92 | + | |
93 | + private AudioManager mAM; | |
94 | + | |
95 | + public MediaController(Context context, AttributeSet attrs) { | |
96 | + super(context, attrs); | |
97 | + mRoot = this; | |
98 | + mFromXml = true; | |
99 | + initController(context); | |
100 | + } | |
101 | + | |
102 | + public MediaController(Context context) { | |
103 | + super(context); | |
104 | + if (!mFromXml && initController(context)) | |
105 | + initFloatingWindow(); | |
106 | + } | |
107 | + | |
108 | + private boolean initController(Context context) { | |
109 | + mContext = context; | |
110 | + mAM = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); | |
111 | + return true; | |
112 | + } | |
113 | + | |
114 | + @Override | |
115 | + public void onFinishInflate() { | |
116 | + if (mRoot != null) | |
117 | + initControllerView(mRoot); | |
118 | + } | |
119 | + | |
120 | + private void initFloatingWindow() { | |
121 | + mWindow = new PopupWindow(mContext); | |
122 | + mWindow.setFocusable(false); | |
123 | + mWindow.setBackgroundDrawable(null); | |
124 | + mWindow.setOutsideTouchable(true); | |
125 | + mAnimStyle = android.R.style.Animation; | |
126 | + } | |
127 | + | |
128 | + /** | |
129 | + * Set the view that acts as the anchor for the control view. This can for | |
130 | + * example be a VideoView, or your Activity's main view. | |
131 | + * | |
132 | + * @param view | |
133 | + * The view to which to anchor the controller when it is visible. | |
134 | + */ | |
135 | + public void setAnchorView(View view) { | |
136 | + mAnchor = view; | |
137 | + if (!mFromXml) { | |
138 | + removeAllViews(); | |
139 | + mRoot = makeControllerView(); | |
140 | + mWindow.setContentView(mRoot); | |
141 | + mWindow.setWidth(LayoutParams.MATCH_PARENT); | |
142 | + mWindow.setHeight(LayoutParams.WRAP_CONTENT); | |
143 | + } | |
144 | + initControllerView(mRoot); | |
145 | + } | |
146 | + | |
147 | + /** | |
148 | + * Create the view that holds the widgets that control playback. Derived | |
149 | + * classes can override this to create their own. | |
150 | + * | |
151 | + * @return The controller view. | |
152 | + */ | |
153 | + protected View makeControllerView() { | |
154 | + return ((LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.mediacontroller, this); | |
155 | + } | |
156 | + | |
157 | + private void initControllerView(View v) { | |
158 | + mPauseButton = (ImageButton) v.findViewById(R.id.mediacontroller_play_pause); | |
159 | + if (mPauseButton != null) { | |
160 | + mPauseButton.requestFocus(); | |
161 | + mPauseButton.setOnClickListener(mPauseListener); | |
162 | + } | |
163 | + | |
164 | + mProgress = (ProgressBar) v.findViewById(R.id.mediacontroller_seekbar); | |
165 | + if (mProgress != null) { | |
166 | + if (mProgress instanceof SeekBar) { | |
167 | + SeekBar seeker = (SeekBar) mProgress; | |
168 | + seeker.setOnSeekBarChangeListener(mSeekListener); | |
169 | + seeker.setThumbOffset(1); | |
170 | + } | |
171 | + mProgress.setMax(1000); | |
172 | + } | |
173 | + | |
174 | + mEndTime = (TextView) v.findViewById(R.id.mediacontroller_time_total); | |
175 | + mCurrentTime = (TextView) v.findViewById(R.id.mediacontroller_time_current); | |
176 | + mFileName = (TextView) v.findViewById(R.id.mediacontroller_file_name); | |
177 | + if (mFileName != null) | |
178 | + mFileName.setText(mTitle); | |
179 | + } | |
180 | + | |
181 | + public void setMediaPlayer(MediaPlayerControl player) { | |
182 | + mPlayer = player; | |
183 | + updatePausePlay(); | |
184 | + } | |
185 | + | |
186 | + /** | |
187 | + * Control the action when the seekbar dragged by user | |
188 | + * | |
189 | + * @param seekWhenDragging | |
190 | + * True the media will seek periodically | |
191 | + */ | |
192 | + public void setInstantSeeking(boolean seekWhenDragging) { | |
193 | + mInstantSeeking = seekWhenDragging; | |
194 | + } | |
195 | + | |
196 | + public void show() { | |
197 | + show(sDefaultTimeout); | |
198 | + } | |
199 | + | |
200 | + /** | |
201 | + * Set the content of the file_name TextView | |
202 | + * | |
203 | + * @param name | |
204 | + */ | |
205 | + public void setFileName(String name) { | |
206 | + mTitle = name; | |
207 | + if (mFileName != null) | |
208 | + mFileName.setText(mTitle); | |
209 | + } | |
210 | + | |
211 | + /** | |
212 | + * Set the View to hold some information when interact with the | |
213 | + * MediaController | |
214 | + * | |
215 | + * @param v | |
216 | + */ | |
217 | + public void setInfoView(OutlineTextView v) { | |
218 | + mInfoView = v; | |
219 | + } | |
220 | + | |
221 | + private void disableUnsupportedButtons() { | |
222 | + try { | |
223 | + if (mPauseButton != null && !mPlayer.canPause()) | |
224 | + mPauseButton.setEnabled(false); | |
225 | + } catch (IncompatibleClassChangeError ex) { | |
226 | + } | |
227 | + } | |
228 | + | |
229 | + /** | |
230 | + * <p> | |
231 | + * Change the animation style resource for this controller. | |
232 | + * </p> | |
233 | + * | |
234 | + * <p> | |
235 | + * If the controller is showing, calling this method will take effect only | |
236 | + * the next time the controller is shown. | |
237 | + * </p> | |
238 | + * | |
239 | + * @param animationStyle | |
240 | + * animation style to use when the controller appears and | |
241 | + * disappears. Set to -1 for the default animation, 0 for no | |
242 | + * animation, or a resource identifier for an explicit animation. | |
243 | + * | |
244 | + */ | |
245 | + public void setAnimationStyle(int animationStyle) { | |
246 | + mAnimStyle = animationStyle; | |
247 | + } | |
248 | + | |
249 | + /** | |
250 | + * Show the controller on screen. It will go away automatically after | |
251 | + * 'timeout' milliseconds of inactivity. | |
252 | + * | |
253 | + * @param timeout | |
254 | + * The timeout in milliseconds. Use 0 to show the controller | |
255 | + * until hide() is called. | |
256 | + */ | |
257 | + public void show(int timeout) { | |
258 | + if (!mShowing && mAnchor != null && mAnchor.getWindowToken() != null) { | |
259 | + if (mPauseButton != null) | |
260 | + mPauseButton.requestFocus(); | |
261 | + disableUnsupportedButtons(); | |
262 | + | |
263 | + if (mFromXml) { | |
264 | + setVisibility(View.VISIBLE); | |
265 | + } else { | |
266 | + int[] location = new int[2]; | |
267 | + | |
268 | + mAnchor.getLocationOnScreen(location); | |
269 | + Rect anchorRect = new Rect(location[0], location[1], location[0] + mAnchor.getWidth(), location[1] + mAnchor.getHeight()); | |
270 | + | |
271 | + mWindow.setAnimationStyle(mAnimStyle); | |
272 | + mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, anchorRect.left, anchorRect.bottom); | |
273 | + } | |
274 | + mShowing = true; | |
275 | + if (mShownListener != null) | |
276 | + mShownListener.onShown(); | |
277 | + } | |
278 | + updatePausePlay(); | |
279 | + mHandler.sendEmptyMessage(SHOW_PROGRESS); | |
280 | + | |
281 | + if (timeout != 0) { | |
282 | + mHandler.removeMessages(FADE_OUT); | |
283 | + mHandler.sendMessageDelayed(mHandler.obtainMessage(FADE_OUT), timeout); | |
284 | + } | |
285 | + } | |
286 | + | |
287 | + public boolean isShowing() { | |
288 | + return mShowing; | |
289 | + } | |
290 | + | |
291 | + public void hide() { | |
292 | + if (mAnchor == null) | |
293 | + return; | |
294 | + | |
295 | + if (mShowing) { | |
296 | + try { | |
297 | + mHandler.removeMessages(SHOW_PROGRESS); | |
298 | + if (mFromXml) | |
299 | + setVisibility(View.GONE); | |
300 | + else | |
301 | + mWindow.dismiss(); | |
302 | + } catch (IllegalArgumentException ex) { | |
303 | + Log.d("MediaController already removed"); | |
304 | + } | |
305 | + mShowing = false; | |
306 | + if (mHiddenListener != null) | |
307 | + mHiddenListener.onHidden(); | |
308 | + } | |
309 | + } | |
310 | + | |
311 | + public interface OnShownListener { | |
312 | + public void onShown(); | |
313 | + } | |
314 | + | |
315 | + private OnShownListener mShownListener; | |
316 | + | |
317 | + public void setOnShownListener(OnShownListener l) { | |
318 | + mShownListener = l; | |
319 | + } | |
320 | + | |
321 | + public interface OnHiddenListener { | |
322 | + public void onHidden(); | |
323 | + } | |
324 | + | |
325 | + private OnHiddenListener mHiddenListener; | |
326 | + | |
327 | + public void setOnHiddenListener(OnHiddenListener l) { | |
328 | + mHiddenListener = l; | |
329 | + } | |
330 | + | |
331 | + private Handler mHandler = new Handler() { | |
332 | + @Override | |
333 | + public void handleMessage(Message msg) { | |
334 | + long pos; | |
335 | + switch (msg.what) { | |
336 | + case FADE_OUT: | |
337 | + hide(); | |
338 | + break; | |
339 | + case SHOW_PROGRESS: | |
340 | + pos = setProgress(); | |
341 | + if (!mDragging && mShowing) { | |
342 | + msg = obtainMessage(SHOW_PROGRESS); | |
343 | + sendMessageDelayed(msg, 1000 - (pos % 1000)); | |
344 | + updatePausePlay(); | |
345 | + } | |
346 | + break; | |
347 | + } | |
348 | + } | |
349 | + }; | |
350 | + | |
351 | + private long setProgress() { | |
352 | + if (mPlayer == null || mDragging) | |
353 | + return 0; | |
354 | + | |
355 | + long position = mPlayer.getCurrentPosition(); | |
356 | + long duration = mPlayer.getDuration(); | |
357 | + if (mProgress != null) { | |
358 | + if (duration > 0) { | |
359 | + long pos = 1000L * position / duration; | |
360 | + mProgress.setProgress((int) pos); | |
361 | + } | |
362 | + int percent = mPlayer.getBufferPercentage(); | |
363 | + mProgress.setSecondaryProgress(percent * 10); | |
364 | + } | |
365 | + | |
366 | + mDuration = duration; | |
367 | + | |
368 | + if (mEndTime != null) | |
369 | + mEndTime.setText(StringUtils.generateTime(mDuration)); | |
370 | + if (mCurrentTime != null) | |
371 | + mCurrentTime.setText(StringUtils.generateTime(position)); | |
372 | + | |
373 | + return position; | |
374 | + } | |
375 | + | |
376 | + @Override | |
377 | + public boolean onTouchEvent(MotionEvent event) { | |
378 | + show(sDefaultTimeout); | |
379 | + return true; | |
380 | + } | |
381 | + | |
382 | + @Override | |
383 | + public boolean onTrackballEvent(MotionEvent ev) { | |
384 | + show(sDefaultTimeout); | |
385 | + return false; | |
386 | + } | |
387 | + | |
388 | + @Override | |
389 | + public boolean dispatchKeyEvent(KeyEvent event) { | |
390 | + int keyCode = event.getKeyCode(); | |
391 | + if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE)) { | |
392 | + doPauseResume(); | |
393 | + show(sDefaultTimeout); | |
394 | + if (mPauseButton != null) | |
395 | + mPauseButton.requestFocus(); | |
396 | + return true; | |
397 | + } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) { | |
398 | + if (mPlayer.isPlaying()) { | |
399 | + mPlayer.pause(); | |
400 | + updatePausePlay(); | |
401 | + } | |
402 | + return true; | |
403 | + } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) { | |
404 | + hide(); | |
405 | + return true; | |
406 | + } else { | |
407 | + show(sDefaultTimeout); | |
408 | + } | |
409 | + return super.dispatchKeyEvent(event); | |
410 | + } | |
411 | + | |
412 | + private View.OnClickListener mPauseListener = new View.OnClickListener() { | |
413 | + public void onClick(View v) { | |
414 | + doPauseResume(); | |
415 | + show(sDefaultTimeout); | |
416 | + } | |
417 | + }; | |
418 | + | |
419 | + private void updatePausePlay() { | |
420 | + if (mRoot == null || mPauseButton == null) | |
421 | + return; | |
422 | + | |
423 | + if (mPlayer.isPlaying()) | |
424 | + mPauseButton.setImageResource(R.drawable.mediacontroller_pause_button); | |
425 | + else | |
426 | + mPauseButton.setImageResource(R.drawable.mediacontroller_play_button); | |
427 | + } | |
428 | + | |
429 | + private void doPauseResume() { | |
430 | + if (mPlayer.isPlaying()) | |
431 | + mPlayer.pause(); | |
432 | + else | |
433 | + mPlayer.start(); | |
434 | + updatePausePlay(); | |
435 | + } | |
436 | + | |
437 | + private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() { | |
438 | + public void onStartTrackingTouch(SeekBar bar) { | |
439 | + mDragging = true; | |
440 | + show(3600000); | |
441 | + mHandler.removeMessages(SHOW_PROGRESS); | |
442 | + if (mInstantSeeking) | |
443 | + mAM.setStreamMute(AudioManager.STREAM_MUSIC, true); | |
444 | + if (mInfoView != null) { | |
445 | + mInfoView.setText(""); | |
446 | + mInfoView.setVisibility(View.VISIBLE); | |
447 | + } | |
448 | + } | |
449 | + | |
450 | + public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) { | |
451 | + if (!fromuser) | |
452 | + return; | |
453 | + | |
454 | + long newposition = (mDuration * progress) / 1000; | |
455 | + String time = StringUtils.generateTime(newposition); | |
456 | + if (mInstantSeeking) | |
457 | + mPlayer.seekTo(newposition); | |
458 | + if (mInfoView != null) | |
459 | + mInfoView.setText(time); | |
460 | + if (mCurrentTime != null) | |
461 | + mCurrentTime.setText(time); | |
462 | + } | |
463 | + | |
464 | + public void onStopTrackingTouch(SeekBar bar) { | |
465 | + if (!mInstantSeeking) | |
466 | + mPlayer.seekTo((mDuration * bar.getProgress()) / 1000); | |
467 | + if (mInfoView != null) { | |
468 | + mInfoView.setText(""); | |
469 | + mInfoView.setVisibility(View.GONE); | |
470 | + } | |
471 | + show(sDefaultTimeout); | |
472 | + mHandler.removeMessages(SHOW_PROGRESS); | |
473 | + mAM.setStreamMute(AudioManager.STREAM_MUSIC, false); | |
474 | + mDragging = false; | |
475 | + mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS, 1000); | |
476 | + } | |
477 | + }; | |
478 | + | |
479 | + @Override | |
480 | + public void setEnabled(boolean enabled) { | |
481 | + if (mPauseButton != null) | |
482 | + mPauseButton.setEnabled(enabled); | |
483 | + if (mProgress != null) | |
484 | + mProgress.setEnabled(enabled); | |
485 | + disableUnsupportedButtons(); | |
486 | + super.setEnabled(enabled); | |
487 | + } | |
488 | + | |
489 | + public interface MediaPlayerControl { | |
490 | + void start(); | |
491 | + | |
492 | + void pause(); | |
493 | + | |
494 | + long getDuration(); | |
495 | + | |
496 | + long getCurrentPosition(); | |
497 | + | |
498 | + void seekTo(long pos); | |
499 | + | |
500 | + boolean isPlaying(); | |
501 | + | |
502 | + int getBufferPercentage(); | |
503 | + | |
504 | + boolean canPause(); | |
505 | + | |
506 | + boolean canSeekBackward(); | |
507 | + | |
508 | + boolean canSeekForward(); | |
509 | + } | |
510 | + | |
511 | +} | ... | ... |
VitamioBundle/src/io/vov/vitamio/widget/OutlineTextView.java
0 → 100644
1 | +/* | |
2 | + * Copyright (C) 2011 Cedric Fung (wolfplanet@gmail.com) | |
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 | + | |
17 | +package io.vov.vitamio.widget; | |
18 | + | |
19 | +import android.annotation.SuppressLint; | |
20 | +import android.content.Context; | |
21 | +import android.graphics.Canvas; | |
22 | +import android.graphics.Paint; | |
23 | +import android.graphics.Typeface; | |
24 | +import android.text.Layout; | |
25 | +import android.text.StaticLayout; | |
26 | +import android.text.TextPaint; | |
27 | +import android.util.AttributeSet; | |
28 | +import android.widget.TextView; | |
29 | + | |
30 | +/** | |
31 | + * Display text with border, use the same XML attrs as | |
32 | + * {@link android.widget.TextView}, except that {@link OutlineTextView} will | |
33 | + * transform the shadow to border | |
34 | + */ | |
35 | +@SuppressLint("DrawAllocation") | |
36 | +public class OutlineTextView extends TextView { | |
37 | + public OutlineTextView(Context context) { | |
38 | + super(context); | |
39 | + initPaint(); | |
40 | + } | |
41 | + | |
42 | + public OutlineTextView(Context context, AttributeSet attrs) { | |
43 | + super(context, attrs); | |
44 | + initPaint(); | |
45 | + } | |
46 | + | |
47 | + public OutlineTextView(Context context, AttributeSet attrs, int defStyle) { | |
48 | + super(context, attrs, defStyle); | |
49 | + initPaint(); | |
50 | + } | |
51 | + | |
52 | + private void initPaint() { | |
53 | + mTextPaint = new TextPaint(); | |
54 | + mTextPaint.setAntiAlias(true); | |
55 | + mTextPaint.setTextSize(getTextSize()); | |
56 | + mTextPaint.setColor(mColor); | |
57 | + mTextPaint.setStyle(Paint.Style.FILL); | |
58 | + mTextPaint.setTypeface(getTypeface()); | |
59 | + | |
60 | + mTextPaintOutline = new TextPaint(); | |
61 | + mTextPaintOutline.setAntiAlias(true); | |
62 | + mTextPaintOutline.setTextSize(getTextSize()); | |
63 | + mTextPaintOutline.setColor(mBorderColor); | |
64 | + mTextPaintOutline.setStyle(Paint.Style.STROKE); | |
65 | + mTextPaintOutline.setTypeface(getTypeface()); | |
66 | + mTextPaintOutline.setStrokeWidth(mBorderSize); | |
67 | + } | |
68 | + | |
69 | + public void setText(String text) { | |
70 | + super.setText(text); | |
71 | + mText = text.toString(); | |
72 | + requestLayout(); | |
73 | + invalidate(); | |
74 | + } | |
75 | + | |
76 | + public void setTextSize(float size) { | |
77 | + super.setTextSize(size); | |
78 | + requestLayout(); | |
79 | + invalidate(); | |
80 | + initPaint(); | |
81 | + } | |
82 | + | |
83 | + public void setTextColor(int color) { | |
84 | + super.setTextColor(color); | |
85 | + mColor = color; | |
86 | + invalidate(); | |
87 | + initPaint(); | |
88 | + } | |
89 | + | |
90 | + public void setShadowLayer(float radius, float dx, float dy, int color) { | |
91 | + super.setShadowLayer(radius, dx, dy, color); | |
92 | + mBorderSize = radius; | |
93 | + mBorderColor = color; | |
94 | + requestLayout(); | |
95 | + invalidate(); | |
96 | + initPaint(); | |
97 | + } | |
98 | + | |
99 | + public void setTypeface(Typeface tf, int style) { | |
100 | + super.setTypeface(tf, style); | |
101 | + requestLayout(); | |
102 | + invalidate(); | |
103 | + initPaint(); | |
104 | + } | |
105 | + | |
106 | + public void setTypeface(Typeface tf) { | |
107 | + super.setTypeface(tf); | |
108 | + requestLayout(); | |
109 | + invalidate(); | |
110 | + initPaint(); | |
111 | + } | |
112 | + | |
113 | + @Override | |
114 | + protected void onDraw(Canvas canvas) { | |
115 | + Layout layout = new StaticLayout(getText(), mTextPaintOutline, getWidth(), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); | |
116 | + layout.draw(canvas); | |
117 | + layout = new StaticLayout(getText(), mTextPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); | |
118 | + layout.draw(canvas); | |
119 | + } | |
120 | + | |
121 | + @Override | |
122 | + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
123 | + Layout layout = new StaticLayout(getText(), mTextPaintOutline, measureWidth(widthMeasureSpec), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); | |
124 | + int ex = (int) (mBorderSize * 2 + 1); | |
125 | + setMeasuredDimension(measureWidth(widthMeasureSpec) + ex, measureHeight(heightMeasureSpec) * layout.getLineCount() + ex); | |
126 | + } | |
127 | + | |
128 | + private int measureWidth(int measureSpec) { | |
129 | + int result = 0; | |
130 | + int specMode = MeasureSpec.getMode(measureSpec); | |
131 | + int specSize = MeasureSpec.getSize(measureSpec); | |
132 | + | |
133 | + if (specMode == MeasureSpec.EXACTLY) { | |
134 | + result = specSize; | |
135 | + } else { | |
136 | + result = (int) mTextPaintOutline.measureText(mText) + getPaddingLeft() + getPaddingRight(); | |
137 | + if (specMode == MeasureSpec.AT_MOST) { | |
138 | + result = Math.min(result, specSize); | |
139 | + } | |
140 | + } | |
141 | + | |
142 | + return result; | |
143 | + } | |
144 | + | |
145 | + private int measureHeight(int measureSpec) { | |
146 | + int result = 0; | |
147 | + int specMode = MeasureSpec.getMode(measureSpec); | |
148 | + int specSize = MeasureSpec.getSize(measureSpec); | |
149 | + | |
150 | + mAscent = (int) mTextPaintOutline.ascent(); | |
151 | + if (specMode == MeasureSpec.EXACTLY) { | |
152 | + result = specSize; | |
153 | + } else { | |
154 | + result = (int) (-mAscent + mTextPaintOutline.descent()) + getPaddingTop() + getPaddingBottom(); | |
155 | + if (specMode == MeasureSpec.AT_MOST) { | |
156 | + result = Math.min(result, specSize); | |
157 | + } | |
158 | + } | |
159 | + return result; | |
160 | + } | |
161 | + | |
162 | + private TextPaint mTextPaint; | |
163 | + private TextPaint mTextPaintOutline; | |
164 | + private String mText = ""; | |
165 | + private int mAscent = 0; | |
166 | + private float mBorderSize; | |
167 | + private int mBorderColor; | |
168 | + private int mColor; | |
169 | + private float mSpacingMult = 1.0f; | |
170 | + private float mSpacingAdd = 0; | |
171 | + private boolean mIncludePad = true; | |
172 | +} | |
0 | 173 | \ No newline at end of file | ... | ... |
VitamioBundle/src/io/vov/vitamio/widget/VideoView.java
0 → 100644
1 | +/* | |
2 | + * Copyright (C) 2006 The Android Open Source Project | |
3 | + * Copyright (C) 2012 YIXIA.COM | |
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 | + | |
18 | +package io.vov.vitamio.widget; | |
19 | + | |
20 | +import io.vov.utils.Log; | |
21 | +import io.vov.vitamio.MediaPlayer; | |
22 | +import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener; | |
23 | +import io.vov.vitamio.MediaPlayer.OnCompletionListener; | |
24 | +import io.vov.vitamio.MediaPlayer.OnErrorListener; | |
25 | +import io.vov.vitamio.MediaPlayer.OnInfoListener; | |
26 | +import io.vov.vitamio.MediaPlayer.OnPreparedListener; | |
27 | +import io.vov.vitamio.MediaPlayer.OnSeekCompleteListener; | |
28 | +import io.vov.vitamio.MediaPlayer.OnSubtitleUpdateListener; | |
29 | +import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener; | |
30 | +import io.vov.vitamio.R; | |
31 | + | |
32 | +import java.io.IOException; | |
33 | +import java.util.HashMap; | |
34 | +import java.util.List; | |
35 | + | |
36 | +import android.app.Activity; | |
37 | +import android.app.AlertDialog; | |
38 | +import android.content.Context; | |
39 | +import android.content.DialogInterface; | |
40 | +import android.content.Intent; | |
41 | +import android.media.AudioManager; | |
42 | +import android.net.Uri; | |
43 | +import android.util.AttributeSet; | |
44 | +import android.util.DisplayMetrics; | |
45 | +import android.view.KeyEvent; | |
46 | +import android.view.MotionEvent; | |
47 | +import android.view.SurfaceHolder; | |
48 | +import android.view.SurfaceView; | |
49 | +import android.view.View; | |
50 | +import android.view.ViewGroup.LayoutParams; | |
51 | + | |
52 | +/** | |
53 | + * Displays a video file. The VideoView class can load images from various | |
54 | + * sources (such as resources or content providers), takes care of computing its | |
55 | + * measurement from the video so that it can be used in any layout manager, and | |
56 | + * provides various display options such as scaling and tinting. | |
57 | + * | |
58 | + * VideoView also provide many wrapper methods for | |
59 | + * {@link io.vov.vitamio.MediaPlayer}, such as {@link #getVideoWidth()}, | |
60 | + * {@link #setSubShown(boolean)} | |
61 | + */ | |
62 | +public class VideoView extends SurfaceView implements MediaController.MediaPlayerControl { | |
63 | + private Uri mUri; | |
64 | + private long mDuration; | |
65 | + | |
66 | + private static final int STATE_ERROR = -1; | |
67 | + private static final int STATE_IDLE = 0; | |
68 | + private static final int STATE_PREPARING = 1; | |
69 | + private static final int STATE_PREPARED = 2; | |
70 | + private static final int STATE_PLAYING = 3; | |
71 | + private static final int STATE_PAUSED = 4; | |
72 | + private static final int STATE_PLAYBACK_COMPLETED = 5; | |
73 | + private static final int STATE_SUSPEND = 6; | |
74 | + private static final int STATE_RESUME = 7; | |
75 | + private static final int STATE_SUSPEND_UNSUPPORTED = 8; | |
76 | + | |
77 | + private int mCurrentState = STATE_IDLE; | |
78 | + private int mTargetState = STATE_IDLE; | |
79 | + | |
80 | + private float mAspectRatio = 0; | |
81 | + private int mVideoLayout = VIDEO_LAYOUT_SCALE; | |
82 | + public static final int VIDEO_LAYOUT_ORIGIN = 0; | |
83 | + public static final int VIDEO_LAYOUT_SCALE = 1; | |
84 | + public static final int VIDEO_LAYOUT_STRETCH = 2; | |
85 | + public static final int VIDEO_LAYOUT_ZOOM = 3; | |
86 | + | |
87 | + private SurfaceHolder mSurfaceHolder = null; | |
88 | + private MediaPlayer mMediaPlayer = null; | |
89 | + private int mVideoWidth; | |
90 | + private int mVideoHeight; | |
91 | + private float mVideoAspectRatio; | |
92 | + private int mSurfaceWidth; | |
93 | + private int mSurfaceHeight; | |
94 | + private MediaController mMediaController; | |
95 | + private OnCompletionListener mOnCompletionListener; | |
96 | + private OnPreparedListener mOnPreparedListener; | |
97 | + private OnErrorListener mOnErrorListener; | |
98 | + private OnSeekCompleteListener mOnSeekCompleteListener; | |
99 | + private OnSubtitleUpdateListener mOnSubtitleUpdateListener; | |
100 | + private OnInfoListener mOnInfoListener; | |
101 | + private OnBufferingUpdateListener mOnBufferingUpdateListener; | |
102 | + private int mCurrentBufferPercentage; | |
103 | + private long mSeekWhenPrepared; | |
104 | + private boolean mCanPause = true; | |
105 | + private boolean mCanSeekBack = true; | |
106 | + private boolean mCanSeekForward = true; | |
107 | + private Context mContext; | |
108 | + | |
109 | + public VideoView(Context context) { | |
110 | + super(context); | |
111 | + initVideoView(context); | |
112 | + } | |
113 | + | |
114 | + public VideoView(Context context, AttributeSet attrs) { | |
115 | + this(context, attrs, 0); | |
116 | + } | |
117 | + | |
118 | + public VideoView(Context context, AttributeSet attrs, int defStyle) { | |
119 | + super(context, attrs, defStyle); | |
120 | + initVideoView(context); | |
121 | + } | |
122 | + | |
123 | + @Override | |
124 | + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
125 | + int width = getDefaultSize(mVideoWidth, widthMeasureSpec); | |
126 | + int height = getDefaultSize(mVideoHeight, heightMeasureSpec); | |
127 | + setMeasuredDimension(width, height); | |
128 | + } | |
129 | + | |
130 | + /** | |
131 | + * Set the display options | |
132 | + * | |
133 | + * @param layout | |
134 | + * <ul> | |
135 | + * <li>{@link #VIDEO_LAYOUT_ORIGIN} | |
136 | + * <li>{@link #VIDEO_LAYOUT_SCALE} | |
137 | + * <li>{@link #VIDEO_LAYOUT_STRETCH} | |
138 | + * <li>{@link #VIDEO_LAYOUT_ZOOM} | |
139 | + * </ul> | |
140 | + * @param aspectRatio | |
141 | + * video aspect ratio, will audo detect if 0. | |
142 | + */ | |
143 | + public void setVideoLayout(int layout, float aspectRatio) { | |
144 | + LayoutParams lp = getLayoutParams(); | |
145 | + DisplayMetrics disp = mContext.getResources().getDisplayMetrics(); | |
146 | + int windowWidth = disp.widthPixels, windowHeight = disp.heightPixels; | |
147 | + float windowRatio = windowWidth / (float) windowHeight; | |
148 | + float videoRatio = aspectRatio <= 0.01f ? mVideoAspectRatio : aspectRatio; | |
149 | + mSurfaceHeight = mVideoHeight; | |
150 | + mSurfaceWidth = mVideoWidth; | |
151 | + if (VIDEO_LAYOUT_ORIGIN == layout && mSurfaceWidth < windowWidth && mSurfaceHeight < windowHeight) { | |
152 | + lp.width = (int) (mSurfaceHeight * videoRatio); | |
153 | + lp.height = mSurfaceHeight; | |
154 | + } else if (layout == VIDEO_LAYOUT_ZOOM) { | |
155 | + lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight); | |
156 | + lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio); | |
157 | + } else { | |
158 | + boolean full = layout == VIDEO_LAYOUT_STRETCH; | |
159 | + lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight); | |
160 | + lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio); | |
161 | + } | |
162 | + setLayoutParams(lp); | |
163 | + getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight); | |
164 | + Log.d("VIDEO: %dx%dx%f, Surface: %dx%d, LP: %dx%d, Window: %dx%dx%f", mVideoWidth, mVideoHeight, mVideoAspectRatio, mSurfaceWidth, mSurfaceHeight, lp.width, lp.height, windowWidth, windowHeight, windowRatio); | |
165 | + mVideoLayout = layout; | |
166 | + mAspectRatio = aspectRatio; | |
167 | + } | |
168 | + | |
169 | + private void initVideoView(Context ctx) { | |
170 | + mContext = ctx; | |
171 | + mVideoWidth = 0; | |
172 | + mVideoHeight = 0; | |
173 | + getHolder().addCallback(mSHCallback); | |
174 | + setFocusable(true); | |
175 | + setFocusableInTouchMode(true); | |
176 | + requestFocus(); | |
177 | + mCurrentState = STATE_IDLE; | |
178 | + mTargetState = STATE_IDLE; | |
179 | + if (ctx instanceof Activity) | |
180 | + ((Activity) ctx).setVolumeControlStream(AudioManager.STREAM_MUSIC); | |
181 | + } | |
182 | + | |
183 | + public boolean isValid() { | |
184 | + return (mSurfaceHolder != null && mSurfaceHolder.getSurface().isValid()); | |
185 | + } | |
186 | + | |
187 | + public void setVideoPath(String path) { | |
188 | + setVideoURI(Uri.parse(path)); | |
189 | + } | |
190 | + | |
191 | + public void setVideoURI(Uri uri) { | |
192 | + mUri = uri; | |
193 | + mSeekWhenPrepared = 0; | |
194 | + openVideo(); | |
195 | + requestLayout(); | |
196 | + invalidate(); | |
197 | + } | |
198 | + | |
199 | + public void stopPlayback() { | |
200 | + if (mMediaPlayer != null) { | |
201 | + mMediaPlayer.stop(); | |
202 | + mMediaPlayer.release(); | |
203 | + mMediaPlayer = null; | |
204 | + mCurrentState = STATE_IDLE; | |
205 | + mTargetState = STATE_IDLE; | |
206 | + } | |
207 | + } | |
208 | + | |
209 | + private void openVideo() { | |
210 | + if (mUri == null || mSurfaceHolder == null) | |
211 | + return; | |
212 | + | |
213 | + Intent i = new Intent("com.android.music.musicservicecommand"); | |
214 | + i.putExtra("command", "pause"); | |
215 | + mContext.sendBroadcast(i); | |
216 | + | |
217 | + release(false); | |
218 | + try { | |
219 | + mDuration = -1; | |
220 | + mCurrentBufferPercentage = 0; | |
221 | + mMediaPlayer = new MediaPlayer(mContext); | |
222 | + mMediaPlayer.setOnPreparedListener(mPreparedListener); | |
223 | + mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); | |
224 | + mMediaPlayer.setOnCompletionListener(mCompletionListener); | |
225 | + mMediaPlayer.setOnErrorListener(mErrorListener); | |
226 | + mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); | |
227 | + mMediaPlayer.setOnInfoListener(mInfoListener); | |
228 | + mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener); | |
229 | + mMediaPlayer.setOnSubtitleUpdateListener(mSubtitleUpdateListener); | |
230 | + mMediaPlayer.setDataSource(mContext, mUri); | |
231 | + mMediaPlayer.setDisplay(mSurfaceHolder); | |
232 | + mMediaPlayer.setScreenOnWhilePlaying(true); | |
233 | + mMediaPlayer.prepareAsync(); | |
234 | + mCurrentState = STATE_PREPARING; | |
235 | + attachMediaController(); | |
236 | + } catch (IOException ex) { | |
237 | + Log.e("Unable to open content: " + mUri, ex); | |
238 | + mCurrentState = STATE_ERROR; | |
239 | + mTargetState = STATE_ERROR; | |
240 | + mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); | |
241 | + return; | |
242 | + } catch (IllegalArgumentException ex) { | |
243 | + Log.e("Unable to open content: " + mUri, ex); | |
244 | + mCurrentState = STATE_ERROR; | |
245 | + mTargetState = STATE_ERROR; | |
246 | + mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); | |
247 | + return; | |
248 | + } | |
249 | + } | |
250 | + | |
251 | + public void setMediaController(MediaController controller) { | |
252 | + if (mMediaController != null) | |
253 | + mMediaController.hide(); | |
254 | + mMediaController = controller; | |
255 | + attachMediaController(); | |
256 | + } | |
257 | + | |
258 | + private void attachMediaController() { | |
259 | + if (mMediaPlayer != null && mMediaController != null) { | |
260 | + mMediaController.setMediaPlayer(this); | |
261 | + View anchorView = this.getParent() instanceof View ? (View) this.getParent() : this; | |
262 | + mMediaController.setAnchorView(anchorView); | |
263 | + mMediaController.setEnabled(isInPlaybackState()); | |
264 | + | |
265 | + if (mUri != null) { | |
266 | + List<String> paths = mUri.getPathSegments(); | |
267 | + String name = paths == null || paths.isEmpty() ? "null" : paths.get(paths.size() - 1); | |
268 | + mMediaController.setFileName(name); | |
269 | + } | |
270 | + } | |
271 | + } | |
272 | + | |
273 | + OnVideoSizeChangedListener mSizeChangedListener = new OnVideoSizeChangedListener() { | |
274 | + public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { | |
275 | + Log.d("onVideoSizeChanged: (%dx%d)", width, height); | |
276 | + mVideoWidth = mp.getVideoWidth(); | |
277 | + mVideoHeight = mp.getVideoHeight(); | |
278 | + mVideoAspectRatio = mp.getVideoAspectRatio(); | |
279 | + if (mVideoWidth != 0 && mVideoHeight != 0) | |
280 | + setVideoLayout(mVideoLayout, mAspectRatio); | |
281 | + } | |
282 | + }; | |
283 | + | |
284 | + OnPreparedListener mPreparedListener = new OnPreparedListener() { | |
285 | + public void onPrepared(MediaPlayer mp) { | |
286 | + Log.d("onPrepared"); | |
287 | + mCurrentState = STATE_PREPARED; | |
288 | + mTargetState = STATE_PLAYING; | |
289 | + | |
290 | + if (mOnPreparedListener != null) | |
291 | + mOnPreparedListener.onPrepared(mMediaPlayer); | |
292 | + if (mMediaController != null) | |
293 | + mMediaController.setEnabled(true); | |
294 | + mVideoWidth = mp.getVideoWidth(); | |
295 | + mVideoHeight = mp.getVideoHeight(); | |
296 | + mVideoAspectRatio = mp.getVideoAspectRatio(); | |
297 | + | |
298 | + long seekToPosition = mSeekWhenPrepared; | |
299 | + | |
300 | + if (seekToPosition != 0) | |
301 | + seekTo(seekToPosition); | |
302 | + if (mVideoWidth != 0 && mVideoHeight != 0) { | |
303 | + setVideoLayout(mVideoLayout, mAspectRatio); | |
304 | + if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) { | |
305 | + if (mTargetState == STATE_PLAYING) { | |
306 | + start(); | |
307 | + if (mMediaController != null) | |
308 | + mMediaController.show(); | |
309 | + } else if (!isPlaying() && (seekToPosition != 0 || getCurrentPosition() > 0)) { | |
310 | + if (mMediaController != null) | |
311 | + mMediaController.show(0); | |
312 | + } | |
313 | + } | |
314 | + } else if (mTargetState == STATE_PLAYING) { | |
315 | + start(); | |
316 | + } | |
317 | + } | |
318 | + }; | |
319 | + | |
320 | + private OnCompletionListener mCompletionListener = new OnCompletionListener() { | |
321 | + public void onCompletion(MediaPlayer mp) { | |
322 | + Log.d("onCompletion"); | |
323 | + mCurrentState = STATE_PLAYBACK_COMPLETED; | |
324 | + mTargetState = STATE_PLAYBACK_COMPLETED; | |
325 | + if (mMediaController != null) | |
326 | + mMediaController.hide(); | |
327 | + if (mOnCompletionListener != null) | |
328 | + mOnCompletionListener.onCompletion(mMediaPlayer); | |
329 | + } | |
330 | + }; | |
331 | + | |
332 | + private OnErrorListener mErrorListener = new OnErrorListener() { | |
333 | + public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { | |
334 | + Log.d("Error: %d, %d", framework_err, impl_err); | |
335 | + mCurrentState = STATE_ERROR; | |
336 | + mTargetState = STATE_ERROR; | |
337 | + if (mMediaController != null) | |
338 | + mMediaController.hide(); | |
339 | + | |
340 | + if (mOnErrorListener != null) { | |
341 | + if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) | |
342 | + return true; | |
343 | + } | |
344 | + | |
345 | + if (getWindowToken() != null) { | |
346 | + int message = framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK ? R.string.vitamio_videoview_error_text_invalid_progressive_playback : R.string.vitamio_videoview_error_text_unknown; | |
347 | + | |
348 | + new AlertDialog.Builder(mContext).setTitle(R.string.vitamio_videoview_error_title).setMessage(message).setPositiveButton(R.string.vitamio_videoview_error_button, new DialogInterface.OnClickListener() { | |
349 | + public void onClick(DialogInterface dialog, int whichButton) { | |
350 | + if (mOnCompletionListener != null) | |
351 | + mOnCompletionListener.onCompletion(mMediaPlayer); | |
352 | + } | |
353 | + }).setCancelable(false).show(); | |
354 | + } | |
355 | + return true; | |
356 | + } | |
357 | + }; | |
358 | + | |
359 | + private OnBufferingUpdateListener mBufferingUpdateListener = new OnBufferingUpdateListener() { | |
360 | + public void onBufferingUpdate(MediaPlayer mp, int percent) { | |
361 | + mCurrentBufferPercentage = percent; | |
362 | + if (mOnBufferingUpdateListener != null) | |
363 | + mOnBufferingUpdateListener.onBufferingUpdate(mp, percent); | |
364 | + } | |
365 | + }; | |
366 | + | |
367 | + private OnInfoListener mInfoListener = new OnInfoListener() { | |
368 | + @Override | |
369 | + public boolean onInfo(MediaPlayer mp, int what, int extra) { | |
370 | + Log.d("onInfo: (%d, %d)", what, extra); | |
371 | + if (mOnInfoListener != null) { | |
372 | + mOnInfoListener.onInfo(mp, what, extra); | |
373 | + } else if (mMediaPlayer != null) { | |
374 | + if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) | |
375 | + mMediaPlayer.pause(); | |
376 | + else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) | |
377 | + mMediaPlayer.start(); | |
378 | + } | |
379 | + | |
380 | + return true; | |
381 | + } | |
382 | + }; | |
383 | + | |
384 | + private OnSeekCompleteListener mSeekCompleteListener = new OnSeekCompleteListener() { | |
385 | + @Override | |
386 | + public void onSeekComplete(MediaPlayer mp) { | |
387 | + Log.d("onSeekComplete"); | |
388 | + if (mOnSeekCompleteListener != null) | |
389 | + mOnSeekCompleteListener.onSeekComplete(mp); | |
390 | + } | |
391 | + }; | |
392 | + | |
393 | + private OnSubtitleUpdateListener mSubtitleUpdateListener = new OnSubtitleUpdateListener() { | |
394 | + @Override | |
395 | + public void onSubtitleUpdate(byte[] pixels, int width, int height) { | |
396 | + Log.i("onSubtitleUpdate: bitmap subtitle, %dx%d", width, height); | |
397 | + if (mOnSubtitleUpdateListener != null) | |
398 | + mOnSubtitleUpdateListener.onSubtitleUpdate(pixels, width, height); | |
399 | + } | |
400 | + | |
401 | + @Override | |
402 | + public void onSubtitleUpdate(String text) { | |
403 | + Log.i("onSubtitleUpdate: %s", text); | |
404 | + if (mOnSubtitleUpdateListener != null) | |
405 | + mOnSubtitleUpdateListener.onSubtitleUpdate(text); | |
406 | + } | |
407 | + }; | |
408 | + | |
409 | + public void setOnPreparedListener(OnPreparedListener l) { | |
410 | + mOnPreparedListener = l; | |
411 | + } | |
412 | + | |
413 | + public void setOnCompletionListener(OnCompletionListener l) { | |
414 | + mOnCompletionListener = l; | |
415 | + } | |
416 | + | |
417 | + public void setOnErrorListener(OnErrorListener l) { | |
418 | + mOnErrorListener = l; | |
419 | + } | |
420 | + | |
421 | + public void setOnBufferingUpdateListener(OnBufferingUpdateListener l) { | |
422 | + mOnBufferingUpdateListener = l; | |
423 | + } | |
424 | + | |
425 | + public void setOnSeekCompleteListener(OnSeekCompleteListener l) { | |
426 | + mOnSeekCompleteListener = l; | |
427 | + } | |
428 | + | |
429 | + public void setOnSubtitleUpdateListener(OnSubtitleUpdateListener l) { | |
430 | + mOnSubtitleUpdateListener = l; | |
431 | + } | |
432 | + | |
433 | + public void setOnInfoListener(OnInfoListener l) { | |
434 | + mOnInfoListener = l; | |
435 | + } | |
436 | + | |
437 | + SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() { | |
438 | + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { | |
439 | + mSurfaceWidth = w; | |
440 | + mSurfaceHeight = h; | |
441 | + boolean isValidState = (mTargetState == STATE_PLAYING); | |
442 | + boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h); | |
443 | + if (mMediaPlayer != null && isValidState && hasValidSize) { | |
444 | + if (mSeekWhenPrepared != 0) | |
445 | + seekTo(mSeekWhenPrepared); | |
446 | + start(); | |
447 | + if (mMediaController != null) { | |
448 | + if (mMediaController.isShowing()) | |
449 | + mMediaController.hide(); | |
450 | + mMediaController.show(); | |
451 | + } | |
452 | + } | |
453 | + } | |
454 | + | |
455 | + public void surfaceCreated(SurfaceHolder holder) { | |
456 | + mSurfaceHolder = holder; | |
457 | + if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND && mTargetState == STATE_RESUME) { | |
458 | + mMediaPlayer.setDisplay(mSurfaceHolder); | |
459 | + resume(); | |
460 | + } else { | |
461 | + openVideo(); | |
462 | + } | |
463 | + } | |
464 | + | |
465 | + public void surfaceDestroyed(SurfaceHolder holder) { | |
466 | + mSurfaceHolder = null; | |
467 | + if (mMediaController != null) | |
468 | + mMediaController.hide(); | |
469 | + if (mCurrentState != STATE_SUSPEND) | |
470 | + release(true); | |
471 | + } | |
472 | + }; | |
473 | + | |
474 | + private void release(boolean cleartargetstate) { | |
475 | + if (mMediaPlayer != null) { | |
476 | + mMediaPlayer.reset(); | |
477 | + mMediaPlayer.release(); | |
478 | + mMediaPlayer = null; | |
479 | + mCurrentState = STATE_IDLE; | |
480 | + if (cleartargetstate) | |
481 | + mTargetState = STATE_IDLE; | |
482 | + } | |
483 | + } | |
484 | + | |
485 | + @Override | |
486 | + public boolean onTouchEvent(MotionEvent ev) { | |
487 | + if (isInPlaybackState() && mMediaController != null) | |
488 | + toggleMediaControlsVisiblity(); | |
489 | + return false; | |
490 | + } | |
491 | + | |
492 | + @Override | |
493 | + public boolean onTrackballEvent(MotionEvent ev) { | |
494 | + if (isInPlaybackState() && mMediaController != null) | |
495 | + toggleMediaControlsVisiblity(); | |
496 | + return false; | |
497 | + } | |
498 | + | |
499 | + @Override | |
500 | + public boolean onKeyDown(int keyCode, KeyEvent event) { | |
501 | + boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_MENU && keyCode != KeyEvent.KEYCODE_CALL && keyCode != KeyEvent.KEYCODE_ENDCALL; | |
502 | + if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) { | |
503 | + if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE) { | |
504 | + if (mMediaPlayer.isPlaying()) { | |
505 | + pause(); | |
506 | + mMediaController.show(); | |
507 | + } else { | |
508 | + start(); | |
509 | + mMediaController.hide(); | |
510 | + } | |
511 | + return true; | |
512 | + } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP && mMediaPlayer.isPlaying()) { | |
513 | + pause(); | |
514 | + mMediaController.show(); | |
515 | + } else { | |
516 | + toggleMediaControlsVisiblity(); | |
517 | + } | |
518 | + } | |
519 | + | |
520 | + return super.onKeyDown(keyCode, event); | |
521 | + } | |
522 | + | |
523 | + private void toggleMediaControlsVisiblity() { | |
524 | + if (mMediaController.isShowing()) { | |
525 | + mMediaController.hide(); | |
526 | + } else { | |
527 | + mMediaController.show(); | |
528 | + } | |
529 | + } | |
530 | + | |
531 | + public void start() { | |
532 | + if (isInPlaybackState()) { | |
533 | + mMediaPlayer.start(); | |
534 | + mCurrentState = STATE_PLAYING; | |
535 | + } | |
536 | + mTargetState = STATE_PLAYING; | |
537 | + } | |
538 | + | |
539 | + public void pause() { | |
540 | + if (isInPlaybackState()) { | |
541 | + if (mMediaPlayer.isPlaying()) { | |
542 | + mMediaPlayer.pause(); | |
543 | + mCurrentState = STATE_PAUSED; | |
544 | + } | |
545 | + } | |
546 | + mTargetState = STATE_PAUSED; | |
547 | + } | |
548 | + | |
549 | + public void suspend() { | |
550 | + if (isInPlaybackState()) { | |
551 | + release(false); | |
552 | + mCurrentState = STATE_SUSPEND_UNSUPPORTED; | |
553 | + Log.d("Unable to suspend video. Release MediaPlayer."); | |
554 | + } | |
555 | + } | |
556 | + | |
557 | + public void resume() { | |
558 | + if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND) { | |
559 | + mTargetState = STATE_RESUME; | |
560 | + } else if (mCurrentState == STATE_SUSPEND_UNSUPPORTED) { | |
561 | + openVideo(); | |
562 | + } | |
563 | + } | |
564 | + | |
565 | + public long getDuration() { | |
566 | + if (isInPlaybackState()) { | |
567 | + if (mDuration > 0) | |
568 | + return mDuration; | |
569 | + mDuration = mMediaPlayer.getDuration(); | |
570 | + return mDuration; | |
571 | + } | |
572 | + mDuration = -1; | |
573 | + return mDuration; | |
574 | + } | |
575 | + | |
576 | + public long getCurrentPosition() { | |
577 | + if (isInPlaybackState()) | |
578 | + return mMediaPlayer.getCurrentPosition(); | |
579 | + return 0; | |
580 | + } | |
581 | + | |
582 | + public void seekTo(long msec) { | |
583 | + if (isInPlaybackState()) { | |
584 | + mMediaPlayer.seekTo(msec); | |
585 | + mSeekWhenPrepared = 0; | |
586 | + } else { | |
587 | + mSeekWhenPrepared = msec; | |
588 | + } | |
589 | + } | |
590 | + | |
591 | + public boolean isPlaying() { | |
592 | + return isInPlaybackState() && mMediaPlayer.isPlaying(); | |
593 | + } | |
594 | + | |
595 | + public int getBufferPercentage() { | |
596 | + if (mMediaPlayer != null) | |
597 | + return mCurrentBufferPercentage; | |
598 | + return 0; | |
599 | + } | |
600 | + | |
601 | + public void setVolume(float leftVolume, float rightVolume) { | |
602 | + if (mMediaPlayer != null) | |
603 | + mMediaPlayer.setVolume(leftVolume, rightVolume); | |
604 | + } | |
605 | + | |
606 | + public int getVideoWidth() { | |
607 | + return mVideoWidth; | |
608 | + } | |
609 | + | |
610 | + public int getVideoHeight() { | |
611 | + return mVideoHeight; | |
612 | + } | |
613 | + | |
614 | + public float getVideoAspectRatio() { | |
615 | + return mVideoAspectRatio; | |
616 | + } | |
617 | + | |
618 | + public void setVideoQuality(int quality) { | |
619 | + if (mMediaPlayer != null) | |
620 | + mMediaPlayer.setVideoQuality(quality); | |
621 | + } | |
622 | + | |
623 | + public void setBufferSize(int bufSize) { | |
624 | + if (mMediaPlayer != null) | |
625 | + mMediaPlayer.setBufferSize(bufSize); | |
626 | + } | |
627 | + | |
628 | + public boolean isBuffering() { | |
629 | + if (mMediaPlayer != null) | |
630 | + return mMediaPlayer.isBuffering(); | |
631 | + return false; | |
632 | + } | |
633 | + | |
634 | + public void setMetaEncoding(String encoding) { | |
635 | + if (mMediaPlayer != null) | |
636 | + mMediaPlayer.setMetaEncoding(encoding); | |
637 | + } | |
638 | + | |
639 | + public String getMetaEncoding() { | |
640 | + if (mMediaPlayer != null) | |
641 | + return mMediaPlayer.getMetaEncoding(); | |
642 | + return null; | |
643 | + } | |
644 | + | |
645 | + public HashMap<String, Integer> getAudioTrackMap(String encoding) { | |
646 | + if (mMediaPlayer != null) | |
647 | + return mMediaPlayer.getAudioTrackMap(encoding); | |
648 | + return null; | |
649 | + } | |
650 | + | |
651 | + public int getAudioTrack() { | |
652 | + if (mMediaPlayer != null) | |
653 | + return mMediaPlayer.getAudioTrack(); | |
654 | + return -1; | |
655 | + } | |
656 | + | |
657 | + public void setAudioTrack(int audioIndex) { | |
658 | + if (mMediaPlayer != null) | |
659 | + mMediaPlayer.setAudioTrack(audioIndex); | |
660 | + } | |
661 | + | |
662 | + public void setSubShown(boolean shown) { | |
663 | + if (mMediaPlayer != null) | |
664 | + mMediaPlayer.setSubShown(shown); | |
665 | + } | |
666 | + | |
667 | + public void setSubEncoding(String encoding) { | |
668 | + if (mMediaPlayer != null) | |
669 | + mMediaPlayer.setSubEncoding(encoding); | |
670 | + } | |
671 | + | |
672 | + public int getSubLocation() { | |
673 | + if (mMediaPlayer != null) | |
674 | + return mMediaPlayer.getSubLocation(); | |
675 | + return -1; | |
676 | + } | |
677 | + | |
678 | + public void setSubPath(String subPath) { | |
679 | + if (mMediaPlayer != null) | |
680 | + mMediaPlayer.setSubPath(subPath); | |
681 | + } | |
682 | + | |
683 | + public String getSubPath() { | |
684 | + if (mMediaPlayer != null) | |
685 | + return mMediaPlayer.getSubPath(); | |
686 | + return null; | |
687 | + } | |
688 | + | |
689 | + public void setSubTrack(int trackId) { | |
690 | + if (mMediaPlayer != null) | |
691 | + mMediaPlayer.setSubTrack(trackId); | |
692 | + } | |
693 | + | |
694 | + public int getSubTrack() { | |
695 | + if (mMediaPlayer != null) | |
696 | + return mMediaPlayer.getSubTrack(); | |
697 | + return -1; | |
698 | + } | |
699 | + | |
700 | + public HashMap<String, Integer> getSubTrackMap(String encoding) { | |
701 | + if (mMediaPlayer != null) | |
702 | + return mMediaPlayer.getSubTrackMap(encoding); | |
703 | + return null; | |
704 | + } | |
705 | + | |
706 | + protected boolean isInPlaybackState() { | |
707 | + return (mMediaPlayer != null && mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); | |
708 | + } | |
709 | + | |
710 | + public boolean canPause() { | |
711 | + return mCanPause; | |
712 | + } | |
713 | + | |
714 | + public boolean canSeekBackward() { | |
715 | + return mCanSeekBack; | |
716 | + } | |
717 | + | |
718 | + public boolean canSeekForward() { | |
719 | + return mCanSeekForward; | |
720 | + } | |
721 | +} | ... | ... |
project.properties
res/layout/activity_video.xml
src/com/upc/pbe/upcnews/VideoActivity.java
... | ... | @@ -2,15 +2,15 @@ package com.upc.pbe.upcnews; |
2 | 2 | |
3 | 3 | import java.io.IOException; |
4 | 4 | |
5 | +import io.vov.vitamio.widget.VideoView; | |
5 | 6 | import android.app.Activity; |
6 | -import android.media.MediaPlayer; | |
7 | +import io.vov.vitamio.MediaPlayer; | |
7 | 8 | import android.net.Uri; |
8 | 9 | import android.os.Bundle; |
9 | 10 | import android.util.Log; |
10 | 11 | import android.view.Menu; |
11 | -import android.widget.MediaController; | |
12 | +import io.vov.vitamio.widget.MediaController; | |
12 | 13 | import android.widget.Toast; |
13 | -import android.widget.VideoView; | |
14 | 14 | |
15 | 15 | //Tercera activitat principal, executa la reproduccio del video sencer |
16 | 16 | public class VideoActivity extends Activity { | ... | ... |