【问题标题】:Android MediaPlayer not playing soundAndroid MediaPlayer 不播放声音
【发布时间】:2021-10-11 00:00:15
【问题描述】:

在我的 Android 应用中,我希望在显示特定 Activity 时播放振动和声音。我创建了两个 VibrationManager 和 SoundManager 单例类,并在 Activity 的“onCreate”方法中启动振动和声音。 Activity 有一个按钮,可以在单击时停止振动和声音,并关闭 Activity。即使输入了“playSound()”方法,除了没有播放的声音之外,一切似乎都可以正常工作。此外,有时会播放声音,显然是随机逻辑...我的声音代码有什么问题?

我的活动:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

import java.util.Calendar;

import it.mypackage.DBHelper;
import it.mypackage.DBManager;
import it.mypackage.R;
import it.mypackage.SoundManager;
import it.mypackage.VibrationManager;
import it.mypackage.listeners.MyActivityStopAlarmButtonClickListener;

public class MyActivity extends AppCompatActivity
    {
     SoundManager soundManager;
     VibrationManager vibrationManager;
     DBManager dbManager;

     TextView alarmTitle, alarmText;
     Button stopButton;

     String title, text;
     boolean okClicked;

     int request_code = -1;

     @Override
     protected void onCreate(Bundle savedInstanceState)
        {
         super.onCreate(savedInstanceState);

         dbManager = new DBManager(getApplicationContext());
         vibrationManager = VibrationManager.getInstance(getApplicationContext());
         soundManager = SoundManager.getInstance(getApplicationContext());

         // Vibrate
         vibrationManager.startVibration();

         // Play sound
         soundManager.playSound();

         setOkClicked(false);

         // Set Activity fullscreen
         this.requestWindowFeature(Window.FEATURE_NO_TITLE);
         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

         Window window = getWindow();

         // let the window be shown when the screen is locked and the keyguard will be dismissed
         window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                       | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

         // Turn the device's screen on and keep it turned on and bright
         // as long as this window is visible to the user
         window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                       | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

         setContentView(R.layout.activity_alarm_receiver);

         // Reference all Views of the Activity
         alarmTitle = (TextView) findViewById(R.id.alarm_title_push_notification);
         alarmText = (TextView) findViewById(R.id.alarm_text_push_notification);
         stopButton = (Button) findViewById(R.id.stop_alarm_push_button);

         Bundle extras = getIntent().getExtras();

         title = extras.getString("title");
         text = extras.getString("text");

         // used to snooze the alarm, to cancel the alarm schedule or to stop the alarm
         request_code = extras.getInt("request_code");

         alarmTitle.setText(title);
         alarmText.setText(text);

         // Set all listeners
         stopButton.setOnClickListener(new PatientsValuesCheckStopAlarmButtonClickListener());
        }


     @Override
     protected void onStop()
        {
         super.onStop();

         finish();
        }


     public void setOkClicked(boolean value)
        {
         this.okClicked = value;
        }
    }

MyActivityStopAlarmButtonClickListener:

package it.mypackage.listeners;

import android.app.Activity;
import android.view.View;

import java.util.Calendar;

import it.mypackage.SoundManager;
import it.mypackage.VibrationManager;
import it.mypackage.alarm.AlarmBroadcastReceiver;
import it.mypackage.alarm.AlarmSettingManager;
import it.mypackage.alarm.PatientsValuesCheckAlarmReceiverActivity;

public class MyActivityStopAlarmButtonClickListener implements View.OnClickListener
    {
     // Constructor
     public MyActivityStopAlarmButtonClickListener()
        {

        }


     @Override
     public void onClick(View v)
        {
         ((MyActivity)v.getContext()).setOkClicked(true);

         // Stop vibration
         VibrationManager vibrationManager = VibrationManager.getInstance(v.getContext().getApplicationContext());
         vibrationManager.stopVibration();

         // Stop the ringtone sound
         SoundManager soundManager = SoundManager.getInstance(v.getContext().getApplicationContext());
         soundManager.stopSound();

         // Close the reminder
         ((Activity)v.getContext()).finish();
        }
    }

振动管理器:

package it.mypackage;

import android.content.Context;
import android.os.Vibrator;

public class VibrationManager
    {
     private static VibrationManager vibrationManagerInstance = null;
     private Vibrator vibrator;


     public static VibrationManager getInstance(Context context)
        {
         // Use the application context, which will ensure that you
         // don't accidentally leak an Activity's context.
         if(vibrationManagerInstance == null)
            {
             vibrationManagerInstance = new VibrationManager(context.getApplicationContext());
            }

         return vibrationManagerInstance;
        }


     // Constructor
     private VibrationManager(Context context)
        {
         vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        }


     public void startVibration()
        {
         // vibration pattern
         long pattern[] = {60, 120, 180, 240, 300, 360, 420, 480};

         vibrator.vibrate(pattern, 1);
        }


     public void stopVibration()
        {
         vibrator.cancel();
        }
    }

