多个 MediaPlayers 不断失败 - Android 工作室

Posted

技术标签:

【中文标题】多个 MediaPlayers 不断失败 - Android 工作室【英文标题】:Multiple MediaPlayers keep failing - Android studio 【发布时间】:2018-11-09 21:54:14 【问题描述】:

我是 android 和 Java 开发的新手,我正在寻找一些关于设置简单音板应用程序的指导。我正在尝试做的并且在使其有效工作方面遇到问题的是为多个媒体播放器处理事件。

例如,我正在创建一个音板,当我单击一个按钮时,我希望所有其他声音停止并从内存中释放,并且我刚刚按下的按钮播放其分配的声音。我意识到重复代码块不是一种好的编程方法,但我也尝试过使用数组和 switch 语句,但效果不大。任何关于如何在使用多个 MediaPlayer 时有效地从内存中释放声音的指导对我来说都非常有用。我在下面包含了 4 个按钮的代码(我在这个应用上有超过 30 个)

public class MainActivity extends AppCompatActivity 


private MediaPlayer Meow1,Meow2,Meow3,Meow4;
private Button meowButton1,meowButton2,meowButton3,meowButton4;


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



 Meow1 = new MediaPlayer();
        Meow1 = MediaPlayer.create(getApplicationContext(), R.raw.meow1);
       // final Boolean Meow1Pause = !Meow1.isPlaying() && Meow1.getCurrentPosition() >1;
        meowButton1 = (Button) findViewById(R.id.Meow1);
        meowButton1.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                if (Meow1.isPlaying())
                 pauseMusic1();
                 else 
                    Meow1.start();
                
        );
        Meow1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() 
            @Override
            public void onCompletion(MediaPlayer Meow1) 
                Meow1.stop();
                Meow1.reset();
                Meow1.release();

            
        );



       Meow2 = new MediaPlayer();
       Meow2 = MediaPlayer.create(getApplicationContext(), R.raw.meow2);

        meowButton2 = (Button) findViewById(R.id.Meow2);
        meowButton2.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                if (Meow2.isPlaying() )
                    pauseMusic();
                 else 
                    Meow2.start();      
        
        );

        Meow2.setOnCompletionListener(new MediaPlayer.OnCompletionListener() 
            @Override
            public void onCompletion(MediaPlayer Meow1) 
                Meow2.stop();
                Meow2.reset();
                Meow2.release();
            
        );

        Meow3 = new MediaPlayer();
        Meow3 = MediaPlayer.create(getApplicationContext(), R.raw.meow3);
        meowButton3 = (Button) findViewById(R.id.Meow3);
        meowButton3.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                if (Meow3.isPlaying())
                 pauseMusic();
                 else 
                    Meow3.start();
                
        );
        Meow3.setOnCompletionListener(new MediaPlayer.OnCompletionListener() 
            @Override
            public void onCompletion(MediaPlayer Meow1) 
                Meow3.stop();
                Meow3.reset();
                Meow3.release();

            
        );

        Meow4 = new MediaPlayer();
        Meow4  = MediaPlayer.create(getApplicationContext(), R.raw.meow4);
        meowButton4 = (Button) findViewById(R.id.Meow4);
        meowButton4.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                if (Meow4.isPlaying())
                 pauseMusic();
                 else 
                    Meow4.start();
                
        );


public void pauseMusic()  
    if(Meow1 != null && Meow1.isPlaying()) Meow1.pause();
    if(Meow2 != null && Meow2.isPlaying()) Meow2.pause();
    if(Meow3 != null && Meow3.isPlaying()) Meow3.pause();
    if(Meow4 != null && Meow4.isPlaying()) Meow4.pause();





Run Compiler:
A: Logging event (FE): screen_view(_vs), Bundle[firebase_event_origin(_o)=auto, firebase_previous_class(_pc)=SplashScreen, firebase_previous_id(_pi)=-6549553702477848745, firebase_screen_class(_sc)=MainActivity, firebase_screen_id(_si)=-6549553702477848744]
I/zygote: Do partial code cache collection, code=124KB, data=67KB
I/zygote: After code cache collection, code=124KB, data=67KB
I/zygote: Increasing code cache capacity to 512KB
V/FA: Activity resumed, time: 6376787
D/EGL_emulation: eglMakeCurrent: 0x980fde60: ver 3 0 (tinfo 0xa3c3c290)
D/EGL_emulation: eglMakeCurrent: 0x980fde60: ver 3 0 (tinfo 0xa3c3c290)
D/EGL_emulation: eglMakeCurrent: 0x980fde60: ver 3 0 (tinfo 0xa3c3c290)
I/chatty: uid=10085(u0_a85) RenderThread identical 2 lines
D/EGL_emulation: eglMakeCurrent: 0x980fde60: ver 3 0 (tinfo 0xa3c3c290)
V/FA: Inactivity, disconnecting from the service
V/MediaPlayer: resetDrmState:  mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
               cleanDrmObj: mDrmObj=null mDrmSessionId=null
V/MediaPlayer: resetDrmState:  mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
               cleanDrmObj: mDrmObj=null mDrmSessionId=null
