将android应用中的视频文件集成为应用背景

Posted

技术标签:

【中文标题】将android应用中的视频文件集成为应用背景【英文标题】:Integrating video file in android app as app background 【发布时间】:2012-02-08 10:46:14 【问题描述】:

我需要使用视频作为背景。首先,我将视频文件放在可绘制文件夹中,并在 main.xml 中作为LinearLayout 的背景调用。但是在运行应用程序时,我只看到一个黑屏。然后我尝试使用VideoView 并将其命名如下:

  <VideoView
    android:id="@+id/video"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:background="@raw/hp"/>

在我的活动文件中,我使用以下代码 sn-p 调用它:

  public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        VideoView video=(VideoView) findViewById(R.id.video);
        video.start();

但我仍然没有在那里获得视频文件。我的主要建议是使用气泡视频作为背景,并在其上放置两个气泡按钮,并给用户一种水景屏幕的感觉。谁能帮我?

还有我想从 res 文件夹中使用的视频文件。不是来自 SD 卡或任何外部媒体文件夹。

【问题讨论】:

【参考方案1】:

我的朋友,首先你不能为你的VideoView 设置背景并让它在你的屏幕背景中播放。

请按照我的步骤并付出你的努力,你应该在那里。

从可绘制文件夹中删除您的视频并将其添加到原始文件夹。请谷歌如何创建原始文件夹。虽然很简单。并将您的视频文件放入其中。

首先,像这样在您的 xml 中创建一个SurfaceView

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
            android:id="@+id/home_container"  
            android:layout_ 
            android:layout_>

<SurfaceView 
        android:id="@+id/surface" 
        android:layout_ 
        android:layout_ 
        android:paddingTop="10dip" />
</Framelayout>

现在,创建一个类似下面的类,它可以实现SurfaceView

public class YourMovieActivity extends Activity implements SurfaceHolder.Callback 
    private MediaPlayer mp = null;
    //...
  SurfaceView mSurfaceView=null;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        mp = new MediaPlayer();
        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
        mSurfaceView.getHolder().addCallback(this);
        //...
    

现在您的班级将要求添加未实现的方法。只需点击“添加未实现的方法”即可添加这些方法

现在您将能够看到这样的自动生成方法,

@Override
public void surfaceCreated(SurfaceHolder holder) 


在这个方法里面,添加下面的代码,

@Override
public void surfaceCreated(SurfaceHolder holder) 


   Uri video = Uri.parse("android.resource://" + getPackageName() + "/" 
      + R.raw.your_raw_file);

    mp.setDataSource(video);
    mp.prepare();

    //Get the dimensions of the video
    int videoWidth = mp.getVideoWidth();
    int videoHeight = mp.getVideoHeight();

    //Get the width of the screen
    int screenWidth = getWindowManager().getDefaultDisplay().getWidth();

    //Get the SurfaceView layout parameters
    android.view.ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();

    //Set the width of the SurfaceView to the width of the screen
    lp.width = screenWidth;

    //Set the height of the SurfaceView to match the aspect ratio of the video 
    //be sure to cast these as floats otherwise the calculation will likely be 0
    lp.height = (int) (((float)videoHeight / (float)videoWidth) * (float)screenWidth);

    //Commit the layout parameters
    mSurfaceView.setLayoutParams(lp);        

    //Start video
    mp.setDisplay(holder);
    mp.start();

【讨论】:

我有什么办法可以通过后台服务做同样的事情吗?比如从服务中创建视频播放器? TextureView 呢? @AndroSelva 这对我不起作用,希望有人能提供更好的解决方案,或者整合视频文件的有效方法。 只有黑色背景 我和@Mansuu 有同样的问题......我有一个黑色的背景。有谁知道问题所在?【参考方案2】:
/**
 * Created by zoid23 on 05/10/15.
 */
public class IntroVideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback 

    private static final String TAG = "INTRO_SF_VIDEO_CALLBACK";
    private MediaPlayer mp;

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public IntroVideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    

    public IntroVideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        init();
    
    public IntroVideoSurfaceView(Context context, AttributeSet attrs) 
        super(context, attrs);
        init();
    
    public IntroVideoSurfaceView(Context context) 
        super(context);
        init();
    

    private void init ()
        mp = new MediaPlayer();
        getHolder().addCallback(this);
    

    @Override
    public void surfaceCreated(SurfaceHolder holder) 
        AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.intro);
        try 
            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
            mp.prepare();
         catch (IOException e) 
            e.printStackTrace();
        
        int videoWidth = mp.getVideoWidth();
        int videoHeight = mp.getVideoHeight();
        int screenHeight = getHeight();
        android.view.ViewGroup.LayoutParams lp = getLayoutParams();
        lp.height = screenHeight;
        lp.width = (int) (((float)videoWidth / (float)videoHeight) * (float)screenHeight);

        setLayoutParams(lp);
        mp.setDisplay(getHolder());
        mp.setLooping(true);
        mp.start();
    

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
    

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) 
        mp.stop();
    


在您的 xml 上使用 IntroVideoSurfaceView 并将您的视频放入 raw/intro.mp4

【讨论】:

您需要关闭 afd。最后 尝试 afd.close(); catch (IOException e) e.printStackTrace(); 【参考方案3】:

luigi23 修改版的完整版,避免了一些崩溃。

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity 

  @Override public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  

