Android:在service和activity之中,实现音乐播放进度条传递信息的两种方式,MediaPlayer做音乐播放器采坑以及解决办法

26 篇文章 1 订阅
15 篇文章 0 订阅

实现播放时的进度条显示,或是定时从service获取某些信息,是我们日常开发中经常遇到的需求,下面介绍当音乐再service中运行时,activity如果获取音乐进度信息的两种方式:

一、在activity中建立消息接收机制

我们需要在activity中建立一个用于接收信息的handler(handler简单的说是在android中可以发送消息和也可以处理消息的一种机制,当然它的用途更加强大,有时间可以去自己了解)

我们需要在onCreate方法之前添加handler,这样才能保证当我们的activity被destroy之后,再重建时可以第一时间获取当前音乐的进度。

下面是代码,有的同学可能看出来了,这个Handler的handleMessage被重写了,handleMessage写在了new Handler.Callback()回调函数中,返回值变成了boolean,其实这样做是为了防止内存泄漏,当然如果你能忍受Android Studio那一坨巨大的黄色警告你也可以选择用原本的handler方法,

	//当前音乐播放进度
    private static TextView nowTime;
	//音乐进度条
    static SeekBar songseek;
    
    //运用Handler中的handleMessage方法接收service传递的音乐播放进度信息
    public static Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            // super.handleMessage(msg);
            // 将SeekBar位置设置到当前播放位置,
            // msg.arg1是service传过来的音乐播放进度信息,将其设置为进度条进度
            songseek.setProgress(msg.arg1);
            //将进度时间其转为mm:ss时间格式
            nowTime.setText(new SimpleDateFormat("mm:ss",Locale.getDefault()).format(new Date(msg.arg1)));
            return false;
        }
    });

	//下面才是android的onCreate方法
	protected void onCreate(Bundle savedInstanceState) {
		......
	}

二、在service中建立一个定时器来定时发送音乐进度信息

		//开始播放音乐
       	mediaPlayer.start();
      	//每隔50毫秒发送音乐进度
      	Timer timer = new Timer();
       	timer.schedule(new TimerTask() {
        	@Override
       		public void run() {
       			//实例化一个Message对象
				Message msg = Message.obtain();
				//Message对象的arg1参数携带音乐当前播放进度信息,类型是int
            	msg.arg1 = mediaPlayer.getCurrentPosition();
            	//使用MainActivity中的handler发送信息
            	MainActivity.handler.sendMessage(msg);
       		}
        }, 0, 50);

当然你也可以使用线程的方式来发现音乐进度信息,不过在这里并不推荐,因为单纯的音乐播放进度信息而已,没有必要用到线程来传信息,而已每一次执行都会创建一个线程,这样很浪费资源

		//创建一个线程每隔100毫秒发送一次信息
        Runnable runnable = new Runnable() {
		@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Message msg = Message.obtain();
                    msg.arg1 = mediaPlayer.getCurrentPosition();
                    MainActivity.handler.sendMessage(msg);
                    }
                 }
            };
        Thread musicThread = new Thread(runnable);
        musicThread.start();

附:MediaPlayer做音乐播放器采坑以及解决办法

1.千万不要把mediaPlayer.getDuration()放在定时任务里,线程和定时器都不能放

因为mediaPlayer.prepare()的执行速度很低,有概率出现mediaPlayer.prepare()还在执行中,突然定时器里刚刚好到时间该调用mediaPlayer.getDuration()这个方法,结果就是mediaPlayer.prepare()因为没有初始化成功就调用mediaPlayer.getDuration()而报下面的错误导致程序闪退。

java.lang.IllegalStateException android.media.MediaPlayer._prepare(Native Method)
(当然如果你的定时操作间隔越大出错的概率就越小,不过我强迫症就是忍不了)

2.上面提到mediaPlayer.prepare()的执行速度很低,如何解决

使用mediaPlayer.prepare()时,正常操作是:

	mediaPlayer.prepare();
	mediaPlayer.start();

建议使用 mediaPlayer.prepareAsync()来代替mediaPlayer.prepare(),下面的代码可以取代上面

	mediaPlayer.prepareAsync();
	//需要设置一个监听器
	mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
		@Override
		public void onPrepared(MediaPlayer mp) {
			mediaPlayer.start();
		}
	});

看一下效果

