音乐播放程序有Activity、Service构成,音乐播放在Service中完成。
现象1:在后台播放在线音乐时,前台程序快速滑动Listview,此时前台程序cpu占有率可达60%-80%,后台音乐播放程序cpu占有率1%-3%,但出现严重卡顿现象;
现象2:音乐播放程序在前台,在Service中播放在线音乐,在Activity中快速滑动Listview,此时音乐播放程序cpu占有率60%-80%,但播放没有卡顿现象;
上述现象是在Android 2.3版本上测试;
二、问题分析:
先看一下Android系统里面定义的进程优先级:
1.前台进程( FOREGROUND_APP)
2.可视进程(VISIBLE_APP )
3.次要服务进程(SECONDARY_SERVER )
4.后台进程 (HIDDEN_APP)
5.内容供应节点(CONTENT_PROVIDER)
6.空进程(EMPTY_APP)
Android系统会根据这个优先级分配资源,如:内存、cpu等,大家知道的应用程序在系统内存不足时呗系统kill掉就是根据这个优先级做的。
当音乐程序退到后台之后其进程优先级降低,在系统cpu资料不足时,会降低音乐程序的cpu占有率,此时会出现卡顿问题;
三、解决办法:
将不可见的进程(我程序中因为包含Service,因此处于3级)提高到可见进程(发通知到通知栏),即2级;
具体做法在Service的onCreate方法中调用improvePriority:
private void improvePriority() { NotificationManager mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 我们并不需要为 notification.flags 设置 FLAG_ONGOING_EVENT,因为 // 前台服务的 notification.flags 总是默认包含了那个标志位 Notification notification = new Notification(R.drawable.ic_launcher, "Foreground Service Started.", System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, PlayMusicService.class), 0); notification.setLatestEventInfo(this, "Foreground Service", "Foreground Service Started.", contentIntent); // 注意使用 startForeground ,id 为 0 将不会显示 notification startForeground(1, notification); }
注意在Service的onDestroy中调用:
stopForeground(true);
一般情况不需要显示通知图标,因此注意startForeground的第一个参数;
上述发通知的方法已过时,不建议使用,用下面方面,原理不变:
private void improvePriority() { PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, CenterService.class), 0); Notification notification = new Notification.Builder(this) .setContentTitle("Foreground Service") .setContentText("Foreground Service Started.") .setSmallIcon(R.drawable.ic_launcher).setLargeIcon(null) .build(); notification.contentIntent = contentIntent; startForeground(1, notification); }