【问题标题】:Is it good practice or necessary to use a Service to use a Media Player in the backgound使用服务在后台使用媒体播放器是好的做法还是有必要?
【发布时间】:2019-07-30 21:25:50
【问题描述】:

您好 StackOverflow 的用户, 我正在为安卓开发一个音乐播放器应用程序。在我的主要活动中,当用户单击一首歌曲时,我会启动一个显示 PlayerActivity 的新意图。在那里,我初始化了一个 MediaPlayer 和所有其他 UI 元素。当用户单击后退按钮时,我将他们带回主活动,歌曲继续在后台播放。如果他们退出应用程序,也会发生同样的事情。现在我想知道做这样的事情是否可以,或者我是否应该从 PlayerActivity 类为 MediaPlayer 启动一个新服务,而不是在那里做。

玩家活动:

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

    Bundle extras = getIntent().getExtras();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
        getWindow().setNavigationBarColor(getResources().getColor(R.color.colorPrimaryDark));
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        getWindow().setNavigationBarDividerColor(getResources().getColor(R.color.white));
    }

    playBtn = findViewById(R.id.btn_play);
    artImage = findViewById(R.id.art);
    remainingTimeLabel = findViewById(R.id.current_song_duration);
    totalTimeLabel = findViewById(R.id.total_duration);
    manager = MainActivity.getManager();

    Song song = manager.getCurrentSong();

    boolean wasCall = extras != null && extras.containsKey("call");
    if (!wasCall && manager.hasStarted()) {
        MediaPlayer mediaPlayer = manager.getMediaPlayer();
        mediaPlayer.pause();
        mediaPlayer.stop();
    }


    if (!wasCall) {
        mp = MediaPlayer.create(this, Uri.parse(song.getPath()));
        mp.setLooping(true);
        mp.seekTo(0);
        mp.setVolume(0.5f, 0.5f);
    } else {
        mp = manager.getMediaPlayer();
        mp.setLooping(true);
        mp.setVolume(0.5f, 0.5f);
    }

    totalTime = mp.getDuration();
    artImage.setImageBitmap(Bitmap.createScaledBitmap(song.getIcon(), 250, 250, true));

    totalTimeLabel.setText(createTimeLabel(totalTime));

    songName = findViewById(R.id.songName);
    songName.setText(song.getName());

    songAuthor = findViewById(R.id.songAuthor);
    songAuthor.setText(song.getArtist());

    Toolbar toolbar = findViewById(R.id.player_top_bar);
    toolbar.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
    setSupportActionBar(toolbar);

    assert getSupportActionBar() != null;
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    assert toolbar.getNavigationIcon() != null;
    toolbar.getNavigationIcon().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
    getSupportActionBar().setTitle(Html.fromHtml("<font color='#ffffff'>MySound</font>"));

    positionBar =  findViewById(R.id.seek_song_progressbar);
    positionBar.setMax(totalTime);
    positionBar.setOnSeekBarChangeListener(
            new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    if (fromUser) {
                        mp.seekTo(progress);

                        positionBar.setProgress(progress);
                    }
                }

                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {

                }

                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {

                }
            }
    );

    LinearLayout layout = findViewById(R.id.player_control);
    layout.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));

    new Thread(() -> {
        while (mp != null) {
            try {
                Message msg = new Message();
                msg.what = mp.getCurrentPosition();
                handler.sendMessage(msg);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();

    this.action = SongEndAction.REPEAT;

    mp.start();
    manager.setMediaPlayer(mp);
}

【问题讨论】:

  • 播放音乐是一项后台任务,因此您最好使用后台服务(Activity 应该处理 UI 事件而不是播放背景音乐)

标签: java android android-mediaplayer


【解决方案1】:

这是我在书中实现的音乐服务。 https://github.com/Wickapps/Practical-Android-MusicService 此实现包括播放、停止和向前搜索,但您可以添加其他功能。 服务是未来可扩展性的最佳架构。 有一个启动服务的 MainActivity.java。 MusicService.java 是服务实现。 希望这会有所帮助。

【讨论】:

  • 您是否建议我将我的 PlayerActivity 实例解析到服务并从服务中更改可绘制对象,或者只保留音乐播放器功能并从 PlayerActivity 更新可绘制对象?
  • 听起来你最好从活动中管理播放列表和可绘制对象(我假设你的意思是与正在播放的内容相关的图像),因为它可以更新 UI。
  • 由于某种原因,永远不会调用 onCreate。
  • 如果我把你的代码放在主类中它可以工作,但如果我把它放在 PlayerAtcivity 类中它不会
  • 嗯,不确定,您应该能够将服务绑定到任何活动。最好仔细检查您的 AndroidManifest 并确保已定义所有 Activity 和 Service。
【解决方案2】:

如果您希望您的应用在后台继续播放音频(例如 spotify),那么是的,必须使用前台服务。

不幸的是,它比您当前的实现更复杂。

这是一个不错的起点:https://developer.android.com/guide/topics/media-apps/audio-app/building-an-audio-app

【讨论】:

    猜你喜欢
    • 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
    相关资源
    最近更新 更多