D/TAG1: Button 2 pressed
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: g.convery.cat_sounds, PID: 12276
                  java.lang.IllegalStateException
                      at android.media.MediaPlayer.isPlaying(Native Method)
                      at g.convery.cat_sounds.MainActivity$1.onClick(MainActivity.java:97)
                      at android.view.View.performClick(View.java:6256)
                      at android.view.View$PerformClick.run(View.java:24701)
                      at android.os.Handler.handleCallback(Handler.java:789)
                      at android.os.Handler.dispatchMessage(Handler.java:98)
                      at android.os.Looper.loop(Looper.java:164)
                      at android.app.ActivityThread.main(ActivityThread.java:6541)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
W/MediaPlayer-JNI: MediaPlayer finalized without being released
W/MediaPlayer-JNI: MediaPlayer finalized without being released
Application terminated.


LOGCAT:

05-31 09:21:30.099 12276-12288/g.convery.cat_sounds W/MediaPlayer-JNI: MediaPlayer finalized without being released
05-31 09:21:30.211 12276-12288/g.convery.cat_sounds I/chatty: uid=10085(u0_a85) FinalizerDaemon identical 33 lines
05-31 09:21:30.212 12276-12288/g.convery.cat_sounds W/MediaPlayer-JNI: MediaPlayer finalized without being released
05-31 09:21:30.283 12276-12284/g.convery.cat_sounds I/zygote: Do partial code cache collection, code=124KB, data=67KB
05-31 09:21:30.286 12276-12284/g.convery.cat_sounds I/zygote: After code cache collection, code=124KB, data=67KB
05-31 09:21:30.287 12276-12284/g.convery.cat_sounds I/zygote: Increasing code cache capacity to 512KB
05-31 09:21:31.159 12276-12307/g.convery.cat_sounds I/chatty: uid=10085(u0_a85) RenderThread identical 2 lines
05-31 09:24:41.746 12276-12276/g.convery.cat_sounds E/AndroidRuntime: FATAL EXCEPTION: main
    Process: g.convery.cat_sounds, PID: 12276
    java.lang.IllegalStateException
        at android.media.MediaPlayer.isPlaying(Native Method)
        at g.convery.cat_sounds.MainActivity$1.onClick(MainActivity.java:97)
        at android.view.View.performClick(View.java:6256)
        at android.view.View$PerformClick.run(View.java:24701)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
05-31 09:24:47.955 12276-12288/g.convery.cat_sounds W/MediaPlayer-JNI: MediaPlayer finalized without being released
05-31 09:24:47.956 12276-12288/g.convery.cat_sounds W/MediaPlayer-JNI: MediaPlayer finalized without being released

【问题讨论】:

【参考方案1】:

释放媒体播放器后,您正在使用它。从您的 onCompletionListener 中删除这些行并将它们添加到您的活动的 onDestroy 中

Meow1.release();
Meow2.release();
Meow3.release();
Meow4.release();

同样调用 create 会自动创建一个新实例,你也可以删除这些行

Meow1 = new MediaPlayer();
Meow2 = new MediaPlayer();
Meow3 = new MediaPlayer();
Meow4 = new MediaPlayer();

更好的方法是使用单个媒体播放器,并在用户想要播放不同的源时更改日期源,但是这种方法在播放音频之前需要一些时间,因为它每次都会准备音频,这将除非您的音频尺寸很大,否则可以忽略不计

【讨论】:

【参考方案2】:

    看看你现在是如何控制你的媒体的:

    if (Meow4.isPlaying())  
        pauseMusic();
     else 
        Meow4.start();
    
    

    第一次调用Meow4.isPlaying(),您将收到IllegalStateException,因为您的播放器尚未初始化。

    查看您的 MediaPlayer 状态是如何定义的并调用适当的函数

    第二点,遇到重复块的时候,应该想到一个函数。

    Meow3 = new MediaPlayer();
    Meow3 = MediaPlayer.create(getApplicationContext(), R.raw.meow3);
    meowButton3 = (Button) findViewById(R.id.Meow3);
    meowButton3.setOnClickListener(new View.OnClickListener() 
    
    );
    meowButton3.setOnCompletionListener...
    

在函数中:registerPlayer(Context context, int resourceId, Button controlButton)

Or with higher level of abstraction, create a subclass of `MediaPlayer` and wrap these logic inside it

    你肯定不想一遍又一遍地Meow1.pause()。相反,将您的 MeoX 存储在一个列表中,然后循环遍历它:

    List<MediaPlayer> players = new ArrayList<>();
    players.add(Meow1);
    ....
    public void pauseMusic()  
         players.stream().filter(p -> p != null && p.isPlaying()).forEach(p -p.pause());
    
    

【讨论】:

谢谢伙计。我放弃了 MediaPlayer 类,转而使用 SoundPool 类,这似乎是制作音板应用程序的最佳方式。感谢您的帮助,我将在下一个应用程序中使用此解决方案。我已经针对 SoundPool 类遇到的一些问题打开了另一篇文章。 ***.com/questions/50635392/…

以上是关于多个 MediaPlayers 不断失败 - Android 工作室的主要内容,如果未能解决你的问题,请参考以下文章

Windows安装PostgreSQL失败:There has been an error

数组 UDF 不断重复单个值

liunx开启Nginx失败, 出现 An error occurred

具有多个 NIC 的计算机上的 UDPClient 多播接收失败

liunx开启Nginx失败, 出现 An error occurred

netstat-an 提示不是内部或外部命令