Commit 46f3a709817f5e22fe9b10708ce2dbdffb881b11

Authored by Imanol-Mikel Barba Sabariego
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
  1 +Vitamio
  2 +=======
  3 +
  4 +Vitamio for Android
0 5 \ No newline at end of file
... ...
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
  1 +# cache for current jar dependecy. DO NOT EDIT.
  2 +# format is <lastModified> <length> <SHA-1> <path>
  3 +# Encoding is UTF-8
... ...
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
  1 +/** Automatically generated file. DO NOT MODIFY */
  2 +package io.vov.vitamio;
  3 +
  4 +public final class BuildConfig {
  5 + public final static boolean DEBUG = true;
  6 +}
0 7 \ No newline at end of file
... ...
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
... ... @@ -12,3 +12,4 @@
12 12  
13 13 # Project target.
14 14 target=android-10
  15 +android.library.reference.1=VitamioBundle
... ...
res/layout/activity_video.xml
... ... @@ -3,7 +3,7 @@
3 3 android:layout_width="match_parent"
4 4 android:layout_height="match_parent" >
5 5  
6   - <VideoView
  6 + <io.vov.vitamio.widget.VideoView
7 7 android:id="@+id/videoView1"
8 8 android:layout_width="wrap_content"
9 9 android:layout_height="wrap_content"
... ...
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 {
... ...