PendingIntent

准备工作复习一下PendingIntent,前面的博文《 Android开发笔记(五十)定时器AlarmManager》已经提到了它。PendingIntent意即延迟的Intent,主要用于非立即响应的通信场合。上回的博文,博主介绍了PendingIntent的用法,下面再列出有用到它的场合:
1、用于定时器AlarmManager,处理时刻到达后的提醒动作
2、用于通知推送Notification,处理点击通知后的相应动作
3、用于远程视图RemoteViews,处理远程控件上的点击动作
4、用于发送短信SmsManager,处理短信发送完的后续动作

Notification

Android的消息通知栏放的是APP想即时提醒用户的消息,Notification就是这么一个由APP提供的通知推送内容,每条通知基本都有这些元素:图标、标题、内容、时间等等,它的参数通过建造者模式来构建。下面是Notification.Builder常用的构建参数方法:
setWhen : 设置推送时间,以“小时:分钟”格式显示
setShowWhen : 设置是否显示推送时间
setUsesChronometer : 设置是否显示时间计数。为true时将不显示推送时间,动态显示从通知被推送到当前的时间间隔,以“分钟:秒钟”格式显示
setSmallIcon : 设置状态栏里面的图标(小图标)
setTicker : 设置状态栏里面的提示文本
setLargeIcon : 设置下拉列表里面的图标(大图标)
setContentTitle : 设置下拉列表里面的标题文本
setContentText : 设置下拉列表里面的内容文本
setSubText : 设置下拉列表里面的附加说明文本,位于内容文本下方。若调用该方法,则setProgress的设置将失效
setProgress : 设置进度条与当前进度。进度条位于标题文本与内容文本中间
setNumber : 设置下拉列表右下方的数字,可与setProgress联合使用,表示进度条的当前进度数值
setContentInfo : 设置下拉列表右下方的文本。若调用该方法,则setNumber的设置将失效
setContentIntent : 设置内容的PendingIntent,在点击该通知时触发Intent动作
setDeleteIntent : 设置删除的PendingIntent,在滑掉该通知时触发Intent动作
setAutoCancel : 设置该通知是否自动清除。若为true,点击该通知后,通知会自动消失;若为false,点击该通知后,通知不会消失。
setSound : 设置通知推送时的声音
setVibrate : 设置通知推送时的震动方式
setOngoing : 设置该通知是否保持在下拉列表中。为true时用户将不能从下拉列表中去掉该通知
setPriority : 设置该通知的优先级
setExtras : 设置该通知的Bundle参数信息
setContent : 设置一个定制视图RemoteViews,用于取代Builder的默认视图模板
build : 构建方法。在以上参数都设置完毕后,调用该方法会返回Notification对象

NotificationManager

Notification只是生成通知的内容,实际推送动作还需要借助于系统的通知服务来实现。NotificationManager便是系统通知服务的管理类,它的常用方法如下:
notify : 推送指定通知到状态栏和下拉列表
cancel : 取消指定通知。调用该方法后,状态栏和下拉列表中的指定通知将消失
cancelAll : 取消所有通知

下面是NotificationManager的调用代码例子:

         NotificationManager notifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);notifyMgr.notify(R.string.app_name, notify);

Notification除了可由NotificationManager进行推送,也可由Service的startForeground方法推送,从而使得后台服务保持在前台运行,详细说明见《 Android开发笔记(四十一)Service的生命周期》。

RemoteViews

远程视图RemoteViews与页面视图一样也是从layout下的布局文件中得到,二者之间的区别主要有:
1、远程视图主要用于桌面部件与通知栏部件,而页面视图用于APP页面;
2、远程视图只支持少数几种控件,如TextView、ImageView、Button、ImageButton、ProcessBar、Chronometer(计时器)、AnalogClock(模拟时钟);
3、远程视图不可直接设置控件信息,只能通过RemoteViews对象的set方法来设置;

下面是RemoteViews的常用方法:
RemoteViews : 构造函数。第一个参数是包名,第二个参数是布局文件id
setViewVisibility : 设置控件是否可见
setViewPadding : 设置控件的间距
setTextViewText : 设置TextView和Button的文本内容
setTextViewTextSize : 设置TextView和Button的文本大小
setTextColor : 设置TextView和Button的文本颜色
setTextViewCompoundDrawables : 设置TextView的周围图标
setImageViewResource : 设置ImageView和ImageButton的图片id
setImageViewBitmap : 设置ImageView和ImageButton的图片位图
setChronometer : 设置计时器信息
setProgressBar : 设置进度条信息
setOnClickPendingIntent : 设置控件点击的响应动作

