From 9360294d2217e4e06ea566790749db9395c6c05c Mon Sep 17 00:00:00 2001 From: Renato Date: Mon, 2 Mar 2026 18:25:49 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20migrar=20player=20a=20media3=20y=20mejo?= =?UTF-8?q?ras=20de=20resoluci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DisneyPlayer/app/build.gradle | 31 + DisneyPlayer/app/src/main/AndroidManifest.xml | 21 + .../java/com/disneyplayer/MainActivity.java | 186 +++++ .../app/src/main/res/layout/activity_main.xml | 35 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 585 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 585 bytes .../app/src/main/res/values/strings.xml | 4 + .../app/src/main/res/values/themes.xml | 7 + DisneyPlayer/build.gradle | 21 + DisneyPlayer/gradle.properties | 2 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63375 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + DisneyPlayer/settings.gradle | 1 + VLC_MIGRATION_PLAN.md | 639 ++++++++++++++++++ app/build.gradle | 18 +- app/src/main/AndroidManifest.xml | 1 + .../com/streamplayer/EventRepository.java | 7 +- .../java/com/streamplayer/NetworkUtils.java | 107 +-- .../java/com/streamplayer/PlayerActivity.java | 430 +++++++----- .../com/streamplayer/StreamUrlResolver.java | 355 +++++++++- .../java/com/streamplayer/VlcDrmManager.java | 66 ++ .../com/streamplayer/VlcPlayerConfig.java | 29 + app/src/main/res/layout/activity_player.xml | 6 +- build.gradle | 1 + 24 files changed, 1679 insertions(+), 295 deletions(-) create mode 100644 DisneyPlayer/app/build.gradle create mode 100644 DisneyPlayer/app/src/main/AndroidManifest.xml create mode 100644 DisneyPlayer/app/src/main/java/com/disneyplayer/MainActivity.java create mode 100644 DisneyPlayer/app/src/main/res/layout/activity_main.xml create mode 100644 DisneyPlayer/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 DisneyPlayer/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 DisneyPlayer/app/src/main/res/values/strings.xml create mode 100644 DisneyPlayer/app/src/main/res/values/themes.xml create mode 100644 DisneyPlayer/build.gradle create mode 100644 DisneyPlayer/gradle.properties create mode 100644 DisneyPlayer/gradle/wrapper/gradle-wrapper.jar create mode 100644 DisneyPlayer/gradle/wrapper/gradle-wrapper.properties create mode 100644 DisneyPlayer/settings.gradle create mode 100644 VLC_MIGRATION_PLAN.md create mode 100644 app/src/main/java/com/streamplayer/VlcDrmManager.java create mode 100644 app/src/main/java/com/streamplayer/VlcPlayerConfig.java diff --git a/DisneyPlayer/app/build.gradle b/DisneyPlayer/app/build.gradle new file mode 100644 index 0000000..6845bda --- /dev/null +++ b/DisneyPlayer/app/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'com.android.application' + +android { + namespace "com.disneyplayer" + compileSdk 35 + + defaultConfig { + applicationId "com.disneyplayer" + minSdk 21 + targetSdk 35 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'org.videolan.android:libvlc-all:3.6.0-eap9' + implementation 'com.squareup.okhttp3:okhttp:4.12.0' +} diff --git a/DisneyPlayer/app/src/main/AndroidManifest.xml b/DisneyPlayer/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..821a672 --- /dev/null +++ b/DisneyPlayer/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/DisneyPlayer/app/src/main/java/com/disneyplayer/MainActivity.java b/DisneyPlayer/app/src/main/java/com/disneyplayer/MainActivity.java new file mode 100644 index 0000000..be1fa43 --- /dev/null +++ b/DisneyPlayer/app/src/main/java/com/disneyplayer/MainActivity.java @@ -0,0 +1,186 @@ +package com.disneyplayer; + +import android.app.Activity; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.SurfaceView; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.Toast; +import android.widget.TextView; + +import org.videolan.libvlc.LibVLC; +import org.videolan.libvlc.Media; +import org.videolan.libvlc.MediaPlayer; +import org.videolan.libvlc.interfaces.IVLCVout; + +import java.util.ArrayList; + +public class MainActivity extends Activity { + + private SurfaceView surfaceView; + private ProgressBar progressBar; + private Button playButton; + private TextView statusText; + private LibVLC libVlc; + private MediaPlayer mediaPlayer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Create layout programmatically + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + layout.setGravity(android.view.Gravity.CENTER); + + statusText = new TextView(this); + statusText.setText("Disney Player Ready"); + statusText.setTextSize(18); + statusText.setPadding(20, 20, 20, 20); + + playButton = new Button(this); + playButton.setText("▶ Reproducir Disney+"); + playButton.setTextSize(18); + playButton.setPadding(40, 40, 40, 40); + + progressBar = new ProgressBar(this); + progressBar.setVisibility(View.GONE); + + surfaceView = new SurfaceView(this); + surfaceView.setVisibility(View.GONE); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + 0 + ); + params.weight = 1; + surfaceView.setLayoutParams(params); + + layout.addView(statusText); + layout.addView(progressBar); + layout.addView(playButton); + layout.addView(surfaceView); + + setContentView(layout); + + Toast.makeText(this, "App iniciada correctamente", Toast.LENGTH_LONG).show(); + + playButton.setOnClickListener(v -> { + Toast.makeText(this, "Botón presionado", Toast.LENGTH_SHORT).show(); + playButton.setEnabled(false); + progressBar.setVisibility(View.VISIBLE); + statusText.setText("Iniciando reproducción..."); + + new Thread(() -> { + try { + String streamUrl = "https://live-ftc-sa-east-2.media.dssott.com/dvt2=exp=1772064227~url=%2Fgru1%2Fva01%2Fdisneyplus%2Fevent%2F2026%2F02%2F25%2FIndependiente_Medellin_CO_20260225_1771970452022%2F~psid=17da5759-0dba-4eb5-9375-616e2a1b1443~aid=71e116db-825e-477c-b3f4-df5d3f2c8923~did=2e11e811-1ed0-4193-859b-5c4ff40a44c5~country=AR~kid=k02~hmac=9da7486b6390fbbef9a9bf47aac4a6b18fe424f1d0c3c6c8623cf2785e74c60f/gru1/va01/disneyplus/event/2026/02/25/Independiente_Medellin_CO_20260225_1771970452022/ctr-all-hdri-complete.m3u8"; + String drmKeyId = "4f37dd7a0f4d41b5947f627c0efcf654"; + String drmKey = "01987a05f2f3ab9b0e245a4f1b36474e"; + + Thread.sleep(500); // Small delay to show the toast + runOnUiThread(() -> startPlayback(streamUrl, drmKeyId, drmKey)); + } catch (Exception e) { + runOnUiThread(() -> { + Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show(); + playButton.setEnabled(true); + progressBar.setVisibility(View.GONE); + }); + } + }).start(); + }); + } + + private void startPlayback(String streamUrl, String drmKeyId, String drmKey) { + try { + releasePlayer(); + + ArrayList options = new ArrayList<>(); + options.add("--network-caching=3000"); + options.add(":no-cert-check"); + options.add(":demux=avformat"); + options.add(":key-format=org.w3.clearkey"); + options.add(":key=" + drmKeyId + ":" + drmKey); + options.add(":http-user-agent=Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36"); + options.add(":http-referrer=https://sudamericaplay.com/"); + + libVlc = new LibVLC(this, options); + mediaPlayer = new MediaPlayer(libVlc); + + final Handler mainHandler = new Handler(Looper.getMainLooper()); + + mediaPlayer.setEventListener(new MediaPlayer.EventListener() { + @Override + public void onEvent(MediaPlayer.Event event) { + mainHandler.post(() -> { + switch (event.type) { + case MediaPlayer.Event.Playing: + statusText.setText("Reproduciendo..."); + progressBar.setVisibility(View.GONE); + surfaceView.setVisibility(View.VISIBLE); + Toast.makeText(MainActivity.this, "Video iniciado", Toast.LENGTH_SHORT).show(); + break; + + case MediaPlayer.Event.EncounteredError: + statusText.setText("Error de reproducción"); + progressBar.setVisibility(View.GONE); + Toast.makeText(MainActivity.this, "Error al reproducir", Toast.LENGTH_LONG).show(); + playButton.setEnabled(true); + break; + + case MediaPlayer.Event.EndReached: + statusText.setText("Video terminado"); + break; + + case MediaPlayer.Event.Buffering: + float buffer = event.getBuffering(); + if (buffer < 1.0f) { + statusText.setText("Buffering: " + (int)(buffer * 100) + "%"); + } else { + statusText.setText("Reproduciendo..."); + } + break; + } + }); + } + }); + + Media media = new Media(libVlc, Uri.parse(streamUrl)); + mediaPlayer.setMedia(media); + media.release(); + + IVLCVout vout = mediaPlayer.getVLCVout(); + vout.setVideoView(surfaceView); + vout.attachViews(); + + mediaPlayer.play(); + + } catch (Exception e) { + Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show(); + playButton.setEnabled(true); + progressBar.setVisibility(View.GONE); + } + } + + private void releasePlayer() { + if (mediaPlayer != null) { + mediaPlayer.stop(); + mediaPlayer.getVLCVout().detachViews(); + mediaPlayer.release(); + mediaPlayer = null; + } + if (libVlc != null) { + libVlc.release(); + libVlc = null; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + releasePlayer(); + } +} diff --git a/DisneyPlayer/app/src/main/res/layout/activity_main.xml b/DisneyPlayer/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..e6f7738 --- /dev/null +++ b/DisneyPlayer/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,35 @@ + + + + + + + + + +