В настоящее время я разрабатываю приложение для Android, использующее LibVLC для воспроизведения видео. Однако я столкнулся с проблемой, из-за которой LibVLC не может открыть указатель медиаресурсов (MRL) при попытке воспроизвести видео MP4 из внутренней памяти.
Я использую Android 13 в качестве целевой SDK. Вот соответствующий фрагмент кода:
// Code snippet
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.view.WindowManager;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.interfaces.IMedia;
import org.videolan.libvlc.interfaces.IVLCVout;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import org.videolan.libvlc.Media;
public class MainActivity extends AppCompatActivity {
private SurfaceView surfaceView;
private LibVLC libVLC;
private org.videolan.libvlc.MediaPlayer mediaPlayer;
private Button browseButton;
private static final int PERMISSION_REQUEST_CODE = 1;
private static final int PICK_VIDEO_REQUEST_CODE = 2;
private static WeakReference instance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance = new WeakReference(this);
setContentView(R.layout.activity_main);
checkPermissions(); // Call checkPermissions() in onCreate()
// Prevent screenshots while the video is playing
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
// Check if USB debugging is enabled
// if (isUsbDebuggingEnabled()) {
// showUsbDebuggingDialog();
// }
if (RootChecker.isDeviceRooted()) {
showRootedDeviceDialog();
return; // Exit the onCreate method if the device is rooted
}
// Check if the app is running on an emulator
if (EmulatorDetector.isEmulator()) {
showEmulatorDetectedDialog();
return; // Exit the onCreate method if running on an emulator
}
// Check app integrity
// if (!AppIntegrityChecker.isSignatureValid(this)) {
// Show error dialog and redirect to Play Store
// showAppCorruptDialog();
// return; // Exit the onCreate method if app integrity check fails
// }
// Initialize VLC
ArrayList options = new ArrayList();
options.add("--aout=opensles");
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
libVLC = new LibVLC(this, options);
// Initialize media player
mediaPlayer = new MediaPlayer(libVLC);
mediaPlayer.setEventListener(event -> {
switch (event.type) {
case MediaPlayer.Event.EndReached:
// Handle the end of media playback
break;
}
});
// Initialize player view
surfaceView = findViewById(R.id.surface_view);
IVLCVout vout = mediaPlayer.getVLCVout();
vout.setVideoView(surfaceView);
vout.attachViews();
// Set up browse button click listener
browseButton = findViewById(R.id.browse_button);
browseButton.setOnClickListener(v -> pickVideo());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_open:
// Launch file picker activity to select video file
pickVideo();
return true;
case R.id.action_add:
// Handle "Add License" menu item click
openAddLicenseActivity();
return true;
case R.id.action_edit:
// Handle "Edit License" menu item click
openEditLicenseActivity();
return true;
case R.id.action_exit:
// Handle "Exit" menu item click
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void openAddLicenseActivity() {
Intent intent = new Intent(this, AddLicense.class);
startActivity(intent);
}
private void openEditLicenseActivity() {
Intent intent = new Intent(this, EditLicense.class);
startActivity(intent);
}
@Override
protected void onResume() {
super.onResume();
checkPermissions(); // Call checkPermissions() in onResume() too
}
private void checkPermissions() {
String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!arePermissionsGranted(permissions)) {
ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
}
}
private void showAppCorruptDialog() {
new AlertDialog.Builder(this)
.setTitle("App Corrupted")
.setMessage("Please download the app from the Google Play Store.")
.setPositiveButton("OK", (dialog, which) -> redirectToPlayStore())
.setCancelable(false)
.show();
}
private void redirectToPlayStore() {
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.dedseec")));
} catch (android.content.ActivityNotFoundException e) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/deta ... om.dedseec")));
}
finish(); // Close the current activity
}
private void showRootedDeviceDialog() {
new AlertDialog.Builder(this)
.setTitle("Rooted Device Detected")
.setMessage("This app cannot be used on rooted devices.")
.setPositiveButton("Exit", (dialog, which) -> finish())
.setCancelable(false)
.show();
}
private void showEmulatorDetectedDialog() {
new AlertDialog.Builder(this)
.setTitle("Emulator Detected")
.setMessage("This app cannot be used on emulators.")
.setPositiveButton("Exit", (dialog, which) -> finish())
.setCancelable(false)
.show();
}
private void pickVideo() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("video/*");
startActivityForResult(intent, PICK_VIDEO_REQUEST_CODE);
}
private void onVideoPicked(Uri videoUri) {
if (videoUri != null) {
playVideo(videoUri);
}
}
private void playVideo(Uri videoUri) {
// Create media object
Media media = new Media(libVLC, videoUri);
// Set media to the media player
mediaPlayer.setMedia(media);
// Start playback
mediaPlayer.play();
}
// Method to get the context of MainActivity
public static Context getContext() {
return instance().getApplicationContext();
}
// Method to read data from a file
public static String readFromFile(File file) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
int size = fis.available();
byte[] buffer = new byte[size];
fis.read(buffer);
return new String(buffer);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// Method to write data to a file
public static void writeToFile(File file, String data) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// Helper method to get the instance of MainActivity
private static MainActivity instance() {
return instance != null ? instance.get() : null;
}
private boolean isUsbDebuggingEnabled() {
int adbEnabled = Settings.Global.getInt(getContentResolver(), Settings.Global.ADB_ENABLED, 0);
return adbEnabled == 1;
}
private void showUsbDebuggingDialog() {
new AlertDialog.Builder(this)
.setTitle("USB Debugging Enabled")
.setMessage("Please disable USB debugging to continue using the app.")
.setPositiveButton("OK", (dialog, which) -> finish())
.setCancelable(false)
.show();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
for (int i = 0; i < permissions.length; i++) {
String permission = permissions;
if (grantResults == PackageManager.PERMISSION_GRANTED) {
// Permission granted, proceed with your action
} else {
// Permission denied, handle accordingly (e.g., show a message)
Toast.makeText(this, permission + " permission denied", Toast.LENGTH_SHORT).show();
}
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_VIDEO_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
Uri videoUri = data.getData();
if (videoUri != null) {
if (isDedFile(videoUri)) {
onVideoPicked(videoUri);
} else {
// Show error message for invalid file format
Toast.makeText(this, "Invalid file format. Please select a .ded file.", Toast.LENGTH_SHORT).show();
}
}
}
}
private boolean isDedFile(Uri uri) {
// Always return true to allow playing any video file
return true;
}
private String getFileExtension(Uri uri) {
// Get the file path from the URI
String filePath = getFilePathFromUri(uri);
// Extract the file extension
if (filePath != null && !filePath.isEmpty()) {
int lastDotIndex = filePath.lastIndexOf('.');
if (lastDotIndex != -1) {
return filePath.substring(lastDotIndex + 1);
}
}
return null;
}
private String getFilePathFromUri(Uri uri) {
String filePath = null;
if (uri != null) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
return filePath;
}
private boolean arePermissionsGranted(String[] permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
private byte[] decrypt(byte[] value, String key) {
try {
return Decryptor.decrypt(value, key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mediaPlayer.release();
libVLC.release();
}
}
The error message I'm receiving is:
libvlc input: VLC is unable to open the MRL 'content://com.android.externalstorage.documents/document/WA0033.mp4'.
Подробнее здесь: https://stackoverflow.com/questions/781 ... p4-video-f
Ошибка с LibVLC на Android 13: невозможно открыть MRL при воспроизведении видео MP4 из внутреннего хранилища. ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Видео libvlc играет нормально, но таймер видео не достигает конца продолжительности
Anonymous » » в форуме Android - 0 Ответы
- 3 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Exoplayer «MediaCodecvideorendererer ошибка» при воспроизведении видео в Flutter
Anonymous » » в форуме Android - 0 Ответы
- 2 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как избежать основной ошибки libvlc при использовании пакета python-vlc?
Anonymous » » в форуме Python - 0 Ответы
- 25 Просмотры
-
Последнее сообщение Anonymous
-