方向改变后播放位置重置为零

Posted

技术标签:

【中文标题】方向改变后播放位置重置为零【英文标题】:Playback position resets to zero after orientation change 【发布时间】:2021-01-25 09:35:42 【问题描述】:

下面是我的音乐播放器的代码。我使用 Videoview 播放本地精选歌曲列表。 我想在方向改变(纵向/横向)时存储和恢复播放位置。

我使用过 onSaveInstanceState 和 onRestoreInstanceState 方法。构建时没有错误,但歌曲每次都会重置。

我不知道出了什么问题。

package io.automaton.android.morningbinge;

import androidx.appcompat.app.AlertDialog;
import android.app.Activity;
import android.content.DialogInterface;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
import android.widget.VideoView;
import android.widget.MediaController;

import java.util.ArrayList;

public class MainActivity extends Activity
        implements MediaPlayer.OnCompletionListener 


        VideoView vw;
        ArrayList<Integer> videolist = new ArrayList<>();
        int currvideo = 0;
        int mPositionWhenPaused=0;
    @Override
        protected void onCreate(Bundle savedInstanceState)
        
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            vw = (VideoView)findViewById(R.id.videoView);
            vw.setMediaController(new MediaController(this));
            vw.setOnCompletionListener(this);

            // video name should be in lower case alphabet.
            videolist.add(R.raw.onbadhu_kolum);
            videolist.add(R.raw.kala_bhairava_ashtakam);
            videolist.add(R.raw.panchamukh_hanumath_kavacham);
            videolist.add(R.raw.kandha_shashti_kavasam);
            setVideo(videolist.get(0));
        
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) 
        super.onSaveInstanceState(savedInstanceState);
        //we use onSaveInstanceState in order to store the video playback position for orientation change
        savedInstanceState.putInt("Position", vw.getCurrentPosition());
        vw.pause();
    

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) 
        super.onRestoreInstanceState(savedInstanceState);
        //we use onRestoreInstanceState in order to play the video playback from the stored position
        mPositionWhenPaused = savedInstanceState.getInt("Position");
        vw.seekTo(mPositionWhenPaused);
    

    public void setVideo(int id)
        
            String uriPath
                    = "android.resource://"
                    + getPackageName() + "/" + id;
            Uri uri = Uri.parse(uriPath);
            vw.setVideoURI(uri);
            vw.start();
        

        public void onCompletion(MediaPlayer mediapalyer)
        
            AlertDialog.Builder obj = new AlertDialog.Builder(this);
            obj.setTitle("Playback Finished!");
            obj.setIcon(R.mipmap.ic_launcher);
            MyListener m = new MyListener();
            obj.setPositiveButton("Replay", m);
            obj.setNegativeButton("Next", m);
            obj.setMessage("Want to replay or play next video?");
            obj.show();
        

        class MyListener implements DialogInterface.OnClickListener 
            public void onClick(DialogInterface dialog, int which)
            
                if (which == -1) 
                    vw.seekTo(0);
                    vw.start();
                
                else 
                    ++currvideo;
                    if (currvideo == videolist.size())
                        currvideo = 0;
                    setVideo(videolist.get(currvideo));
                
            
        
    

【问题讨论】:

你能在你的 AndroidManifest 文件中分享这个活动声明吗? 您可能想尝试在其中设置配置更改而不是维护状态。例如,如果您在活动声明中设置 android:configChanges="orientation|keyboardHidden|screenSize" 内联,您会看到每次方向更改时都不会重新启动活动。 谢谢@Nathan Walsh。我设法让代码在没有重置的情况下运行。我已经在答案部分给出了代码。 【参考方案1】:

我解决了这个问题。我改变了调用列表的方式,以使用 setOnPreparedListener 进行播放,寻找最后播放的位置。

... 主要活动

package io.automaton.android.morningbinge;

import androidx.appcompat.app.AlertDialog;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import android.widget.VideoView;
import android.widget.MediaController;
import android.media.MediaPlayer.OnPreparedListener;
import java.util.ArrayList;

public class MainActivity extends Activity
        implements MediaPlayer.OnCompletionListener 

        VideoView vw;
        ArrayList<Integer> videolist = new ArrayList<>();
        int currvideo = 0;
        int mPositionWhenPaused=0;
        private static final String TAG = "MyActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
        
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            vw = (VideoView)findViewById(R.id.videoView);
            vw.setMediaController(new MediaController(this));
            vw.setOnCompletionListener(this);

            videolist.add(R.raw.onbadhu_kolum);
            videolist.add(R.raw.kala_bhairava_ashtakam);
            videolist.add(R.raw.panchamukh_hanumath_kavacham);
            videolist.add(R.raw.kandha_shashti_kavasam);

            try 
               //set the uri of the video to be played
                vw.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + videolist.get(0)));

             catch (Exception e) 
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            

            View decorView = getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(uiOptions);

           vw.requestFocus();
           vw.setOnPreparedListener(new OnPreparedListener() 
           public void onPrepared(MediaPlayer mediaPlayer) 
                    vw.seekTo(mPositionWhenPaused);
                    if (mPositionWhenPaused == 0) 
                        vw.start();
                     else 
                        vw.pause();
                    
                
            );
        

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) 
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt("Position", vw.getCurrentPosition());
        Log.i("Orientation Change", "Warn-orientation change and saved");
        vw.pause();
    

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) 
        super.onRestoreInstanceState(savedInstanceState);
        mPositionWhenPaused = savedInstanceState.getInt("Position");
        vw.seekTo(mPositionWhenPaused);
        Log.i("restored", "restored after orientation change");
    

    public void onCompletion(MediaPlayer mediapalyer)
        
            ++currvideo;
            if (currvideo == videolist.size())
                currvideo = 0;
            setVideo(videolist.get(currvideo));
        

    

...

android manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="io.automaton.android.morningbinge">
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity"
            android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

...

【讨论】:

以上是关于方向改变后播放位置重置为零的主要内容,如果未能解决你的问题,请参考以下文章

Android 设定横屏,禁止屏幕旋转,Activity重置 [更新视频播放器相关]

在 react-native-video 中,视频播放完毕后如何重置视频播放器?

Unity重置动画帧位置转换状态时控制播放速度

Unity重置动画帧位置转换状态时控制播放速度

Unity重置动画帧位置转换状态时控制播放速度

如何将 HTMLAudioElement 的当前播放位置重置为 0?