没有关于主要活动的内容。您可能希望通过添加

使其全屏
  <style name="Theme.AppCompat.Light.NoActionBar.FullScreen" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
  </style>

创建文件 IntroVideoSurfaceView.java

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.os.Build;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;

public class IntroVideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback 

  private MediaPlayer mp;
  private boolean has_started = false;

  @TargetApi(Build.VERSION_CODES.LOLLIPOP) public IntroVideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
    super(context, attrs, defStyleAttr, defStyleRes);
    init();
  

  public IntroVideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) 
    super(context, attrs, defStyleAttr);
    init();
  

  public IntroVideoSurfaceView(Context context, AttributeSet attrs) 
    super(context, attrs);
    init();
  

  public IntroVideoSurfaceView(Context context) 
    super(context);
    init();
  

  private void init() 
    mp = new MediaPlayer();
    getHolder().addCallback(this);
  

  @Override public void surfaceCreated(SurfaceHolder holder) 
    AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.slideshow);
    try 
      if (!has_started) 
        has_started = true;
        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
      

      mp.prepare();
      android.view.ViewGroup.LayoutParams lp = getLayoutParams();
      lp.height = getHeight();
      lp.width = getWidth();

      setLayoutParams(lp);
      mp.setDisplay(getHolder());
      mp.setLooping(true);
      mp.start();
     catch (IOException e) 
      e.printStackTrace();
    
  

  @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
  

  @Override public void surfaceDestroyed(SurfaceHolder holder) 
    mp.stop();
  

在 resources/raw 中添加“slideshow.mp4”

修改activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/home_container"
    android:layout_
    android:layout_
    >

  <com.androidadvance.videobackground.IntroVideoSurfaceView
      android:id="@+id/surface"
      android:layout_
      android:layout_
      />

  <Button
      android:layout_
      android:layout_
      android:text="Press Me"
      android:id="@+id/button"
      android:layout_gravity="center_horizontal|bottom"
      android:layout_margin="16dp"
      />
</FrameLayout>

一些笔记。

添加视频会使您的 apk 变得庞大,因此您可能希望避免这种情况...有时甚至在高端手机(galaxy s6)上也会发生未知崩溃 保持文件小很重要。

【讨论】:

此代码在活动创建并运行时起作用。但是当我们进入下一个活动并返回此活动时,它失败并出现错误:android.media.MediaPlayer._prepare(Native Method) at android.media.MediaPlayer.prepare(MediaPlayer.java:1135) 的 java.lang.IllegalStateException ) 在 我已经为 onStop、onResume 和 onPause 放置了 onResume() mediaplyer.resume() 等的代码,但不确定。它在 mp.prepare(); 失败; @OWADVL : 你能把你正在做的代码放在活动中吗?【参考方案4】:

我已使用此代码在表面视图上播放视频

public class VideoPlayOnSurfaceView extends SurfaceView implements SurfaceHolder.Callback 

    private MediaPlayer mediaPlayer;
    private boolean has_started = false;

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public VideoPlayOnSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    

    public VideoPlayOnSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        init();
    

    public VideoPlayOnSurfaceView(Context context, AttributeSet attrs) 
        super(context, attrs);
        init();
    

    public VideoPlayOnSurfaceView(Context context) 
        super(context);
        init();
    

    private void init() 
        mediaPlayer = new MediaPlayer();
        getHolder().addCallback(this);
    

    @Override
    public void surfaceCreated(SurfaceHolder holder) 
        AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.small);
        try 
            if (!has_started) 
                has_started = true;
                mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
            

            mediaPlayer.prepare();
            android.view.ViewGroup.LayoutParams lp = getLayoutParams();
            lp.height = getHeight();
            lp.width = getWidth();

            setLayoutParams(lp);
            mediaPlayer.setDisplay(holder);
            mediaPlayer.setLooping(true);
            mediaPlayer.start();
         catch (IOException e) 
            e.printStackTrace();
        
    

    @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
    

    @Override public void surfaceDestroyed(SurfaceHolder holder) 
        mediaPlayer.stop();
    

xml 文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>

        <YourPacakageName.VideoPlayOnSurfaceView
            android:id="@+id/surface"
            android:layout_
            android:layout_
            android:paddingTop="10dip" />
</FrameLayout>

【讨论】:

【参考方案5】:

我能够结合以上和以下其他两个帖子来完成此工作:

Android player raising exception prepare failed:status 0x1

How to attach MediaPlayer with SurfaceView in android?

【讨论】:

【参考方案6】:

我用过

AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.file_name);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());

而不是

 Uri video = Uri.parse("android.resource://" + getPackageName() + "/" 
      + R.raw.your_raw_file);

并使用下面的代码来设置媒体播放器。

MediaPlayer mp = new MediaPlayer();
SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.video_surface);
SurfaceHolder holder = mSurfaceView.getHolder();
holder.addCallback(this);

【讨论】:

以上是关于将android应用中的视频文件集成为应用背景的主要内容,如果未能解决你的问题,请参考以下文章

将视频设置为背景

用于开发使用视频流的应用程序的 Windows 或 Android 平板电脑

用声网 Android UIKit 为实时视频通话应用添加自定义背景丨声网 SDK 教程

ios上cordova应用程序中的视频没有声音

将视频保存为输入而不是android中的相机

Android:如何获取应用程序私有文件的视频缩略图?