使用示例

为演示本文提到的几种推送,博主编码实现了下列三种方式的推送:
1、采用默认模板推送一个通知;
2、采用RemoteViews方式推送通知,并可根据部件上的点击事件改变通知内容;
3、采用RemoteViews方式让后台服务保持在前台运行,并可由后台服务的运行进度来实时更新通知内容;

下面是采用RemoteViews方式的通知推送效果图:

下面是通知推送的示例代码:

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RemoteViews;@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class NotificationActivity extends Activity implements OnClickListener {private static final String TAG = "NotificationActivity";private String mSong = "《两只老虎》";private String PLAY_EVENT = "";private boolean bPlay = true;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_notification);Button btn_default = (Button) findViewById(R.id.btn_default);Button btn_custom = (Button) findViewById(R.id.btn_custom);Button btn_service = (Button) findViewById(R.id.btn_service);btn_default.setOnClickListener(this);btn_custom.setOnClickListener(this);btn_service.setOnClickListener(this);PLAY_EVENT = getResources().getString(R.string.play_event);}private void sendDefaultNotify() {Intent clickIntent = new Intent(this, MainActivity.class);PendingIntent contentIntent = PendingIntent.getActivity(this,R.string.app_name, clickIntent,PendingIntent.FLAG_UPDATE_CURRENT);Intent cancelIntent = new Intent(this, MessengerActivity.class);PendingIntent deleteIntent = PendingIntent.getActivity(this,R.string.app_name, cancelIntent,PendingIntent.FLAG_UPDATE_CURRENT);Notification.Builder builder = new Notification.Builder(this);builder.setContentIntent(contentIntent).setDeleteIntent(deleteIntent).setUsesChronometer(true).setProgress(100, 60, false).setSubText("这里是副本").setNumber(99).setAutoCancel(false).setSmallIcon(R.drawable.tt_s).setTicker("提示文本")//.setWhen(System.currentTimeMillis()).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.tt_s)).setContentTitle("标题文本").setContentText("内容文本");Notification notify = builder.build();NotificationManager notifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);notifyMgr.notify(R.string.app_name, notify);}private void sendCustomNotify(boolean is_play) {bPlay = !bPlay;Intent pIntent = new Intent(PLAY_EVENT);PendingIntent nIntent = PendingIntent.getBroadcast(this, R.string.app_name, pIntent, PendingIntent.FLAG_UPDATE_CURRENT);RemoteViews widget_notify = new RemoteViews(getPackageName(), R.layout.widget_notify);if (is_play == true) {widget_notify.setTextViewText(R.id.btn_play, "暂停");widget_notify.setTextViewText(R.id.tv_play, mSong+"正在播放");widget_notify.setProgressBar(R.id.pb_play, 100, 10, false);widget_notify.setOnClickPendingIntent(R.id.btn_play, nIntent);widget_notify.setChronometer(R.id.chr_play, SystemClock.elapsedRealtime(), "%s", true);} else {widget_notify.setTextViewText(R.id.btn_play, "继续");widget_notify.setTextViewText(R.id.tv_play, mSong+"暂停播放");widget_notify.setProgressBar(R.id.pb_play, 100, 60, false);widget_notify.setChronometer(R.id.chr_play, SystemClock.elapsedRealtime(), "%s", false);}widget_notify.setOnClickPendingIntent(R.id.btn_play, nIntent);Intent intent = new Intent(this, MainActivity.class);PendingIntent contentIntent = PendingIntent.getActivity(this,R.string.app_name, intent,PendingIntent.FLAG_UPDATE_CURRENT);Notification.Builder builder = new Notification.Builder(this);builder.setContentIntent(contentIntent).setContent(widget_notify).setTicker(mSong).setSmallIcon(R.drawable.tt_s);Notification notify = builder.build();NotificationManager notifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);notifyMgr.notify(R.string.app_name, notify);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_default) {sendDefaultNotify();} else if (v.getId() == R.id.btn_custom) {sendCustomNotify(bPlay);} else if (v.getId() == R.id.btn_service) {Intent intent = new Intent(this, MusicService.class);intent.putExtra("is_play", bPlay);intent.putExtra("song", mSong);if (bPlay == true) {startService(intent);} else {stopService(intent);}bPlay = !bPlay;}}@Overridepublic void onStart() {super.onStart();notifyReceiver = new NotifyReceiver();IntentFilter filter = new IntentFilter(PLAY_EVENT);registerReceiver(notifyReceiver, filter);}@Overridepublic void onStop() {unregisterReceiver(notifyReceiver);super.onStop();}private NotifyReceiver notifyReceiver;public class NotifyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent != null) {sendCustomNotify(bPlay);}}}}

下面是后台服务的示例代码:

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
import android.widget.RemoteViews;@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class MusicService extends Service {private static final String TAG = "MusicService";private final IBinder mBinder = new LocalBinder();public class LocalBinder extends Binder {public MusicService getService() {return MusicService.this;}}@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "onBind");return mBinder;}private String mSong;private String PAUSE_EVENT = "";private boolean bPlay = true;private long mBaseTime;private long mPauseTime = 0;private int mProcess = 0;private Handler mHandler = new Handler();private Runnable mPlay = new Runnable() {@Overridepublic void run() {if (bPlay == true) {if (mProcess < 100) {mProcess+=2;} else {mProcess = 0;}mHandler.postDelayed(this, 200);}refresh();}};private void refresh() {Intent pIntent = new Intent(PAUSE_EVENT);PendingIntent nIntent = PendingIntent.getBroadcast(this, R.string.app_name, pIntent, PendingIntent.FLAG_UPDATE_CURRENT);RemoteViews widget_notify = new RemoteViews(getPackageName(), R.layout.widget_notify);if (bPlay == true) {widget_notify.setTextViewText(R.id.btn_play, "暂停");widget_notify.setTextViewText(R.id.tv_play, mSong+"正在播放");widget_notify.setProgressBar(R.id.pb_play, 100, mProcess, false);widget_notify.setOnClickPendingIntent(R.id.btn_play, nIntent);widget_notify.setChronometer(R.id.chr_play, mBaseTime, "%s", true);} else {widget_notify.setTextViewText(R.id.btn_play, "继续");widget_notify.setTextViewText(R.id.tv_play, mSong+"暂停播放");widget_notify.setProgressBar(R.id.pb_play, 100, mProcess, false);widget_notify.setChronometer(R.id.chr_play, mBaseTime, "%s", false);}widget_notify.setOnClickPendingIntent(R.id.btn_play, nIntent);Intent intent = new Intent(this, MainActivity.class);PendingIntent contentIntent = PendingIntent.getActivity(this,R.string.app_name, intent,PendingIntent.FLAG_UPDATE_CURRENT);Notification.Builder builder = new Notification.Builder(this);builder.setContentIntent(contentIntent).setContent(widget_notify).setTicker(mSong).setSmallIcon(R.drawable.tt_s);Notification notify = builder.build();startForeground(1, notify);}@Overridepublic int onStartCommand(Intent intent, int flags, int startid) {mBaseTime = SystemClock.elapsedRealtime();bPlay = intent.getBooleanExtra("is_play", true);mSong = intent.getStringExtra("song");Log.d(TAG, "bPlay="+bPlay+", mSong="+mSong);mHandler.postDelayed(mPlay, 200);return START_STICKY;}@Overridepublic void onCreate() {PAUSE_EVENT = getResources().getString(R.string.pause_event);pauseReceiver = new PauseReceiver();IntentFilter filter = new IntentFilter(PAUSE_EVENT);registerReceiver(pauseReceiver, filter);super.onCreate();}@Overridepublic void onDestroy() {unregisterReceiver(pauseReceiver);super.onDestroy();}private PauseReceiver pauseReceiver;public class PauseReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent != null) {bPlay = !bPlay;if (bPlay == true) {mHandler.postDelayed(mPlay, 200);if (mPauseTime > 0) {long gap = SystemClock.elapsedRealtime() - mPauseTime;mBaseTime += gap;}} else {mPauseTime = SystemClock.elapsedRealtime();}}}}}

点此查看Android开发笔记的完整目录

Android开发笔记(五十二)通知推送Notification相关推荐

  1. Android开发笔记(十二)测量尺寸与下拉刷新

    尺寸测量的配置 控件宽和高的设置方式 大家知道,自定义视图的目的就是要在屏幕上显示期望的图案,那在绘制图案之前,我们得先知道这个图案的尺寸(如宽多少高多少). 一般在xml中给控件的宽和高有三种赋值方 ...

  2. Android开发笔记(一百二十三)下拉刷新布局SwipeRefreshLayout

    SwipeRefreshLayout 下拉刷新布局SwipeRefreshLayout是Android又一与时俱进的控件,顾名思义它随着用户手势向下滑动就会触发刷新操作.从实际的下拉效果来看,Swip ...

  3. Android开发笔记(一百二十六)自定义音乐播放器

    MediaRecorder/MediaPlayer 在Android手机上面,音频的处理比视频还要复杂,这真是出人意料.在前面的博文< Android开发笔记(五十七)录像录音与播放>中, ...

  4. Android开发笔记(一百二十二)循环器视图RecyclerView

    RecyclerView RecyclerView是Android在support-v7库中新推出控件,中文别名为循环器视图,它的功能非常强大,可分别实现ListView.GridView,以及瀑布流 ...

  5. Android开发笔记(一百二十五)自定义视频播放器

    视频播放方式 在Android中播放视频的方式有两种: 1.使用MediaPlayer结合SurfaceView进行播放.其中通过SurfaceView显示视频的画面,通过MediaPlayer来设置 ...

  6. Android开发笔记(一百二十九)使用变换图形

    裁剪图形ClipDrawable ClipDrawable可设置图形的裁剪幅度,它的构造函数除了指定来源图形之外,还可以指定图形的裁剪方式(从开始裁剪还是从中间裁剪还是从末尾裁剪),以及裁剪方向(水平 ...

  7. Android开发笔记(一百二十八)手机制式适配

    查看运营商与网络类型 虽然现在4G网络很普及了,但是我国幅员辽阔,4G信号在某些地方接收不良,手机连接很容易掉到3G甚至2G网络.为了让用户在低速环境也能使用App的基础功能,而不至于还在老牛破车地缓 ...

  8. Android开发笔记(一百二十四)自定义相册

    画廊Gallery Gallery是一个早期的画廊控件,左右滑动手势可展示内嵌的图片列表,类似于一个平面的万花筒.虽然Android现在将Gallery标记为Deprecation(表示已废弃),建议 ...

  9. Android开发笔记(一百二十)两种侧滑布局

    SlidingPaneLayout SlidingPaneLayout是Android在android-support-v4.jar中推出的一个可滑动面板的布局,在前面< Android开发笔记 ...

最新文章

  1. 5分钟回顾Linux25年的发展历程与变迁
  2. Python编程学习:让函数更加灵活的*args和**kwargs(设计不同数量参数的函数)的简介、使用方法、经典案例之详细攻略
  3. python mpl_toolkits.mplot3d.axes3d.Axes3D()使用 介绍
  4. vue项目没有启动成功的原因之一
  5. Silverlight 5 Beta新特性[4]文本缩进控制
  6. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]42蒙哥马利乘法,哪里泄漏侧信道路吗?
  7. C语言课后习题(9)
  8. Spring的Bean属性依赖注入
  9. java 实现多重继承
  10. arduino下载ESP8266开发板的方法
  11. 深入理解SD卡基础原理以及内部结构的总结
  12. 程序员如何站在巨人的肩膀上
  13. matlab求解常微分方程的实验,实验五__用matlab求解常微分方程
  14. 第 7 章 —— 代理模式
  15. pfSense与CARP的硬件冗余
  16. 关于按键精灵url的post方法返回值为空
  17. 纸壳CMS可视化建站系统搭建多语言网站
  18. 逻辑运算符,if、swtch语句(java基础知识三)
  19. 亚马逊测评有哪些误解?
  20. 配置软路由-同时连接内网和外网

热门文章

  1. Leetcode每日一题:剑指 Offer 04.(二维数组中的查找)
  2. Redis基础(三)——数据类型
  3. PHP学习记录(数学函数库)
  4. Pythonic版二分查找
  5. android本地图片,Android中ImageView实现选择本地图片并显示功能
  6. python api框架 hook_python学习之hook钩子的原理和使用
  7. spring 主从表_听听京东架构师浅谈,MySQL binlog 主从同步
  8. JavaScript Promise 快速入门
  9. nodemcu固件_从无到有玩NodeMcu:web端控制
  10. Dropping tests