├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── malmstein │ │ └── fenster │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── malmstein │ │ └── fenster │ │ └── demo │ │ ├── GestureMediaPlayerActivity.java │ │ ├── MediaPlayerDemoActivity.java │ │ ├── ScaleMediaPlayerActivity.java │ │ └── SimpleMediaPlayerActivity.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_demo.xml │ ├── activity_gesture_media_player.xml │ ├── activity_scale_media_player.xml │ └── activity_simple_media_player.xml │ ├── menu │ └── demo_menu.xml │ ├── raw │ └── big_buck_bunny.mp4 │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── art ├── basic_gesture.gif ├── basic_multitouch.gif ├── custom_controls.png ├── fenster_gesture.gif ├── multitouch.gif └── video_example.gif ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── publish.gradle └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── malmstein │ │ └── fenster │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── malmstein │ │ └── fenster │ │ ├── controller │ │ ├── FensterPlayerController.java │ │ ├── FensterPlayerControllerVisibilityListener.java │ │ ├── MediaFensterPlayerController.java │ │ └── SimpleMediaFensterPlayerController.java │ │ ├── gestures │ │ ├── FensterEventsListener.java │ │ ├── FensterGestureControllerView.java │ │ └── FensterGestureListener.java │ │ ├── helper │ │ └── BrightnessHelper.java │ │ ├── play │ │ ├── FensterPlayer.java │ │ ├── FensterVideoFragment.java │ │ └── FensterVideoStateListener.java │ │ ├── seekbar │ │ ├── BrightnessSeekBar.java │ │ └── VolumeSeekBar.java │ │ └── view │ │ ├── FensterLoadingView.java │ │ ├── FensterTouchRoot.java │ │ ├── FensterVideoView.java │ │ └── VideoSizeCalculator.java │ └── res │ ├── drawable-xhdpi │ ├── fen__ic_action_bulb.png │ └── fen__ic_action_music_2.png │ ├── drawable-xxhdpi │ ├── fen__ic_action_bulb.png │ └── fen__ic_action_music_2.png │ ├── layout │ ├── fen__fragment_fenster_gesture.xml │ ├── fen__fragment_fenster_video.xml │ ├── fen__view_loading.xml │ ├── fen__view_media_controller.xml │ └── fen__view_simple_media_controller.xml │ └── values │ ├── attrs.xml │ ├── fen__colors.xml │ ├── fen__dimens.xml │ ├── fen__strings.xml │ ├── fen__styles.xml │ └── public.xml ├── settings.gradle └── team-props ├── bintray.gradle └── deploy.gradle /.gitignore: -------------------------------------------------------------------------------- 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 | out/ 15 | build.log 16 | build-log.xml 17 | 18 | # Local configuration file (sdk path, etc) 19 | local.properties 20 | 21 | .project 22 | .classpath 23 | .settings 24 | target/ 25 | build/ 26 | classes/ 27 | gen-external-apklibs/ 28 | tmp/ 29 | 30 | # IDEA Ignores 31 | *.iml 32 | *.ipr 33 | *.iws 34 | .idea/ 35 | .gradle/ 36 | 37 | # Android 38 | local.properties 39 | 40 | # MAC 41 | *.DS_Store 42 | 43 | # api scripts 44 | session.key 45 | access.token 46 | response.txt 47 | .pt 48 | *.orig 49 | terminator/ 50 | 51 | ======= 52 | 53 | app/build 54 | app-test/build 55 | lint-results.xml 56 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | android: 4 | components: 5 | - build-tools-23.0.1 6 | - android-23 7 | - extra-android-support 8 | - extra-google-m2repository 9 | - extra-android-m2repository 10 | 11 | script: 12 | - ./gradlew clean build 13 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 David Gonzalez 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | 16 | Apache License 17 | Version 2.0, January 2004 18 | http://www.apache.org/licenses/ 19 | 20 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 21 | 22 | 1. Definitions. 23 | 24 | "License" shall mean the terms and conditions for use, reproduction, 25 | and distribution as defined by Sections 1 through 9 of this document. 26 | 27 | "Licensor" shall mean the copyright owner or entity authorized by 28 | the copyright owner that is granting the License. 29 | 30 | "Legal Entity" shall mean the union of the acting entity and all 31 | other entities that control, are controlled by, or are under common 32 | control with that entity. For the purposes of this definition, 33 | "control" means (i) the power, direct or indirect, to cause the 34 | direction or management of such entity, whether by contract or 35 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 36 | outstanding shares, or (iii) beneficial ownership of such entity. 37 | 38 | "You" (or "Your") shall mean an individual or Legal Entity 39 | exercising permissions granted by this License. 40 | 41 | "Source" form shall mean the preferred form for making modifications, 42 | including but not limited to software source code, documentation 43 | source, and configuration files. 44 | 45 | "Object" form shall mean any form resulting from mechanical 46 | transformation or translation of a Source form, including but 47 | not limited to compiled object code, generated documentation, 48 | and conversions to other media types. 49 | 50 | "Work" shall mean the work of authorship, whether in Source or 51 | Object form, made available under the License, as indicated by a 52 | copyright notice that is included in or attached to the work 53 | (an example is provided in the Appendix below). 54 | 55 | "Derivative Works" shall mean any work, whether in Source or Object 56 | form, that is based on (or derived from) the Work and for which the 57 | editorial revisions, annotations, elaborations, or other modifications 58 | represent, as a whole, an original work of authorship. For the purposes 59 | of this License, Derivative Works shall not include works that remain 60 | separable from, or merely link (or bind by name) to the interfaces of, 61 | the Work and Derivative Works thereof. 62 | 63 | "Contribution" shall mean any work of authorship, including 64 | the original version of the Work and any modifications or additions 65 | to that Work or Derivative Works thereof, that is intentionally 66 | submitted to Licensor for inclusion in the Work by the copyright owner 67 | or by an individual or Legal Entity authorized to submit on behalf of 68 | the copyright owner. For the purposes of this definition, "submitted" 69 | means any form of electronic, verbal, or written communication sent 70 | to the Licensor or its representatives, including but not limited to 71 | communication on electronic mailing lists, source code control systems, 72 | and issue tracking systems that are managed by, or on behalf of, the 73 | Licensor for the purpose of discussing and improving the Work, but 74 | excluding communication that is conspicuously marked or otherwise 75 | designated in writing by the copyright owner as "Not a Contribution." 76 | 77 | "Contributor" shall mean Licensor and any individual or Legal Entity 78 | on behalf of whom a Contribution has been received by Licensor and 79 | subsequently incorporated within the Work. 80 | 81 | 2. Grant of Copyright License. Subject to the terms and conditions of 82 | this License, each Contributor hereby grants to You a perpetual, 83 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 84 | copyright license to reproduce, prepare Derivative Works of, 85 | publicly display, publicly perform, sublicense, and distribute the 86 | Work and such Derivative Works in Source or Object form. 87 | 88 | 3. Grant of Patent License. Subject to the terms and conditions of 89 | this License, each Contributor hereby grants to You a perpetual, 90 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 91 | (except as stated in this section) patent license to make, have made, 92 | use, offer to sell, sell, import, and otherwise transfer the Work, 93 | where such license applies only to those patent claims licensable 94 | by such Contributor that are necessarily infringed by their 95 | Contribution(s) alone or by combination of their Contribution(s) 96 | with the Work to which such Contribution(s) was submitted. If You 97 | institute patent litigation against any entity (including a 98 | cross-claim or counterclaim in a lawsuit) alleging that the Work 99 | or a Contribution incorporated within the Work constitutes direct 100 | or contributory patent infringement, then any patent licenses 101 | granted to You under this License for that Work shall terminate 102 | as of the date such litigation is filed. 103 | 104 | 4. Redistribution. You may reproduce and distribute copies of the 105 | Work or Derivative Works thereof in any medium, with or without 106 | modifications, and in Source or Object form, provided that You 107 | meet the following conditions: 108 | 109 | (a) You must give any other recipients of the Work or 110 | Derivative Works a copy of this License; and 111 | 112 | (b) You must cause any modified files to carry prominent notices 113 | stating that You changed the files; and 114 | 115 | (c) You must retain, in the Source form of any Derivative Works 116 | that You distribute, all copyright, patent, trademark, and 117 | attribution notices from the Source form of the Work, 118 | excluding those notices that do not pertain to any part of 119 | the Derivative Works; and 120 | 121 | (d) If the Work includes a "NOTICE" text file as part of its 122 | distribution, then any Derivative Works that You distribute must 123 | include a readable copy of the attribution notices contained 124 | within such NOTICE file, excluding those notices that do not 125 | pertain to any part of the Derivative Works, in at least one 126 | of the following places: within a NOTICE text file distributed 127 | as part of the Derivative Works; within the Source form or 128 | documentation, if provided along with the Derivative Works; or, 129 | within a display generated by the Derivative Works, if and 130 | wherever such third-party notices normally appear. The contents 131 | of the NOTICE file are for informational purposes only and 132 | do not modify the License. You may add Your own attribution 133 | notices within Derivative Works that You distribute, alongside 134 | or as an addendum to the NOTICE text from the Work, provided 135 | that such additional attribution notices cannot be construed 136 | as modifying the License. 137 | 138 | You may add Your own copyright statement to Your modifications and 139 | may provide additional or different license terms and conditions 140 | for use, reproduction, or distribution of Your modifications, or 141 | for any such Derivative Works as a whole, provided Your use, 142 | reproduction, and distribution of the Work otherwise complies with 143 | the conditions stated in this License. 144 | 145 | 5. Submission of Contributions. Unless You explicitly state otherwise, 146 | any Contribution intentionally submitted for inclusion in the Work 147 | by You to the Licensor shall be under the terms and conditions of 148 | this License, without any additional terms or conditions. 149 | Notwithstanding the above, nothing herein shall supersede or modify 150 | the terms of any separate license agreement you may have executed 151 | with Licensor regarding such Contributions. 152 | 153 | 6. Trademarks. This License does not grant permission to use the trade 154 | names, trademarks, service marks, or product names of the Licensor, 155 | except as required for reasonable and customary use in describing the 156 | origin of the Work and reproducing the content of the NOTICE file. 157 | 158 | 7. Disclaimer of Warranty. Unless required by applicable law or 159 | agreed to in writing, Licensor provides the Work (and each 160 | Contributor provides its Contributions) on an "AS IS" BASIS, 161 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 162 | implied, including, without limitation, any warranties or conditions 163 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 164 | PARTICULAR PURPOSE. You are solely responsible for determining the 165 | appropriateness of using or redistributing the Work and assume any 166 | risks associated with Your exercise of permissions under this License. 167 | 168 | 8. Limitation of Liability. In no event and under no legal theory, 169 | whether in tort (including negligence), contract, or otherwise, 170 | unless required by applicable law (such as deliberate and grossly 171 | negligent acts) or agreed to in writing, shall any Contributor be 172 | liable to You for damages, including any direct, indirect, special, 173 | incidental, or consequential damages of any character arising as a 174 | result of this License or out of the use or inability to use the 175 | Work (including but not limited to damages for loss of goodwill, 176 | work stoppage, computer failure or malfunction, or any and all 177 | other commercial damages or losses), even if such Contributor 178 | has been advised of the possibility of such damages. 179 | 180 | 9. Accepting Warranty or Additional Liability. While redistributing 181 | the Work or Derivative Works thereof, You may choose to offer, 182 | and charge a fee for, acceptance of support, warranty, indemnity, 183 | or other liability obligations and/or rights consistent with this 184 | License. However, in accepting such obligations, You may act only 185 | on Your own behalf and on Your sole responsibility, not on behalf 186 | of any other Contributor, and only if You agree to indemnify, 187 | defend, and hold each Contributor harmless for any liability 188 | incurred by, or claims asserted against, such Contributor by reason 189 | of your accepting any such warranty or additional liability. 190 | 191 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fenster 2 | ============================= 3 | 4 | A library to display videos in a `TextureView` using a custom `MediaPlayer` controller as described in this blog post http://www.malmstein.com/blog/2014/08/09/how-to-use-a-textureview-to-display-a-video-with-custom-media-player-controls/ 5 | 6 | ![Demo gif](https://raw.githubusercontent.com/malmstein/Fenster/master/art/video_example.gif) 7 | 8 | Install 9 | ============================= 10 | 11 | [ ![Download](https://api.bintray.com/packages/malmstein/maven/fenster/images/download.svg) ](https://bintray.com/malmstein/maven/fenster/_latestVersion) 12 | 13 | To get the current snapshot version: 14 | 15 | ```groovy 16 | buildscript { 17 | repositories { 18 | jcenter() 19 | } 20 | dependencies { 21 | classpath 'com.malmstein:fenster:0.0.2' 22 | } 23 | } 24 | ``` 25 | 26 | ### minSDK 27 | 28 | The minSDK for the use of the library is minSDK 16 29 | 30 | Displaying a video with custom controller 31 | ============================= 32 | 33 | ### Add a TextureVideoView and a PlayerController to your Activity or Fragment 34 | 35 | ```xml 36 | 42 | 43 | 49 | 50 | 57 | 58 | 59 | ``` 60 | 61 | ### Setting video URL 62 | 63 | In order to display a video, simply set the video URL and call start. **You can also start the video from a desired second too**. 64 | 65 | 66 | ```java 67 | @Override 68 | protected void onPostCreate(Bundle savedInstanceState) { 69 | super.onPostCreate(savedInstanceState); 70 | 71 | textureView = (TextureVideoView) findViewById(R.id.play_video_texture); 72 | playerController = (PlayerController) findViewById(R.id.play_video_controller); 73 | 74 | textureView.setMediaController(playerController); 75 | 76 | textureView.setVideo("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4", 77 | PlayerController.DEFAULT_VIDEO_START); 78 | textureView.start(); 79 | } 80 | ``` 81 | 82 | ### Exposed listeners 83 | 84 | By default there are the exposed listeners. The `NavigationListener` will listen to the to **Previous** and **Next** events triggered 85 | by the controller. The `VisibilityListener` will be triggered when the `PlayerController` visibility changes. 86 | 87 | ```java 88 | playerController.setNavigationListener(this); 89 | playerController.setVisibilityListener(this); 90 | ``` 91 | 92 | Using the Gesture Detection Player Controller 93 | ============================= 94 | 95 | ### Attach a listener to your player controller 96 | 97 | As described in this blog post http://www.malmstein.com/how-to-use-a-textureview-to-display-a-video-with-custom-media-player-controls/ 98 | it's very simple to use. Just add a listener to Player Controller 99 | 100 | ```java 101 | playerController.setFensterEventsListener(this); 102 | ``` 103 | 104 | The Fenster Events Listener allows you to react to the gestures 105 | 106 | ```java 107 | public interface FensterEventsListener { 108 | 109 | void onTap(); 110 | 111 | void onHorizontalScroll(MotionEvent event, float delta); 112 | 113 | void onVerticalScroll(MotionEvent event, float delta); 114 | 115 | void onSwipeRight(); 116 | 117 | void onSwipeLeft(); 118 | 119 | void onSwipeBottom(); 120 | 121 | void onSwipeTop(); 122 | } 123 | ``` 124 | 125 | ### Use MediaPlayerController instead of SimpleMediaPlayerController 126 | 127 | MediaFensterPlayerController also shows volume and brightness controls, if you just want to use a simple media controller 128 | then the recommendation is to use SimpleMediaFensterPlayerController 129 | 130 | ```xml 131 | 137 | 138 | 144 | 145 | 152 | 153 | 154 | ``` 155 | 156 | ### Using the Volume and Brightness Seekbar 157 | 158 | Add them to your layout: 159 | 160 | ```xml 161 | 165 | ``` 166 | 167 | ```xml 168 | 172 | ``` 173 | 174 | Initialise them from your Fragment or Activity: 175 | 176 | ```java 177 | mVolume = (VolumeSeekBar) findViewById(R.id.media_controller_volume); 178 | mVolume.initialise(this); 179 | 180 | mBrightness = (BrightnessSeekBar) findViewById(R.id.media_controller_brightness); 181 | mBrightness.initialise(this); 182 | 183 | ``` 184 | 185 | You'll get a callback when the seekbar is being dragged: 186 | 187 | ```java 188 | @Override 189 | public void onVolumeStartedDragging() { 190 | mDragging = true; 191 | } 192 | 193 | @Override 194 | public void onVolumeFinishedDragging() { 195 | mDragging = false; 196 | } 197 | 198 | @Override 199 | public void onBrigthnessStartedDragging() { 200 | mDragging = true; 201 | } 202 | 203 | @Override 204 | public void onBrightnessFinishedDragging() { 205 | mDragging = false; 206 | } 207 | ``` 208 | 209 | Support for different video origins 210 | ============================= 211 | 212 | The `setVideo()` method allows you to load remote or local video files. You can also set the start time of the video 213 | (useful if you want to resume content), passing in a integer which corresponds to Milliseconds. 214 | 215 | ### Loading a remote stream 216 | 217 | 218 | ```java 219 | @Override 220 | protected void onPostCreate(Bundle savedInstanceState) { 221 | super.onPostCreate(savedInstanceState); 222 | 223 | textureView = (TextureVideoView) findViewById(R.id.play_video_texture); 224 | playerController = (PlayerController) findViewById(R.id.play_video_controller); 225 | 226 | textureView.setMediaController(playerController); 227 | 228 | textureView.setVideo("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"); 229 | textureView.start(); 230 | } 231 | ``` 232 | 233 | ### Loading a local stream 234 | 235 | `Fenster` uses the [AssetFileDescriptor](http://developer.android.com/intl/es/reference/android/content/res/AssetFileDescriptor.html) in 236 | order to load a local video stream. 237 | 238 | 239 | ```java 240 | @Override 241 | protected void onPostCreate(Bundle savedInstanceState) { 242 | super.onPostCreate(savedInstanceState); 243 | 244 | textureView = (TextureVideoView) findViewById(R.id.play_video_texture); 245 | playerController = (PlayerController) findViewById(R.id.play_video_controller); 246 | 247 | textureView.setMediaController(playerController); 248 | 249 | AssetFileDescriptor assetFileDescriptor = getResources().openRawResourceFd(R.raw.big_buck_bunny); 250 | textureView.setVideo(assetFileDescriptor); 251 | 252 | textureView.start(); 253 | } 254 | ``` 255 | 256 | 257 | Support for video scaling modes 258 | ============================= 259 | 260 | Sets video scaling mode. To make the target video scaling mode effective during playback, 261 | the default video scaling mode is VIDEO_SCALING_MODE_SCALE_TO_FIT. Uses [setVideoScalingMode](http://developer.android.com/intl/es/reference/android/media/MediaPlayer.html) 262 | 263 | There are two different video scaling modes: `scaleToFit` and `crop` 264 | 265 | In order to use it, `Fenster` allows you to pass in an argument from the xml layout: 266 | 267 | ```xml 268 | 273 | ``` 274 | 275 | 276 | License 277 | ------- 278 | 279 | (c) Copyright 2016 David Gonzalez 280 | 281 | Licensed under the Apache License, Version 2.0 (the "License"); 282 | you may not use this file except in compliance with the License. 283 | You may obtain a copy of the License at 284 | 285 | http://www.apache.org/licenses/LICENSE-2.0 286 | 287 | Unless required by applicable law or agreed to in writing, software 288 | distributed under the License is distributed on an "AS IS" BASIS, 289 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 290 | See the License for the specific language governing permissions and 291 | limitations under the License. 292 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:1.3.0' 8 | } 9 | } 10 | 11 | repositories { 12 | jcenter() 13 | } 14 | 15 | apply plugin: 'com.android.application' 16 | 17 | dependencies { 18 | compile project(":library") 19 | // compile 'com.malmstein:fenster:0.0.1' 20 | } 21 | 22 | android { 23 | compileSdkVersion 20 24 | buildToolsVersion "20.0.0" 25 | 26 | defaultConfig { 27 | applicationId "com.malmstein.fenster.demo" 28 | minSdkVersion 16 29 | targetSdkVersion 19 30 | versionCode 1 31 | versionName "1.0" 32 | } 33 | buildTypes { 34 | release { 35 | minifyEnabled false 36 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/malmstein/fenster/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.malmstein.fenster; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/malmstein/fenster/demo/GestureMediaPlayerActivity.java: -------------------------------------------------------------------------------- 1 | package com.malmstein.fenster.demo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import com.malmstein.fenster.controller.FensterPlayerControllerVisibilityListener; 8 | import com.malmstein.fenster.play.FensterVideoFragment; 9 | 10 | public class GestureMediaPlayerActivity extends Activity implements FensterPlayerControllerVisibilityListener { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_gesture_media_player); 16 | } 17 | 18 | @Override 19 | protected void onPostCreate(Bundle savedInstanceState) { 20 | super.onPostCreate(savedInstanceState); 21 | initVideo(); 22 | } 23 | 24 | private void initVideo(){ 25 | findVideoFragment().setVisibilityListener(this); 26 | findVideoFragment().playExampleVideo(); 27 | } 28 | 29 | private FensterVideoFragment findVideoFragment(){ 30 | return (FensterVideoFragment) getFragmentManager().findFragmentById(R.id.play_demo_fragment); 31 | } 32 | 33 | @Override 34 | public void onControlsVisibilityChange(boolean value) { 35 | setSystemUiVisibility(value); 36 | } 37 | 38 | private void setSystemUiVisibility(final boolean visible) { 39 | int newVis = View.SYSTEM_UI_FLAG_LAYOUT_STABLE 40 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 41 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 42 | 43 | if (!visible) { 44 | newVis |= View.SYSTEM_UI_FLAG_LOW_PROFILE 45 | | View.SYSTEM_UI_FLAG_FULLSCREEN 46 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 47 | } 48 | 49 | final View decorView = getWindow().getDecorView(); 50 | decorView.setSystemUiVisibility(newVis); 51 | decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { 52 | @Override 53 | public void onSystemUiVisibilityChange(final int visibility) { 54 | if ((visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) { 55 | findVideoFragment().showFensterController(); 56 | } 57 | } 58 | }); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/malmstein/fenster/demo/MediaPlayerDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.malmstein.fenster.demo; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | 10 | public class MediaPlayerDemoActivity extends Activity implements View.OnClickListener { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | 16 | setContentView(R.layout.activity_demo); 17 | bindViews(); 18 | } 19 | 20 | private void bindViews() { 21 | findViewById(R.id.start_gesture_media_player_button).setOnClickListener(this); 22 | findViewById(R.id.start_simple_media_player_button).setOnClickListener(this); 23 | findViewById(R.id.local_file_media_player_button).setOnClickListener(this); 24 | findViewById(R.id.start_scale_media_player_button).setOnClickListener(this); 25 | } 26 | 27 | @Override 28 | public void onClick(View v) { 29 | switch (v.getId()) { 30 | case R.id.start_gesture_media_player_button: 31 | startActivity(new Intent(this, GestureMediaPlayerActivity.class)); 32 | break; 33 | case R.id.start_simple_media_player_button: 34 | startActivity(new Intent(this, SimpleMediaPlayerActivity.class)); 35 | break; 36 | case R.id.local_file_media_player_button: 37 | Intent localStream = new Intent(this, SimpleMediaPlayerActivity.class); 38 | localStream.putExtra(SimpleMediaPlayerActivity.KEY_LOCAL_FILE, true); 39 | startActivity(localStream); 40 | break; 41 | case R.id.start_scale_media_player_button: 42 | startActivity(new Intent(this, ScaleMediaPlayerActivity.class)); 43 | break; 44 | } 45 | } 46 | 47 | @Override 48 | public boolean onCreateOptionsMenu(Menu menu) { 49 | getMenuInflater().inflate(R.menu.demo_menu, menu); 50 | return true; 51 | } 52 | 53 | @Override 54 | public boolean onOptionsItemSelected(MenuItem item) { 55 | int id = item.getItemId(); 56 | if (id == R.id.action_about) { 57 | return true; 58 | } 59 | return super.onOptionsItemSelected(item); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/malmstein/fenster/demo/ScaleMediaPlayerActivity.java: -------------------------------------------------------------------------------- 1 | package com.malmstein.fenster.demo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import com.malmstein.fenster.controller.SimpleMediaFensterPlayerController; 7 | import com.malmstein.fenster.view.FensterVideoView; 8 | 9 | public class ScaleMediaPlayerActivity extends Activity { 10 | 11 | private FensterVideoView textureView; 12 | private SimpleMediaFensterPlayerController fullScreenMediaPlayerController; 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | 18 | setContentView(R.layout.activity_scale_media_player); 19 | 20 | bindViews(); 21 | initVideo(); 22 | } 23 | 24 | @Override 25 | protected void onPostCreate(Bundle savedInstanceState) { 26 | super.onPostCreate(savedInstanceState); 27 | textureView.setVideo("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"); 28 | textureView.start(); 29 | } 30 | 31 | private void bindViews() { 32 | textureView = (FensterVideoView) findViewById(R.id.play_video_texture); 33 | fullScreenMediaPlayerController = (SimpleMediaFensterPlayerController) findViewById(R.id.play_video_controller); 34 | } 35 | 36 | private void initVideo() { 37 | textureView.setMediaController(fullScreenMediaPlayerController); 38 | textureView.setOnPlayStateListener(fullScreenMediaPlayerController); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/malmstein/fenster/demo/SimpleMediaPlayerActivity.java: -------------------------------------------------------------------------------- 1 | package com.malmstein.fenster.demo; 2 | 3 | import android.app.Activity; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.malmstein.fenster.controller.FensterPlayerControllerVisibilityListener; 9 | import com.malmstein.fenster.controller.SimpleMediaFensterPlayerController; 10 | import com.malmstein.fenster.view.FensterVideoView; 11 | 12 | public class SimpleMediaPlayerActivity extends Activity implements FensterPlayerControllerVisibilityListener { 13 | 14 | public static final String KEY_LOCAL_FILE = BuildConfig.APPLICATION_ID + "KEY_LOCAL_FILE"; 15 | private FensterVideoView textureView; 16 | private SimpleMediaFensterPlayerController fullScreenMediaPlayerController; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | 22 | setContentView(R.layout.activity_simple_media_player); 23 | 24 | bindViews(); 25 | initVideo(); 26 | } 27 | 28 | @Override 29 | protected void onPostCreate(Bundle savedInstanceState) { 30 | super.onPostCreate(savedInstanceState); 31 | 32 | if (getIntent().hasExtra(KEY_LOCAL_FILE)) { 33 | AssetFileDescriptor assetFileDescriptor = getResources().openRawResourceFd(R.raw.big_buck_bunny); 34 | textureView.setVideo(assetFileDescriptor); 35 | } else { 36 | textureView.setVideo("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"); 37 | } 38 | 39 | textureView.start(); 40 | } 41 | 42 | private void bindViews() { 43 | textureView = (FensterVideoView) findViewById(R.id.play_video_texture); 44 | fullScreenMediaPlayerController = (SimpleMediaFensterPlayerController) findViewById(R.id.play_video_controller); 45 | } 46 | 47 | private void initVideo() { 48 | fullScreenMediaPlayerController.setVisibilityListener(this); 49 | textureView.setMediaController(fullScreenMediaPlayerController); 50 | textureView.setOnPlayStateListener(fullScreenMediaPlayerController); 51 | } 52 | 53 | private void setSystemUiVisibility(final boolean visible) { 54 | int newVis = View.SYSTEM_UI_FLAG_LAYOUT_STABLE 55 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 56 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 57 | 58 | if (!visible) { 59 | newVis |= View.SYSTEM_UI_FLAG_LOW_PROFILE 60 | | View.SYSTEM_UI_FLAG_FULLSCREEN 61 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 62 | } 63 | 64 | final View decorView = getWindow().getDecorView(); 65 | decorView.setSystemUiVisibility(newVis); 66 | decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { 67 | @Override 68 | public void onSystemUiVisibilityChange(final int visibility) { 69 | if ((visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) { 70 | fullScreenMediaPlayerController.show(); 71 | } 72 | } 73 | }); 74 | } 75 | 76 | @Override 77 | public void onControlsVisibilityChange(final boolean value) { 78 | setSystemUiVisibility(value); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malmstein/fenster/cd3d32a281125037fa78b8ca689593a82c69dff7/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malmstein/fenster/cd3d32a281125037fa78b8ca689593a82c69dff7/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malmstein/fenster/cd3d32a281125037fa78b8ca689593a82c69dff7/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malmstein/fenster/cd3d32a281125037fa78b8ca689593a82c69dff7/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 |