声音管理器:

package it.mypackage;

import android.content.Context;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.util.Log;

public class SoundManager
    {
     private static SoundManager soundManagerInstance = null;
     private MediaPlayer mediaPlayer;


     public static SoundManager getInstance(Context context)
        {
         // Use the application context, which will ensure that you
         // don't accidentally leak an Activity's context.
         if(soundManagerInstance == null)
            {
             soundManagerInstance = new SoundManager(context.getApplicationContext());
            }

         return soundManagerInstance;
        }


     // Constructor
     private SoundManager(Context context)
        {
         Uri ringtoneUri = getAlarmUri();
         mediaPlayer = MediaPlayer.create(context, ringtoneUri);
        }


     public void playSound()
        {
         Log.d("INFOMESSAGE", "PLAY METHOD CALLED");

         // Play an alarm ringtone
         if(mediaPlayer != null)
            {
             mediaPlayer.setLooping(true);
             mediaPlayer.start();
            }
        }


     public void stopSound()
        {
         if(mediaPlayer != null && mediaPlayer.isPlaying())
            {
             mediaPlayer.stop();
            }
        }


     //Get an alarm sound. Try for an alarm. If none set, try notification, otherwise, ringtone.
     private Uri getAlarmUri()
        {
         Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);

         if(alert == null)
            {
             alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

             if(alert == null)
                {
                 alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
                }
            }

         return alert;
        }
    }

清单中的权限:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

感谢您的帮助。

【问题讨论】:

    标签: android audio android-mediaplayer


    【解决方案1】:

    现在它可以工作了,我以这种方式修改了 SoundManager 类:我在 playSound() 方法中初始化 mediaPlayer,并在 stopSound() 方法中释放它。

    package it.mypackage;
    
    import android.content.Context;
    import android.media.MediaPlayer;
    import android.media.RingtoneManager;
    import android.net.Uri;
    import android.util.Log;
    
    public class SoundManager
        {
         private static SoundManager soundManagerInstance = null;
         private MediaPlayer mediaPlayer;
         private Context context;
    
    
         public static SoundManager getInstance(Context context)
            {
             // Use the application context, which will ensure that you
             // don't accidentally leak an Activity's context.
             if(soundManagerInstance == null)
                {
                 soundManagerInstance = new SoundManager(context.getApplicationContext());
                }
    
             return soundManagerInstance;
            }
    
    
         // Constructor
         private SoundManager(Context context)
            {
             this.context = context;
            }
    
    
         public void playSound()
            {
             Uri ringtoneUri = getAlarmUri();
             mediaPlayer = MediaPlayer.create(context, ringtoneUri);
    
             // Play an alarm ringtone
             if(mediaPlayer != null)
                {
                 Log.d("INFOMESSAGE", "MediaPlayer playing.");
    
                 mediaPlayer.setLooping(true);
                 mediaPlayer.start();
                }
            }
    
    
         public void stopSound()
            {
             if(mediaPlayer != null && mediaPlayer.isPlaying())
                {
                 mediaPlayer.stop();
    
                 mediaPlayer.release();
                 mediaPlayer = null;
                }
            }
    
    
         // Get an alarm sound. Try for an alarm. If none set, try notification, otherwise, ringtone.
         private Uri getAlarmUri()
            {
             Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
    
             if(alert == null)
                {
                 alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    
                 if(alert == null)
                    {
                     alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
                    }
                }
    
             return alert;
            }
        }
    

    【讨论】:

      【解决方案2】:

      在 stop() 之后,你应该再次准备下一个播放声音。此外,playSound 应该移到 onResume 而不是 onCreate。如果可能,不要忘记在使用后释放 MediaPlayer。

      public void stopSound()
      {
          if(mediaPlayer != null && mediaPlayer.isPlaying())
          {
              mediaPlayer.stop();
              try {
                  mediaPlayer.prepare();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      

      注意:第一个 prepare() 会在 MediaPlayer.create() 中自动调用。

      【讨论】:

      • 嗨@You Kim,感谢您的帮助!我找到了下面发布的解决方案,从性能/资源消耗的角度来看,您认为哪一个更好?
      • 您的解决方案 +1。
      【解决方案3】:

      我建议初始化一次mediaPlayer

      if(mediaPlayer == null) 
      {
          mediaPlayer = MediaPlayer.create(context, ringtoneUri);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多