Я новичок в разработке Android и Java, и мне нужны рекомендации по настройке простого приложения для деки. То, что я пытаюсь сделать и у меня возникают проблемы с его эффективной работой, - это обработка событий для нескольких медиаплееров.
Например, я создаю деку, посредством которой, когда я нажимаю кнопку, я хочу, чтобы все остальные звуки были остановлены и высвобождены из памяти, и кнопку, которую я только что нажал, для воспроизведения назначенного звука. Я понимаю, что повторение блоков кода - не лучший подход к программированию, но я пробовал это с массивами и операторами переключения, но без особого эффекта. Мне были бы очень полезны любые инструкции по эффективному освобождению звуков из памяти при использовании нескольких MediaPlayers. Я добавил свой код ниже для 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




Вы используете медиаплеер после его выпуска. Удалите эти строки из своего onCompletionListener и вместо этого добавьте их в onDestroy своей активности.
Meow1.release();
Meow2.release();
Meow3.release();
Meow4.release();
Также вызов create автоматически создает новый экземпляр, вы также можете удалить эти строки
Meow1 = new MediaPlayer();
Meow2 = new MediaPlayer();
Meow3 = new MediaPlayer();
Meow4 = new MediaPlayer();
Лучшим подходом было бы использовать один медиаплеер и просто изменить источник даты, когда пользователь захочет воспроизвести другой источник, но этот метод займет некоторое время, прежде чем он воспроизведет звук, поскольку он будет готовить звук каждый раз, это было бы незначительным, если только ваш аудио размер довольно велик
Посмотрите, как вы сейчас контролируете свои медиа:
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. stackoverflow.com/questions/50635392/…