带有实时音频流的 Android 背景音频

标签 android audio android-service

在过去的三天里,我的第一个 Android 应用取得了长足的进步。这是我最后的障碍。如何让我的应用程序运行允许音频继续播放的后台服务?我尝试了几个我能找到的示例,但它们是基于播放本地(或流式传输)mp3 文件而不是实时 (Icecast) mp3 流。

这是我目前的代码,除背景音频外一切正常。

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private ImageButton btn;
    private ImageView img;
    private boolean playPause;
    private MediaPlayer mediaPlayer;

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

        btn = findViewById(R.id.playPause);
        img = findViewById(R.id.radioTower);

        mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            public boolean onError(MediaPlayer mp, int what, int extra) {
                mp.reset();
                return false;
            }
        });
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            public void onPrepared(MediaPlayer mp) {
                //mp.start();
            }
        });
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!playPause) {
                    if(!mediaPlayer.isPlaying()) {
                        mediaPlayer.start();
                        btn.setBackgroundResource(R.drawable.ic_rounded_pause_button);
                        img.setImageResource(R.drawable.ic_toweron);
                        img.setAlpha(1.0f);
                        playPause = true;
                    }
                } else {
                    if(mediaPlayer.isPlaying()) {
                        mediaPlayer.pause();
                        btn.setBackgroundResource(R.drawable.ic_play_button);
                        img.setImageResource(R.drawable.ic_toweroff);
                        img.setAlpha(0.3f);
                        playPause = false;
                    }
                }
            }
        });

        try {
            mediaPlayer.setDataSource("http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio2_mf_p");
            mediaPlayer.prepareAsync();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

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

        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

如有任何帮助,我们将不胜感激。

最佳答案

使用服务播放音频文件的即时 Activity 。 这是如何在服务中使用媒体播放器的简单代码。

public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener {

    //region "member variable"
    boolean isServiceRunning = false;
    ArrayList<Song> PlayerList = new ArrayList<>();
    MediaPlayer mediaPlayer;
    int position = 0;
    MainActivity mainActivity;
    private final IBinder mBinder = new LocalBinder();
    int playingMood;
    private final static int MAX_VOLUME = 15;
    Toast toast;
    public static MusicService objService;
    //endregion

    //region "service method"


    @Override
    public void onCreate() {
        objService = this;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            isServiceRunning = true;

            if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
//                showNotification(false);
            } else if (intent.getAction().equals(Constants.ACTION.PREV_ACTION)) {
                playPrevious();
            } else if (intent.getAction().equals(Constants.ACTION.PLAY_ACTION)) {
                play();

            } else if (intent.getAction().equals(Constants.ACTION.NEXT_ACTION)) {
                playNext();
            } else if (intent.getAction().equals(
                    Constants.ACTION.STOPFOREGROUND_ACTION)) {
                stop();
                stopForeground(true);
                stopSelf();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isServiceRunning = false;
        objService = null;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }


    //returns the instance of the service
    public class LocalBinder extends Binder {
        public MusicService getServiceInstance() {
            return MusicService.this;
        }
    }

    public void registerClient(MainActivity activity) {
        mainActivity = activity;
    }
    //endregion


    //region "Media player"

    public void SongRequest() {
        try {
            if (mediaPlayer != null) {
                mediaPlayer.release();
                mediaPlayer = null;
            }

            //Handel UI on main activity
            mainActivity.showPlayer();
            mediaPlayer = new MediaPlayer();
            mainActivity.updatePlayerUI();
            prepareMediaPlayer(PlayerList.get(position).getUrl());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    void showToast(String text) {
        if (toast != null)
            toast.cancel();
        toast = Toast.makeText(App.getContext(), text, Toast.LENGTH_LONG);
        toast.show();
    }


    @Override
    public void onPrepared(MediaPlayer mp) {
        // try {
            mediaPlayer.start();
            mainActivity.checkPlaying(true);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        try {
            mainActivity.sentUpdateBroadcast(true);
            if (playingMood == 1) {
                mediaPlayer.start();
            }
            if (playingMood == 2) {
                playNext();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {
        if (mainActivity != null)
            mainActivity.updateProgressBuffer(percent);
        if (percent == 1)
            mainActivity.showPlayer();

    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        try {
            Log.i("MediaPlayer", "error");

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }




    void startPrepare(String url) {

        prepareMediaPlayer(url);

    }



    void prepareMediaPlayer(String url) {
        try {
            mediaPlayer.setDataSource(url);
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setOnPreparedListener(MusicService.this);
            mediaPlayer.setOnErrorListener(MusicService.this);
            mediaPlayer.setOnCompletionListener(MusicService.this);
            mediaPlayer.setOnBufferingUpdateListener(MusicService.this);
            mediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //endregion

    //region "media player method"
    public boolean play() {
        if (mediaPlayer != null) {
            switchButton();
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();

                return false;
            } else {
                mediaPlayer.start();
                return true;
            }
        }

        return false;

    }

    void switchButton() {

        mainActivity.checkPlaying(!mediaPlayer.isPlaying());
    }

    public void stop() {
        try {
            if (mediaPlayer != null) {
                mediaPlayer.release();
                mediaPlayer = null;
            }
            isServiceRunning = false;
            if (mainActivity != null) {
                mainActivity.ShowPlayer(0);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void playNext() {
        if (position < PlayerList.size() - 1) {
            position++;
            mediaPlayer.stop();
            SongRequest();
        }
    }


    public void playPrevious() {
        if (position > 0) {
            position--;
            mediaPlayer.stop();
            SongRequest();
        }
    }


    public void onError() {

    }


    public void onCompletion() {

    }


    public void onCleanMemory() {

    }


    public void initilizePlayerList(ArrayList<Song> list, int position) {
        this.PlayerList = list;
        this.position = position;
    }

    public boolean isplaying() {

        return mediaPlayer == null ? false : mediaPlayer.isPlaying();
    }

    public boolean isRunning() {

        return isServiceRunning;
    }

    public Song getCurrentSong() {
        if (PlayerList != null && PlayerList.size() != 0 && PlayerList.size() >= position) {
            return PlayerList.get(position);
        }
        return null;
    }

    public MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    public void seekTo(int duration) {
        if (mediaPlayer != null) {
            mediaPlayer.seekTo(duration);
        }
    }

    public int getMood() {
        return playingMood;
    }

    public void setMood(int mood) {
        playingMood = mood;
    }

    public void setVolume(int soundVolume) {
        if (mediaPlayer != null) {
            final float volume = (float) (1 - (Math.log(MAX_VOLUME - soundVolume) / Math.log(MAX_VOLUME)));
            mediaPlayer.setVolume(volume, volume);
        }
    }

    //endregion
}

您可以从这样的 Activity 开始您的服务。

   public void startMusicService() {
        Intent serviceIntent = new Intent(MainActivity.this, MusicService.class);
        serviceIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
        startService(serviceIntent);
        bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
    }

停止服务使用此代码

public void stopMusicService() {
    if (service != null) {
        try {
            service.stop();
            unbindService(mConnection);
            stopService(new Intent(MainActivity.this, service.getClass()));
            service = null;
        } catch (IllegalArgumentException ex) {
            stopService(new Intent(MainActivity.this, service.getClass()));
            service = null;
            ex.printStackTrace();
        }
    }
}

对于 Activity 绑定(bind)服务使用这个

private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder _service) {

            MusicService.LocalBinder binder = (MusicService.LocalBinder) _service;
            service = binder.getServiceInstance(); //Get instance of your service!
            service.registerClient(MainActivity.this); //Activity register in the service as client for callabcks!
            if (listHolder != null) {
                initilizeSongsList(listHolder.list, listHolder.position);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {


        }
    };

其中service是activity中的音乐服务对象MusicService服务;

关于带有实时音频流的 Android 背景音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53993541/

相关文章:

java - 在同步块(synchronized block)内使用 wait()

android - 如何在 gitignore 上添加 Manifest.xml 以不推送

csv - 来自音频级别的 ffmpeg txt

audio - 音频信号的数字信号处理

python - 值错误 ("Incomplete wav chunk.") 值错误 : Incomplete wav chunk

安卓模拟器 : How can I get a list of services that are running

android - Firebase Firestore toObject 在 bool 属性映射上失败

java - 如何在用户点击的 TextView 上显示数字?

java - 空对象引用上的 android.content.Context.getSystemService(java.lang.String)'

android - 停止前台行为和通知