Android作业 音乐播放器

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是一个简单的示例,演示如何使用服务来播放音乐并在活动中显示进度。在这个示例中,我们使用MediaPlayer类来播放音乐,使用Handler类来更新UI元素。 1. 创建一个名为MusicService的服务类。 ```java public class MusicService extends Service implements MediaPlayer.OnCompletionListener { private MediaPlayer mediaPlayer; private Handler mHandler = new Handler(); @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); mediaPlayer = MediaPlayer.create(this, R.raw.music); mediaPlayer.setOnCompletionListener(this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { mediaPlayer.start(); return START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); mediaPlayer.release(); } @Override public void onCompletion(MediaPlayer mp) { stopSelf(); } public int getDuration() { return mediaPlayer.getDuration(); } public int getCurrentPosition() { return mediaPlayer.getCurrentPosition(); } public void seekTo(int position) { mediaPlayer.seekTo(position); } } ``` 2. 在Activity中启动服务并绑定它。 ```java public class MainActivity extends AppCompatActivity { private MusicService musicService; private boolean isBound = false; private SeekBar seekBar; private TextView currentTimeTextView; private TextView durationTextView; private Runnable mRunnable = new Runnable() { @Override public void run() { if (isBound) { int currentPosition = musicService.getCurrentPosition(); seekBar.setProgress(currentPosition); String currentTime = millisecondsToString(currentPosition); currentTimeTextView.setText(currentTime); mHandler.postDelayed(this, 1000); } } }; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { MusicService.LocalBinder binder = (MusicService.LocalBinder) service; musicService = binder.getService(); isBound = true; int duration = musicService.getDuration(); seekBar.setMax(duration); String durationString = millisecondsToString(duration); durationTextView.setText(durationString); mHandler.postDelayed(mRunnable, 1000); } @Override public void onServiceDisconnected(ComponentName name) { isBound = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); seekBar = findViewById(R.id.seekBar); currentTimeTextView = findViewById(R.id.currentTimeTextView); durationTextView = findViewById(R.id.durationTextView); Intent intent = new Intent(this, MusicService.class); startService(intent); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mServiceConnection); } private String millisecondsToString(int milliseconds) { int seconds = milliseconds / 1000; int minutes = seconds / 60; seconds = seconds % 60; return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); } } ``` 3. 在Activity的布局文件中添加一个SeekBar和两个TextView,用于显示音乐进度。 ```xml <SeekBar android:id="@+id/seekBar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/currentTimeTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <TextView android:id="@+id/durationTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" /> </LinearLayout> ``` 这个例子中,我们使用服务来播放音乐,并在Activity中显示进度。我们还使用Handler来定期更新UI元素。当Activity被销毁时,我们解除服务的绑定。 ### 回答2: 要使用service实现音乐播放并在activity中显示进度,首先需要创建一个service来处理音乐播放的逻辑。下面是实现该功能的步骤: 1. 创建一个MusicService的类,继承自Service,并实现音乐播放的逻辑。在其中实例化一个MediaPlayer对象,用于控制音乐播放、暂停等操作。 2. 在MusicService中,定义一个Binder内部类,继承自Binder,并实现获取MusicService实例的方法,以便在activity中进行绑定和获取MusicService对象。 3. 在MusicService中,添加一个方法用于获取音乐播放进度(例如getCurrentPosition()),并定义一个Handler对象,用于更新进度数据。 4. 在MusicService的onStartCommand()方法中,开始播放音乐,并使用Handler定时更新进度数据。 5. 在activity中,创建一个MediaPlayer对象和一个ServiceConnection对象,用于绑定MusicService。 6. 在activity中,实现ServiceConnection接口的方法,在其中获取MusicService对象,并调用MusicService的方法获取音乐进度。 7. 在activity中,使用一个TextView来显示音乐进度,通过Handler不断更新TextView的文本。 8. 在activity的onStart()方法中,使用bindService()方法绑定MusicService,并传入ServiceConnection对象。 9. 在activity的onStop()方法中,使用unbindService()方法解绑MusicService。 通过以上步骤实现的代码逻辑,可以实现activity中显示音乐播放进度。通过绑定MusicService,我们可以获取到音乐播放进度,并在activity中动态更新显示。同时,使用Handler定时获取进度数据,保证了进度的准确性和实时性。 ### 回答3: 要实现Activity中显示音乐播放进度,可以使用Service来管理音乐播放,并通过与Activity进行通信来更新进度。 首先,在Activity中创建一个ServiceConnection,用于与Service进行绑定和通信。在Activity的onCreate方法中,通过bindService方法绑定Service,并将ServiceConnection传入,以便进行通信。 在Service中,创建一个MediaPlayer对象用于播放音乐。在Service的onCreate方法中,初始化MediaPlayer对象并设置音乐文件等参数。在Service的onStartCommand方法中,启动MediaPlayer对象并开始播放音乐。 为了让Activity能够获取到音乐播放进度,我们可以在Service中创建一个Handler对象,并在MediaPlayer的onPrepared方法中使用该Handler对象发送消息,将当前音乐播放进度发送给Activity。 在Activity中,创建一个Handler对象,并重写Handler的handleMessage方法,在handleMessage方法中获取到音乐播放进度,并更新到UI界面上的进度条或其他控件。 通过ServiceConnection的onServiceConnected方法,在ActivityService成功绑定后,可以通过Binder对象提供的方法获取到Service中的Handler对象,并将Activity中的Handler对象传递Service中的Handler对象。 在Service中,通过Activity传递的Handler对象,将音乐播放进度发送到Activity中。在Activity中的Handler对象中,通过接收到的消息更新UI界面上的进度。 通过上述步骤,就可以实现Activity中显示音乐播放进度了。使用Service来管理音乐播放可以使音乐在后台不被打断,并且可以与其他组件进行通信,方便控制音乐播放、暂停等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值