简体   繁体   中英

Android MediaPlayer not playing sound

in my Android app I want vibration and sound playing when a specific Activity is shown. I created two VibrationManager and SoundManager singleton classes, and I start vibration and sound in the "onCreate" method of the Activity. The Activity has got a button that stops vibration and sound, and closes the Activity, when clicked. All seems to work, except for the sound, that is not played, even if the "playSound()" method is entered. Further, sometimes the sound is played instead, apparently with random logic... What's wrong with my code for the sound?

MyActivity:

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();
        }
    }

VibrationManager:

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();
        }
    }

SoundManager:

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;
        }
    }

Permissions in manifest:

    <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"/>

Thanks for help.

Now it works, I modified the SoundManager class in this way: I initialize mediaPlayer in the playSound() method, and I release it in the stopSound() method.

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;
        }
    }

After stop(), you should prepare again for next playing sound. Also, playSound should be moved to onResume not onCreate. If possible, don't forget to release MediaPlayer after use.

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

Note : The first prepare() is called automatically in MediaPlayer.create().

I suggest to initialise mediaPlayer once:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM