本文主要想说一下android项目开发中经常会使用到通知机制中的通知栏框架(Notificaiton)。通知栏位于设备的顶层,可以展开的通知列表。通知栏的主要作用大概可以分为三大块:
/***
* NotificationManager类的实例化
* @param context
* @return
*/
public static NotificationManager from(Context context) {
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
/**
* 通知的发布
* @param id
* @param notification
*/
public void notify(int id, Notification notification) {
notify(null, id, notification);
}
/**
* 通知的发布 (含标签)
* @param tag
* @param id
* @param notification
*/
public void notify(String tag, int id, Notification notification) {
notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId()));
}
/**
* 之前发布通知的取消
* @param id
*/
public void cancel(int id) {
cancel(null, id);
}
/**
* 之前发布通知的取消 (含标签)
* @param tag
* @param id
*/
public void cancel(String tag, int id) {
cancelAsUser(tag, id, new UserHandle(UserHandle.myUserId()));
}
/**
* 之前发布通知的取消 (所有当前 应用所发布的通知)
*/
public void cancelAll() {
INotificationManager service = getService();
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
try {
service.cancelAllNotifications(pkg, UserHandle.myUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Notification
具体的状态栏通知对象,它是一个序列化的庞大的类,可以设置icon、文字、提示声音、振动等等参数。
给Notification设置PendingIntent
PendingIntent
点击通知栏中的某个View想跳转一个Activity或者开启一个service时,可以通过设置PendingIntent完成。
PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用),即便创建该PendingIntent对象的进程被杀死了,这个PendingItent对象在其他进程中还是可用的,比如闹钟功能就用到了 PendingIntent。它的获取方式主要有:
//方式一:获取一个用于启动 Activity 的 PendingIntent 对象
public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags);
//方式二: 获取一个用于启动 Service 的 PendingIntent 对象
public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags);
//方式三: 获取一个用于向 BroadcastReceiver 广播的 PendingIntent 对象
public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
PendingIntent 几种重要的flag标志:
1) FLAG_CANCEL_CURRENT
当前系统中已经存在一个相同的 PendingIntent 对象时,先将已有的 PendingIntent 取消,然后重新生成一个 PendingIntent 对象。
2) FLAG_NO_CREATE
当前系统中不存在相同的 PendingIntent 对象时,将不会创建该 PendingIntent 对象而是直接返回 null 。
3)FLAG_ONE_SHOT
该 PendingIntent 只作用一次。
4)FLAG_UPDATE_CURRENT
系统中已存在该 PendingIntent 对象时,那么系统将保留该 PendingIntent 对象,但是会使用新的 Intent 来更新之前 PendingIntent 中的 Intent 对象数据,例如更新 Intent 中的 Extras 。
Android系统使用RemoteViews来自定义通知。视图通知高度限制为64dp,大视图通知高度限制为256dp。同时,建议自定义通知尽量简单,以提高兼容性。 自定义通知需要做如下操作:
自定义通知栏的布局 layout_float_window.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="@+id/fl_window_layout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#f4f2f3"
android:paddingLeft="@dimen/margin_20"
android:paddingRight="@dimen/margin_20">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_vertical"
android:background="@drawable/ic_microphone_white" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="70dp"
android:layout_marginRight="50dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="0sp"
android:text="咪咕家语音播报"
android:textColor="#282e33"
android:textSize="17sp" />
<TextView
android:id="@+id/percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:lineSpacingExtra="0sp"
android:text="IM消息"
android:textColor="#66737f"
android:textSize="14sp" />
LinearLayout>
<ImageView
android:id="@+id/iv_close_notify"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical|right"
android:scaleType="center"
android:src="@drawable/ic_close_grey1" />
FrameLayout>
通知栏创建的关键代码
@SuppressLint("NewApi")
private void createNotification() {
remoteViews = new RemoteViews(getPackageName(), R.layout.layout_float_window);//通知栏布局
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
// 点击跳转到播报界面
if (mMessenger != null) {
Intent intent_main = new Intent(this, VoiceBroadcastActivity.class);
PendingIntent pending_intent_go = PendingIntent.getActivity(this, 1, intent_main, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.fl_window_layout, pending_intent_go);
}
//关闭播报
Intent intent_cancel = new Intent();
intent_cancel.setAction(BroadcastConstants.ACTION_CLOSE);
PendingIntent pending_intent_close = PendingIntent.getBroadcast(this, 2, intent_cancel, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.iv_close_notify, pending_intent_close);
mBuilder.setSmallIcon(R.drawable.ic_close_grey1); // 设置顶部图标(状态栏)
mBuilder.setContent(remoteViews);
mBuilder.setOngoing(true);
mNotificationManager.notify(BroadcastConstants.NOTIFICATION_CEDE, mBuilder.build());
}