什么是前台服务
前台服务是那些被认为用户知道(用户认可所认可)且在系统内存不足的时候不允许系统杀死的服务。前台服务必须给状态栏提供一个通知,它被放到正在运行(Ongoing)标题之下——这就意味着通知只有在这个服务被终止或从前台主动移除通知后才能被解除
1.正式使用
使用notification
在service的onStartCommand的方法中
//实例化通知栏构造器NotificationCompat.Builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// 设置通知的基本信息:icon、标题、内容
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("安全管控系统更新啦!");
builder.setContentText("正在现场检查中~~");
builder.setAutoCancel(true);//点击消息通知前台服务消失
// // 设置通知的点击行为:这里启动一个 Activity
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
//获取状态通知栏管理类实例
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// 发送通知 id 需要在应用内唯一
notificationManager.notify(NOTIFICATION_ID, builder.build());
更新通知
要想更新通知,需要利用NotificationManager.notify()
的id参数,该id在应用内需要唯一。要想更新特定id的通知,只需要创建新的Notification,并发出与之前所用 id 相同的 Notification。如果之前的通知仍然可见,则系统会根据新的 Notification 对象的内容更新该通知。相反,如果之前的通知已被清除,系统则会创建一个新通知。
删除通知
删除通知可以有多种方式:
1.通过NotificationCompat.Builder
设置setAutoCancel(true)
,这样当用户点击通知后,通知自动删除。
2.通过NotificationManager.cancel(id)
方法,删除指定 id 的通知
3.通过 NotificationManager.cancelAll()
方法,删除该应用的所有通知
自定义通知
- 自定义Notification布局
有时候我们需要个性化前台服务的通知内容,那么我么就需要通过自定义Notification布局的方式来达到想要的效果:
RemoteViews remoteViews = new RemoteViews(this.getPackageName(),
R.layout.notification_layout);// 获取remoteViews(参数一:包名;参数二:布局资源)
builder = new Notification.Builder(this.getApplicationContext())
.setContent(remoteViews);// 设置自定义的Notification内容
builder.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher);
Notification notification = builder.getNotification();// 获取构建好的通知--.build()最低要求在
// API16及以上版本上使用,低版本上可以使用.getNotification()。
Notificationnotification.defaults = Notification.DEFAULT_SOUND;//设置为默认的声音
startForeground(110, notification);// 开始前台服务
RemoteViews remoteViews = new RemoteViews(this.getPackageName(),
R.layout.notification_layout);// 获取remoteViews(参数一:包名;参数二:布局资源)
builder = new Notification.Builder(this.getApplicationContext())
.setContent(remoteViews);// 设置自定义的Notification内容
builder.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher);
Notification notification = builder.getNotification();// 获取构建好的通知--.build()最低要求在
// API16及以上版本上使用,低版本上可以使用.getNotification()。
Notificationnotification.defaults = Notification.DEFAULT_SOUND;//设置为默认的声音
startForeground(110, notification);// 开始前台服务
- 为自定义通知内容上的控件绑定点击事件
在通知(Notification)中为自定义布局上的控件绑定点击事件监听,我们需要通广播的形式来实现效果。 - 注册广播
private static final int REQUEST_CODE = 100;
private static final String ACTION_PLAY = "play";
Intent intentPlay = new Intent(ACTION_PLAY);// 指定操作意图--设置对应的行为ACTION
PendingIntent pIntentPlay = PendingIntent.getBroadcast(this.getApplicationContext(),
REQUEST_CODE, intentPlay, PendingIntent.FLAG_UPDATE_CURRENT);// 取的一个PendingIntent,
// 它会发送一个广播,如同Context.sendBroadcast.
private static final int REQUEST_CODE = 100;
private static final String ACTION_PLAY = "play";
Intent intentPlay = new Intent(ACTION_PLAY);// 指定操作意图--设置对应的行为ACTION
PendingIntent pIntentPlay = PendingIntent.getBroadcast(this.getApplicationContext(),
REQUEST_CODE, intentPlay, PendingIntent.FLAG_UPDATE_CURRENT);// 取的一个PendingIntent,
// 它会发送一个广播,如同Context.sendBroadcast.
- 绑定点击事件
remoteViews.setOnClickPendingIntent(R.id.iv_pause, pIntentPlay);// 绑定点击事件(参数一:
// 控件id;参数二:对应触发的PendingIntent)
remoteViews.setOnClickPendingIntent(R.id.iv_pause, pIntentPlay);// 绑定点击事件(参数一:
// 控件id;参数二:对应触发的PendingIntent)
- 注册广播监听器,监听对应广播
- 动态注册
- 在Service的onCreate中添加如下代码注册广播监听:
// 动态注册广播
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate()");
playerReceiver = new PlayerReceiver();
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(ACTION_PLAY);
mFilter.addAction(ACTION_PAUSE);
mFilter.addAction(ACTION_LAST);
mFilter.addAction(ACTION_NEXT);
registerReceiver(playerReceiver, mFilter);
}
// 动态注册广播
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate()");
playerReceiver = new PlayerReceiver();
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(ACTION_PLAY);
mFilter.addAction(ACTION_PAUSE);
mFilter.addAction(ACTION_LAST);
mFilter.addAction(ACTION_NEXT);
registerReceiver(playerReceiver, mFilter);
}
- 在Service销毁时(OnDestory中)解除广播注册:
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
stopForeground(true);// 停止前台服务
if (playerReceiver != null)
unregisterReceiver(playerReceiver);// 解除广播注册
super.onDestroy();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
stopForeground(true);// 停止前台服务
if (playerReceiver != null)
unregisterReceiver(playerReceiver);// 解除广播注册
super.onDestroy();
}
- 静态注册
在AndroidManifest.xml的receiver标签内添加需要过滤的内容,如:
<receiver
android:name=".PlayerReceiver"
android:exported="true">
<intent-filter>
<action android:name="play"/>
<action android:name="pause"/>
<action android:name="last"/>
<action android:name="next"/>
</intent-filter>
</receiver>
- BroadcastReceiver代码如下:
public class PlayerReceiver extends BroadcastReceiver {
private static final String TAG = PlayerReceiver.class.getSimpleName();
public PlayerReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
String action = intent.getAction();// 获取对应Action
Log.d(TAG,"action:"+action);
if(action.equals(MusicPlayerService.ACTION_PLAY)){
// 进行对应操作
} else if(action.equals(MusicPlayerService.ACTION_PAUSE)){
} else if(action.equals(MusicPlayerService.ACTION_LAST)){
} else if(action.equals(MusicPlayerService.ACTION_NEXT)){
}
}
}
public class PlayerReceiver extends BroadcastReceiver {
private static final String TAG = PlayerReceiver.class.getSimpleName();
public PlayerReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
String action = intent.getAction();// 获取对应Action
Log.d(TAG,"action:"+action);
if(action.equals(MusicPlayerService.ACTION_PLAY)){
// 进行对应操作
} else if(action.equals(MusicPlayerService.ACTION_PAUSE)){
} else if(action.equals(MusicPlayerService.ACTION_LAST)){
} else if(action.equals(MusicPlayerService.ACTION_NEXT)){
}
}
}
点击后监听到的动作.png
1.建立对应的Intent(意图)--即指定对应操作的行为Action;2.PendingIntent来处理意图,(Pending译为“待定的”、“延迟”,PendingIntent类提供了一种创建可由其它应用程序在稍晚时间触发的Intent的机制
3.通过RemoteViews.setOnClickPendingIntent(int viewId,PendingIntent pendingIntent)方法来为指定的控件绑定对应的意图;
4.在Service中注册广播,监听对应操作。
修改自定义通知(Notification)上的显示内容
在自定义通知布局后,我们在有些场景下需要修改一些控件的显示内容(如修改TextView
显示文字、ImageView
图片、ProgressBar
进度等),那么我们可以通过如Notification.contentView
的setTextViewText、setImageViewBitmap、setProgressBar
等方法打成效果,示例代码如下:
notification.contentView.setTextViewText(R.id.title_tv, "标题");
notification.contentView.setTextViewText(R.id.title_tv, "标题");
注:方法的差异不大,都需要传递控件的id,需要设置的内容、属性等参数。