Skip to content

Commit

Permalink
[pre-release: v05.00.00-beta01] migrate ExoPlayer to AndroidX Media3
Browse files Browse the repository at this point in the history
  • Loading branch information
warren-bank committed Dec 14, 2022
1 parent ec3bdb3 commit 63586a8
Show file tree
Hide file tree
Showing 18 changed files with 120 additions and 313 deletions.
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename)
### [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3)

Android app to extract video (file/stream) URLs from websites and watch them elsewhere (internal/external video player, Google Chromecast, [ExoAirPlayer](https://github.com/warren-bank/Android-ExoPlayer-AirPlay-Receiver)).

Expand Down Expand Up @@ -106,7 +106,7 @@ Android app to extract video (file/stream) URLs from websites and watch them els
* transfer would not be effected by any of the following events:
- `VideoActivity` stopped
- `BrowserActivity` stopped
- [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename) app exited
- [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3) app exited
- Android device powered off
- list of video URLs
* click a list item to:
Expand Down Expand Up @@ -159,20 +159,20 @@ Android app to extract video (file/stream) URLs from websites and watch them els

#### Important Caveats

* some video URLs may play in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename) and [ExoAirPlayer](https://github.com/warren-bank/Android-ExoPlayer-AirPlay-Receiver), but cannot play on Chromecast or other external video players
* some video URLs may play in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3) and [ExoAirPlayer](https://github.com/warren-bank/Android-ExoPlayer-AirPlay-Receiver), but cannot play on Chromecast or other external video players
- this can occur when a video URL is hosted by a server that uses the `Referer` HTTP request header to restrict access, which is a common strategy
* [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename) and [ExoAirPlayer](https://github.com/warren-bank/Android-ExoPlayer-AirPlay-Receiver) have the functionality to configure the value of this header for each unique video URL
* [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3) and [ExoAirPlayer](https://github.com/warren-bank/Android-ExoPlayer-AirPlay-Receiver) have the functionality to configure the value of this header for each unique video URL
* Chromecast receiver apps cannot change the value of this header because they are restrained by standard browser security policies
- the specs for [XHR](https://xhr.spec.whatwg.org/#dom-xmlhttprequest-setrequestheader) and [fetch](https://fetch.spec.whatwg.org/#forbidden-header-name) forbid changing certain HTTP request headers, including `Referer`
- the [WebCast Chromecast receiver app](https://github.com/warren-bank/Android-WebCast/tree/05-chromecast-receiver-app)
* [attempts](https://github.com/warren-bank/Android-WebCast/blob/05-chromecast-receiver-app/CastReceiver/js/receiver.js#L42) to change the value of this header
* [reveals](https://github.com/warren-bank/Android-WebCast/blob/05-chromecast-receiver-app/notes.txt#L122) in the remote debugger console that this attempt raises the warning:
- the [WebCast Chromecast receiver app](https://github.com/warren-bank/Android-WebCast/tree/00-chromecast-receiver-app)
* [attempts](https://github.com/warren-bank/Android-WebCast/blob/00-chromecast-receiver-app/CastReceiver/js/receiver.js#L42) to change the value of this header
* [reveals](https://github.com/warren-bank/Android-WebCast/blob/00-chromecast-receiver-app/notes.txt#L122) in the remote debugger console that this attempt raises the warning:
- _Refused to set unsafe header "referer"_
* other external video players would need to:
- read the `referUrl` extra in the starting Intent
- configure its HTTP client library to change the value of this header
* [HLS-Proxy](https://github.com/warren-bank/HLS-Proxy) provides a convenient general-purpose workaround
- setup for integration with [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename):
- setup for integration with [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3):
1. install [HLS-Proxy](https://github.com/warren-bank/HLS-Proxy)
* `npm install --global "@warren-bank/hls-proxy"`
2. install [WebMonkey](https://github.com/warren-bank/Android-WebMonkey)
Expand All @@ -189,12 +189,12 @@ Android app to extract video (file/stream) URLs from websites and watch them els
- proxied HLS manifest URL
* type
- "application/x-mpegurl"
4. in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename)
4. in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3)
* _Settings_ > _Video Player_ > _HLS-Proxy configuration_
- usage:
1. run [HLS-Proxy](https://github.com/warren-bank/HLS-Proxy)
* `hlsd --port 8080 --req-insecure --useragent "Chrome/90"`
2. in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename)
2. in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3)
* navigate internal `WebView` to a page having the desired HLS video stream
* open the __Videos__ drawer (on right)
* click on the URL for the desired HLS video stream
Expand All @@ -209,9 +209,9 @@ Android app to extract video (file/stream) URLs from websites and watch them els
- https
* click: _Start App_
- an Activity chooser will start
- [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename) will be included in the list of apps that contain a matching Activity
- [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3) will be included in the list of apps that contain a matching Activity
- click: _WebCast Video Player_
4. in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename)
4. in [WebCast](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3)
* click the ![Chromecast sender icon](https://github.com/warren-bank/crx-webcast-reloaded/raw/gh-pages/chrome_extension/2-release/popup/img/chromecast.png) _Chromecast sender_ icon to cast the proxied HLS video stream to a Chromecast device

* the Android System [`WebView`](https://developer.chrome.com/multidevice/webview/overview) component is wholly responsible for the web browser experience
Expand Down Expand Up @@ -241,15 +241,19 @@ Android app to extract video (file/stream) URLs from websites and watch them els
- [03-webcast-okhttp](https://github.com/warren-bank/Android-WebCast/tree/03-webcast-okhttp)
* used an external HTTP client library: [okhttp](https://github.com/square/okhttp)
* used the `Content-Type` response header to detect video files
* __active branches__
- [04-webcast-filename](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename)
* uses `WebView` to download all HTTP requests
* uses regular expressions to detect file extensions associated with video formats in URL requests
- [05-chromecast-receiver-app](https://github.com/warren-bank/Android-WebCast/tree/05-chromecast-receiver-app)
* __active branches__
- [05-webcast-filename-media3](https://github.com/warren-bank/Android-WebCast/tree/05-webcast-filename-media3)
* uses `WebView` to download all HTTP requests
* uses regular expressions to detect file extensions associated with video formats in URL requests
* builds upon the [04-webcast-filename](https://github.com/warren-bank/Android-WebCast/tree/04-webcast-filename) branch, and migrates from [ExoPlayer](https://github.com/google/ExoPlayer) to [AndroidX Media3](https://github.com/androidx/media)
- [00-chromecast-receiver-app](https://github.com/warren-bank/Android-WebCast/tree/00-chromecast-receiver-app)
* WebCast Chromecast receiver app
- [gh-pages](https://github.com/warren-bank/Android-WebCast/tree/gh-pages)
* WebCast Chromecast receiver app
- the _HEAD_ of this branch should always reference/alias the _HEAD_ of the [05-chromecast-receiver-app](https://github.com/warren-bank/Android-WebCast/tree/05-chromecast-receiver-app) branch
- the _HEAD_ of this branch should always reference/alias the _HEAD_ of the [00-chromecast-receiver-app](https://github.com/warren-bank/Android-WebCast/tree/00-chromecast-receiver-app) branch
* [hosted](https://warren-bank.github.io/Android-WebCast/CastReceiver/receiver.html) by [GitHub Pages](https://pages.github.com/)

#### Highlights of Source Code
Expand Down
31 changes: 18 additions & 13 deletions android-studio-project/WebCast/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,26 @@ android {
}

dependencies {
implementation 'androidx.legacy:legacy-support-v4:' + project.ext.libVersionAndroidxLegacySupportV4 // ( 3 KB) https://mvnrepository.com/artifact/androidx.legacy/legacy-support-v4?repo=google
implementation 'androidx.appcompat:appcompat:' + project.ext.libVersionAndroidxAppCompat // (1.0 MB) https://mvnrepository.com/artifact/androidx.appcompat/appcompat?repo=google
implementation 'androidx.constraintlayout:constraintlayout:' + project.ext.libVersionAndroidxConstraintLayout // ( 63 KB) https://mvnrepository.com/artifact/com.android.support.constraint/constraint-layout?repo=google
implementation 'androidx.core:core:' + project.ext.libVersionAndroidxCore // (618 KB) https://mvnrepository.com/artifact/androidx.core/core?repo=google
implementation 'androidx.recyclerview:recyclerview:' + project.ext.libVersionAndroidxRecyclerView // (344 KB) https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview?repo=google
implementation 'com.google.android.material:material:' + project.ext.libVersionAndroidxMaterial // (566 KB) https://mvnrepository.com/artifact/com.google.android.material/material?repo=google
implementation 'androidx.legacy:legacy-support-v4:' + project.ext.libVersionAndroidxLegacySupportV4 // ( 3 KB) https://mvnrepository.com/artifact/androidx.legacy/legacy-support-v4?repo=google
implementation 'androidx.appcompat:appcompat:' + project.ext.libVersionAndroidxAppCompat // (1.0 MB) https://mvnrepository.com/artifact/androidx.appcompat/appcompat?repo=google
implementation 'androidx.constraintlayout:constraintlayout:' + project.ext.libVersionAndroidxConstraintLayout // ( 63 KB) https://mvnrepository.com/artifact/com.android.support.constraint/constraint-layout?repo=google
implementation 'androidx.core:core:' + project.ext.libVersionAndroidxCore // (618 KB) https://mvnrepository.com/artifact/androidx.core/core?repo=google
implementation 'androidx.recyclerview:recyclerview:' + project.ext.libVersionAndroidxRecyclerView // (344 KB) https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview?repo=google
implementation 'com.google.android.material:material:' + project.ext.libVersionAndroidxMaterial // (566 KB) https://mvnrepository.com/artifact/com.google.android.material/material?repo=google

implementation 'com.google.android.exoplayer:exoplayer-core:' + project.ext.libVersionExoPlayer // (1.6 MB) https://mvnrepository.com/artifact/com.google.android.exoplayer/exoplayer-core?repo=google
implementation 'com.google.android.exoplayer:exoplayer-dash:' + project.ext.libVersionExoPlayer // (111 KB) https://mvnrepository.com/artifact/com.google.android.exoplayer/exoplayer-dash?repo=google
implementation 'com.google.android.exoplayer:exoplayer-hls:' + project.ext.libVersionExoPlayer // (117 KB) https://mvnrepository.com/artifact/com.google.android.exoplayer/exoplayer-hls?repo=google
implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:' + project.ext.libVersionExoPlayer // ( 43 KB) https://mvnrepository.com/artifact/com.google.android.exoplayer/exoplayer-smoothstreaming?repo=google
implementation 'com.google.android.exoplayer:exoplayer-ui:' + project.ext.libVersionExoPlayer // (267 KB) https://mvnrepository.com/artifact/com.google.android.exoplayer/exoplayer-ui?repo=google
implementation 'com.google.android.exoplayer:extension-cast:' + project.ext.libVersionExoPlayer // ( 55 KB) https://mvnrepository.com/artifact/com.google.android.exoplayer/extension-cast?repo=google
implementation 'androidx.media3:media3-cast:' + project.ext.libVersionAndroidxMedia3 // ( 52 KB) https://mvnrepository.com/artifact/androidx.media3/media3-cast?repo=google
implementation 'androidx.media3:media3-common:' + project.ext.libVersionAndroidxMedia3 // (360 KB) https://mvnrepository.com/artifact/androidx.media3/media3-common?repo=google
implementation 'androidx.media3:media3-datasource:' + project.ext.libVersionAndroidxMedia3 // (136 KB) https://mvnrepository.com/artifact/androidx.media3/media3-datasource?repo=google
// implementation 'androidx.media3:media3-decoder:' + project.ext.libVersionAndroidxMedia3 // ( 16 KB) https://mvnrepository.com/artifact/androidx.media3/media3-decoder?repo=google
implementation 'androidx.media3:media3-exoplayer:' + project.ext.libVersionAndroidxMedia3 // (1.1 MB) https://mvnrepository.com/artifact/androidx.media3/media3-exoplayer?repo=google
implementation 'androidx.media3:media3-exoplayer-dash:' + project.ext.libVersionAndroidxMedia3 // (127 KB) https://mvnrepository.com/artifact/androidx.media3/media3-exoplayer-dash?repo=google
implementation 'androidx.media3:media3-exoplayer-hls:' + project.ext.libVersionAndroidxMedia3 // (155 KB) https://mvnrepository.com/artifact/androidx.media3/media3-exoplayer-hls?repo=google
implementation 'androidx.media3:media3-exoplayer-smoothstreaming:' + project.ext.libVersionAndroidxMedia3 // ( 45 KB) https://mvnrepository.com/artifact/androidx.media3/media3-exoplayer-smoothstreaming?repo=google
// implementation 'androidx.media3:media3-extractor:' + project.ext.libVersionAndroidxMedia3 // (694 KB) https://mvnrepository.com/artifact/androidx.media3/media3-extractor?repo=google
// implementation 'androidx.media3:media3-session:' + project.ext.libVersionAndroidxMedia3 // (442 KB) https://mvnrepository.com/artifact/androidx.media3/media3-session?repo=google
implementation 'androidx.media3:media3-ui:' + project.ext.libVersionAndroidxMedia3 // (422 KB) https://mvnrepository.com/artifact/androidx.media3/media3-ui?repo=google

implementation 'com.google.code.gson:gson:' + project.ext.libVersionGson // (235 KB) https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation 'com.google.code.gson:gson:' + project.ext.libVersionGson // (235 KB) https://mvnrepository.com/artifact/com.google.code.gson/gson
}

apply plugin: 'com.google.android.gms.strict-version-matcher-plugin'
4 changes: 2 additions & 2 deletions android-studio-project/WebCast/proguard-rules.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-keep class com.github.warren_bank.webcast.** { *; }

-keep class com.google.android.exoplayer2.** { *; }
-keep class androidx.media3.exoplayer.** { *; }
-keep class com.google.android.gms.** { *; }
-keep class androidx.mediarouter.app.MediaRouteActionProvider { *; }

-dontwarn com.google.android.exoplayer2.**
-dontwarn androidx.media3.exoplayer.**
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;

final class FullScreenManager {
import androidx.media3.ui.PlayerView;

final class FullScreenManager implements PlayerView.FullscreenButtonClickListener {

private boolean isEnabled;
private boolean isFullScreen;
private VideoActivity videoActivity;
private PlayerView localPlayerView;
private Dialog mFullScreenDialog;
private ImageView mFullScreenIcon;
private ViewGroup mFullScreenButton;

// static factory

Expand Down Expand Up @@ -64,8 +62,6 @@ public void release() {
videoActivity = null;
localPlayerView = null;
mFullScreenDialog = null;
mFullScreenIcon = null;
mFullScreenButton = null;
}

// Internal methods.
Expand All @@ -83,7 +79,6 @@ public void onBackPressed() {
private void openFullscreenDialog() {
((ViewGroup) localPlayerView.getParent()).removeView(localPlayerView); // FrameLayout
mFullScreenDialog.addContentView(localPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(videoActivity, R.drawable.ic_fullscreen_close));
isFullScreen = true;
mFullScreenDialog.show();
}
Expand All @@ -93,25 +88,20 @@ private void closeFullscreenDialog() {
((ViewGroup) videoActivity.findViewById(R.id.main_media_frame)).addView(localPlayerView); // FrameLayout
isFullScreen = false;
mFullScreenDialog.dismiss();
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(videoActivity, R.drawable.ic_fullscreen_open));
}

private void initFullscreenButton() {
PlayerControlView controlView;
controlView = (PlayerControlView) localPlayerView.findViewById(R.id.exo_controller);
mFullScreenIcon = (ImageView) controlView.findViewById(R.id.exo_fullscreen_icon);
mFullScreenButton = (ViewGroup) controlView.findViewById(R.id.exo_fullscreen_button); // FrameLayout
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isEnabled)
return;
if (!isFullScreen)
openFullscreenDialog();
else
closeFullscreenDialog();
}
});
localPlayerView.setFullscreenButtonClickListener(this);
}

// PlayerView.FullscreenButtonClickListener implementation.

@Override
public void onFullscreenButtonClick​(boolean isFullScreen) {
if (isFullScreen)
openFullscreenDialog();
else
closeFullscreenDialog();
}

}
Loading

0 comments on commit 63586a8

Please sign in to comment.