Android 无法使用 VLC 设置字幕
Unable to Set Subtitles with VLC for Android
我在为 Android 启动 VLC 的 VideoPlayerActivity 时设置字幕位置时遇到问题。我的目标是 API 27 并使用 FileProvider 来允许访问文件。
根据文档here,如果您设置 "subtitles_location" extra,那么您可以提供字幕文件的路径。不幸的是,我似乎无法让它工作。
我看到 "Subtitles" 菜单项保持灰色,下载字幕似乎不会改变这种状态。点击时,"Select subtitle file" VLC 声明目录中没有字幕文件并且 URI 带有前缀,如预期的那样 "content://"。
视频文件和字幕文件共享相同的父目录,并使用 FileProvider 提供。
目标 API >= 24 时如何设置字幕文件?
更新:
- 好像点击字幕选择菜单项时,它使用
视频文件的父目录。 This is seen here.
- 想通了,请参阅下面的解决方案。
下面是我如何通过意图启动 VideoPlayerActivity 的一些代码片段。
播放视频方法:
/**
* Play a video using VLC media player. This method will play media by using
* the VLC VideoPlayerActivity.
*
* @param activity The current activity.
* @param authority The FileProvider authority.
* @param vlcPackageName The VLC package name.
* @param vlcActivityName The VLC activity name.
* @param videoFile The video file to play.
* @param subtitlesFile The subtitles file to play.
* @param playbackPosition The playback position.
* @param requestCode The activity for result request code.
*/
public static void playVideo(
AppCompatActivity activity,
String authority,
String vlcPackageName,
String vlcActivityName,
String vlcTitleExtra,
String vlcPositionExtra,
String vlcFromStartExtra,
String vlcSubtitlesExtra,
File videoFile,
File subtitlesFile,
long playbackPosition,
int requestCode
) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(vlcPackageName);
// Set component to VLC video player activity.
intent.setComponent(new ComponentName(
vlcPackageName,
vlcActivityName
));
// Set intent permission flags.
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Set title and playback position.
intent.putExtra(vlcTitleExtra, videoFile.getName());
intent.putExtra(vlcPositionExtra, playbackPosition);
intent.putExtra(vlcFromStartExtra, false);
// Set video file location
intent.setDataAndTypeAndNormalize(
FileProvider.getUriForFile(
activity,
authority,
videoFile
),
"video/*"
);
// Subtitles file provided, set location on intent.
if (subtitlesFile != null) {
intent.putExtra(
vlcSubtitlesExtra,
FileProvider.getUriForFile(
activity,
authority,
subtitlesFile
)
);
}
activity.startActivityForResult(intent, requestCode);
}
清单中的提供商定义
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.masterwok.bitcast.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths" />
</provider>
@xml/paths定义:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="Download"
path="Download/"/>
</paths>
我能够通过使用未记录的 "item_location" 额外定义来解决这个问题:here.
当目标 API >= 24 时,这解决了权限问题。发生的事情是 VideoPlayerActivity 试图读取使用 FileProvider 提供的 URI 的父目录。如果非要我猜的话,我会说 Android 不允许这样做。
通过使用 "item_location" extra 传递 URI,我们可以绕过此限制。
我现在播放视频文件的方法如下:
/**
* Play a video using VLC media player. This method will play media by using
* the VLC VideoPlayerActivity.
*
* @param activity The current activity.
* @param vlcPackageName The VLC package name.
* @param vlcActivityName The VLC activity name.
* @param videoFile The video file to play.
* @param playbackPosition The playback position.
* @param requestCode The activity for result request code.
*/
public static void playVideo(
AppCompatActivity activity,
String vlcPackageName,
String vlcActivityName,
String vlcItemLocationExtra,
String vlcTitleExtra,
String vlcPositionExtra,
String vlcFromStartExtra,
File videoFile,
long playbackPosition,
int requestCode
) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(vlcPackageName);
// Set component to VLC video player activity.
intent.setComponent(new ComponentName(
vlcPackageName,
vlcActivityName
));
// Set intent permission flags.
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Set title and playback position.
intent.putExtra(vlcTitleExtra, videoFile.getName());
intent.putExtra(vlcPositionExtra, playbackPosition);
intent.putExtra(vlcFromStartExtra, false);
// Set video file location (subtitles are found by VLC by using parent directory).
intent.putExtra(vlcItemLocationExtra, Uri.fromFile(videoFile));
activity.startActivityForResult(intent, requestCode);
}
我在为 Android 启动 VLC 的 VideoPlayerActivity 时设置字幕位置时遇到问题。我的目标是 API 27 并使用 FileProvider 来允许访问文件。
根据文档here,如果您设置 "subtitles_location" extra,那么您可以提供字幕文件的路径。不幸的是,我似乎无法让它工作。
我看到 "Subtitles" 菜单项保持灰色,下载字幕似乎不会改变这种状态。点击时,"Select subtitle file" VLC 声明目录中没有字幕文件并且 URI 带有前缀,如预期的那样 "content://"。
视频文件和字幕文件共享相同的父目录,并使用 FileProvider 提供。
目标 API >= 24 时如何设置字幕文件?
更新:
- 好像点击字幕选择菜单项时,它使用 视频文件的父目录。 This is seen here.
- 想通了,请参阅下面的解决方案。
下面是我如何通过意图启动 VideoPlayerActivity 的一些代码片段。
播放视频方法:
/**
* Play a video using VLC media player. This method will play media by using
* the VLC VideoPlayerActivity.
*
* @param activity The current activity.
* @param authority The FileProvider authority.
* @param vlcPackageName The VLC package name.
* @param vlcActivityName The VLC activity name.
* @param videoFile The video file to play.
* @param subtitlesFile The subtitles file to play.
* @param playbackPosition The playback position.
* @param requestCode The activity for result request code.
*/
public static void playVideo(
AppCompatActivity activity,
String authority,
String vlcPackageName,
String vlcActivityName,
String vlcTitleExtra,
String vlcPositionExtra,
String vlcFromStartExtra,
String vlcSubtitlesExtra,
File videoFile,
File subtitlesFile,
long playbackPosition,
int requestCode
) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(vlcPackageName);
// Set component to VLC video player activity.
intent.setComponent(new ComponentName(
vlcPackageName,
vlcActivityName
));
// Set intent permission flags.
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Set title and playback position.
intent.putExtra(vlcTitleExtra, videoFile.getName());
intent.putExtra(vlcPositionExtra, playbackPosition);
intent.putExtra(vlcFromStartExtra, false);
// Set video file location
intent.setDataAndTypeAndNormalize(
FileProvider.getUriForFile(
activity,
authority,
videoFile
),
"video/*"
);
// Subtitles file provided, set location on intent.
if (subtitlesFile != null) {
intent.putExtra(
vlcSubtitlesExtra,
FileProvider.getUriForFile(
activity,
authority,
subtitlesFile
)
);
}
activity.startActivityForResult(intent, requestCode);
}
清单中的提供商定义
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.masterwok.bitcast.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths" />
</provider>
@xml/paths定义:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="Download"
path="Download/"/>
</paths>
我能够通过使用未记录的 "item_location" 额外定义来解决这个问题:here.
当目标 API >= 24 时,这解决了权限问题。发生的事情是 VideoPlayerActivity 试图读取使用 FileProvider 提供的 URI 的父目录。如果非要我猜的话,我会说 Android 不允许这样做。
通过使用 "item_location" extra 传递 URI,我们可以绕过此限制。
我现在播放视频文件的方法如下:
/**
* Play a video using VLC media player. This method will play media by using
* the VLC VideoPlayerActivity.
*
* @param activity The current activity.
* @param vlcPackageName The VLC package name.
* @param vlcActivityName The VLC activity name.
* @param videoFile The video file to play.
* @param playbackPosition The playback position.
* @param requestCode The activity for result request code.
*/
public static void playVideo(
AppCompatActivity activity,
String vlcPackageName,
String vlcActivityName,
String vlcItemLocationExtra,
String vlcTitleExtra,
String vlcPositionExtra,
String vlcFromStartExtra,
File videoFile,
long playbackPosition,
int requestCode
) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(vlcPackageName);
// Set component to VLC video player activity.
intent.setComponent(new ComponentName(
vlcPackageName,
vlcActivityName
));
// Set intent permission flags.
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Set title and playback position.
intent.putExtra(vlcTitleExtra, videoFile.getName());
intent.putExtra(vlcPositionExtra, playbackPosition);
intent.putExtra(vlcFromStartExtra, false);
// Set video file location (subtitles are found by VLC by using parent directory).
intent.putExtra(vlcItemLocationExtra, Uri.fromFile(videoFile));
activity.startActivityForResult(intent, requestCode);
}