- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在构建一个应用程序,用户可以在其中点击一个按钮来全屏显示视频。最初,视频附加到 ViewPager 内的 View 。为了能够全屏显示它,我将它从它的父 View 中分离出来并将它重新附加到 Root View 。这工作正常,除非视频在播放时切换到全屏。当我分离一个正在播放的 VideoView 时,它就停止了,我需要重新启动它。这是 Not Acceptable ,因为视频在恢复之前开始缓冲。这是完成分离的代码部分:
final ViewGroup parent = (ViewGroup) findViewById(R.id.parent);
final ViewGroup root = (ViewGroup) findViewById(R.id.root);
Button b = (Button) findViewById(R.id.button);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
parent.removeView(mVideoView);
LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
root.addView(mVideoView, lp);
}
});
根据设备的不同,我有不同的日志错误。可能是因为实际的视频播放器是由制造商提供的,而不是 Android SDK。以下是 Nexus 7 的错误日志:
10-30 20:26:18.618: D/NvOsDebugPrintf(124): NvMMDecTVMRDestroyParser Begin
10-30 20:26:18.618: D/NvOsDebugPrintf(124): --------- Closing TVMR Frame Delivery Thread -------------
10-30 20:26:18.678: D/NvOsDebugPrintf(124): ------- NvAvpClose -------
10-30 20:26:18.678: D/NvOsDebugPrintf(124): NvMMDecTVMRDestroyParser Done
10-30 20:26:18.678: D/NvOsDebugPrintf(124): NvMMLiteTVMRDecPrivateClose Done
我无法在不停止的情况下分离视频。我尝试使用 SurfaceView 或 TextureView 但没有成功。
我还尝试寻找第三方视频播放器。我找到了一个商业的 ( http://www.vitamio.org/ ),出于商业原因我不能真正使用它。我找到了一个开源的,去年没有更新 ( https://code.google.com/p/dolphin-player/ )。
我目前只在平板电脑上定位 Android 4.2 或更高版本。
最佳答案
可以使用 TextureView
实现此效果。基本上你所做的是创建一个 MediaPlayer
实例,prepare()
它并启动它,然后你可以使用 MediaPlayer.setSurface()
任何 TextureView
上的方法在视频播放时更改表面,而不对 MediaPlayer
对象状态进行任何更改,如 android 文档中的 setSurface()
方法:
这个方法可以在任何状态下调用,调用它不会改变对象状态。
请注意此实现是为了演示,您可能应该使用 mediaplayer.prepareAsync()
并使用 onPreparedListener()
等待回调,您还将需要根据您的视频大小为第二个 TextureView
设置正确的尺寸,处理方向变化,当然还需要在需要时正确处理异常。
activity_main.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:background="#ff0000" />
<Button
android:id="@+id/btn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:text="Switch to second surface" />
<TextureView
android:id="@+id/tv_full"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
主 Activity .java
public class MainActivity extends Activity {
private static final String VIDEO_URI = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
private TextureView tvFull;
private MediaPlayer mp;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mp = new MediaPlayer();
try {
mp.setDataSource(this, Uri.parse(VIDEO_URI));
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
((ViewPager) findViewById(R.id.pager)).setAdapter(new PagerAdapter() {
@Override public int getCount() {
return 1;
}
@Override public boolean isViewFromObject(View view, Object o) {
return view == o;
}
@Override public Object instantiateItem(ViewGroup container, int position) {
final TextureView tv = new TextureView(MainActivity.this);
tv.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
tv.setSurfaceTextureListener(null);
mp.setSurface(new Surface(surfaceTexture));
mp.start();
}
@Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {}
@Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
@Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}
});
if (tv.isAvailable()) {
tv.getSurfaceTextureListener().onSurfaceTextureAvailable(tv.getSurfaceTexture(),
tv.getWidth(), tv.getHeight());
}
container.addView(tv, 0);
return tv;
}
@Override public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
});
tvFull = (TextureView) findViewById(R.id.tv_full);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
tvFull.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
tvFull.setSurfaceTextureListener(null);
mp.setSurface(new Surface(surfaceTexture));
}
@Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
}
@Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
@Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
});
if (tvFull.isAvailable()) {
tvFull.getSurfaceTextureListener().onSurfaceTextureAvailable(tvFull.getSurfaceTexture(),
tvFull.getWidth(), tvFull.getHeight());
}
}
});
}
@Override protected void onDestroy() {
mp.reset();
mp.release();
super.onDestroy();
}
}
关于android - 是否可以在不停止流的情况下分离和重新附加 VideoView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19696466/
这是我的代码 fragment ,我想在其中播放来自服务器的视频 private void PlayVideo() { try { getWindow().setFormat(
我对 Android Studio 相当陌生,正在尝试一个项目,其中基于点击事件,videoView(2 个视频)从 vid1 变为 vid2,vid2 变为 vid1 等等,并且两者同时播放且长度相
我感兴趣的是能够在 VideoView B 播放时“预缓冲”VideoView A。这可能吗? 我有两个 VideoView 实例。 在给定时间只会显示一个 VideoView,占据手机的整个屏幕。
我最初隐藏了 VideoView,当加载视频时,我正在显示 VideoView。但是,如果 VideoView 最初是 invisible,则永远不会调用 onPrepared。但是,如果 Video
我正在尝试将视频添加到我的应用程序中。视频本地存储在 res/raw 中。我不知道为什么会出现“videoView.setVideoURI("uri");”错误和“videoView.start();
我正在创建一个应用程序来在 Amazon FireTV 机顶盒上播放各种类型的视频。如果我使用默认的 Android VideoView 播放视频。如果我使用 Vitamio 的 VideoView,
我必须在 android 上强制使用 videoView.setZOrderOnTop(true)。但是在使用它之后,我无法在 videoView 上显示按钮。即使在设置 videoView.setZ
我正在尝试制作一个带有 VideoView 的视频播放器,它支持在其上使用 TextView 的字幕。 我已经解析了字幕,但现在我需要一个在每次帧更改时运行的事件,以使用当前播放位置更新字幕。 我尝试
我有一个 *.mp4文件,持续时间为 2 分钟。现在它有从 30 seconds upto 1.10 min 开始的音轨. 30s 之前的其余部分及之后 1.10min为空白。 现在的问题是当我尝试在
我想在我的started_activity背景下运行视频 View 。但加载失败。 屏幕是黑色的,如果我导航或将我的页面推送到另一个页面两次,它将显示应用程序没有响应警报。 我遵循这个视频教程:htt
我在这里使用imageView,当我点击它时应该向我显示一个视频(线性10),这个视频大约4秒,我需要一个代码,当我再次点击imageView 视频应该再次开始播放,每次我单击 imageView 时
我的一个 Activity 中有一个 VideoView,如果我尝试按后退 Button,它不会将我带到之前的 Activity 并且它也不会在日志猫中给出任何错误消息。 我尝试覆盖 onBackPr
我正在制作一个视频播放器,它将从服务器流式传输视频。我已经检查过,视频网址正确且有效!已经很晚了,所以我可能错过了一些东西,但为什么会这样 VideoView videoView = (VideoVi
我有一个应用程序正在从另一个充当服务器的应用程序接收视频文件。当应用程序保存在套接字上接收到的文件时,视频流开始播放该文件(正在构建中)。在代码示例中,按下 btnStream 后,按下 btnPla
我有一个视频 View ,我希望能够播放/暂停和全屏显示。我无法让视频显示控件。 private fun showVideo() { isLottieVisible = false
我制作了一个应用程序,我想在其中播放原始文件夹中的 SWF 文件。 当我运行应用程序时,它会显示 Sorry, the video cant be played. 我不知道如何纠正它。我已经在设备上安
有谁知道为什么我的应用程序在打印出 VideoView 中的变量时只返回错误的值? @Override public void onCreate(Bundle savedInstanceState)
我想编写在单击按钮时播放视频的代码。我无法显示视频。当我点击按钮播放时,模拟器停止工作。 public class Video extends Activity{ private static fin
所以我正在尝试在 android 中播放基本的 avi 视频,它似乎在 Windows Media Player、VLC 等上运行良好,所以它看起来不需要任何复杂的编解码器。我的应用程序中有一个视频
我正在开发具有两个 View 的应用程序,一个是 UI,另一个是 VideoView。在某些事件发生之前使用 UI 线程,然后我想将 setContentView 设置为 VideoView,但是在将
我是一名优秀的程序员,十分优秀!