1.Notification的使用
Notification的创建使用建造者模式,通过Builder构造器来创建Notification对象,并通过NotificationManager来对Notification进行管理
但是由于android各个版本对这个功能有部分的修改,因此我们最好使用support-v7库中提供的NotificationCompat类,使用这个类的Builder构造器来构建Notification就能解决不同版本android系统的兼容问题
//通过Context获取到NotificationManager
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
//构建PendingIntent
//第一个参数为Context
//第二个参数为requestCode,类似于startActivityForResult()中的requestCode吧(不确定)
//第三个传入Intent,表示触发时要做的行为
//第四个参数则用于确定PendingIntent的模式,有FLAG_ONE_SHOT、FLAG_NO_CREATE 、FLAG_CANCEL_CURRENT、FLAG_UPDATE_CURRENT等4个值可选
Intent intent = new Intent(this, NofiticationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, FLAG_UPDATE_CURRENT);
//通过NotificationCompat.Builder(Context context)构建Notification,使用build()获取到Notification实例
Notification notification= new NotificationCompat.Builder(MainActivity.this)
.setLargeIcon(BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.icon_spring_festival_logo))
.setSmallIcon(R.mipmap.icon_main_app_small_logo)
.setContentTitle("通知")// 设置在下拉status
.setContentText("这是一条通知")// TextView中显示的详细内容
.setContentIntent(mPendingIntent) // 关联PendingIntent
.setNumber(pushBean.id) // 在TextView的右方显示的数字,可放大图片看,在最右侧。这个number同时也起到一个序列号的左右,如果多个触发多个通知(同一ID),可以指定显示哪一个
.setAutoCancel(true) //设置是否点击后通知自动消失,也可以手动调用manager.cancel(id),id对应后面每个通知所指定的id
//进阶功能
//.setSound(Uri.parse("android.resource://" + packageName + File.separator + R.raw.ring_6))
.setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg"))) //设置声音
.setVibrate(new long[]{0, 1000, 1000, 1000})//设置震动,手机静止时长-振动时长-静止时长-震动时长....(以此类推)
.setLights(Color.GREEN, 1000, 1000) //设置LED灯的颜色、亮起时长、暗去时长
//.setDefaults(android.support.v7.app.NotificationCompat.DEFAULT_ALL) //设置默认模式,自动选择声音、震动、灯光
.build();
//发出通知
manager.notify(id, notification); //第一个参数为id,要保证每个通知所指定的id都是不同的
关于Notification的largeIcon无法更改的问题
在项目中我需要通过后台传入的url来加载通知的消息栏图片,于是我的demo如下
package com.sfexpress.testnotificationloadpicure;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.NotificationCompat;
import android.view.View;
import android.widget.Button;
import rx.Subscriber;
import rx.functions.Func1;
public class MainActivity extends AppCompatActivity {
private Button btn_show_notification;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String url = "http://b.hiphotos.baidu.com/zhidao/pic/item/a6efce1b9d16fdfafee0cfb5b68f8c5495ee7bd8.jpg";
btn_show_notification = (Button) findViewById(R.id.show_notification);
btn_show_notification.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
long when = System.currentTimeMillis();
final NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int requestCode = 1;
try {
requestCode = (int) when;
} catch (Exception e) {
//不处理
}
final Notification notification = new NotificationCompat.Builder(MainActivity.this)
//在这里设置默认的largeIcon
.setLargeIcon(BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.icon_spring_festival_logo))
.setSmallIcon(R.mipmap.icon_main_app_small_logo)
.setContentTitle("通知")
.setContentText("这是一条通知")
.build();
final int requestCodeInner = requestCode;
rx.Observable.just(url)
.map(new Func1() {
@Override
public Bitmap call(String url) {
//根据url对图片进行加载,并裁剪为192 X 192的尺寸
ImageLoader imageLoader = ImageLoader.build(MainActivity.this);
return imageLoader.loadBitmap(url,192, 192);
}
})
.compose(RxUtils.applySchedulers())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
//空实现
}
@Override
public void onError(Throwable e) {
//空实现
}
@Override
public void onNext(Bitmap bitmap) {
if(bitmap != null){
//将bitmap设置到notification当中
notification.largeIcon = bitmap;
}
manager.notify(requestCodeInner, notification);
}
});
}
});
}
}
程序运行的结果是largeIcon仍然显示为我在构建notification时的默认icon,而不是通过网络url加载的icon。
刚开始我以为是因为匿名内部类导致外部Notification对象必须定义为final而导致不可修改,但是我们知道final在修饰一个对象的时候只是会使这个对象始终指向同一个地址,而不会限制对象中成员变量的修改。
因此我尝试对程序打断点,结果发现,在最后调用manager.notify()的时候,notification中的largeIcon实际上已经被替换为了新加载的bitmap,因此我猜测在Builder构建的时候设置LargeIcon会将其设置到一个map当中,在manager.notify()的时候会优先从map中进行取值,为空才会查询notification的largeIcon字段,因此这种方式无法成功加载网络图片,那么解决方案就有两种:
- 第一种方案:在Builder构建notification的时候不设置largeIcon,但是这种方式不优雅
- 第二种方案: Builder构建notification时不直接调用build获取Notificaition实例,而是在manager.notify()调用前再调用build()方法,下面使用这种方案
package com.sfexpress.testnotificationloadpicure;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.NotificationCompat;
import android.view.View;
import android.widget.Button;
import rx.Subscriber;
import rx.functions.Func1;
public class MainActivity extends AppCompatActivity {
private Button btn_show_notification;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String url = "http://b.hiphotos.baidu.com/zhidao/pic/item/a6efce1b9d16fdfafee0cfb5b68f8c5495ee7bd8.jpg";
btn_show_notification = (Button) findViewById(R.id.show_notification);
btn_show_notification.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
long when = System.currentTimeMillis();
final NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int requestCode = 1;
try {
requestCode = (int) when;
} catch (Exception e) {
//不处理
}
//获取到Builder对象
final NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
//给Builder对象设置默认属性
builder.setLargeIcon(BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.icon_spring_festival_logo))
.setSmallIcon(R.mipmap.icon_main_app_small_logo)
.setContentTitle("通知")// 设置在下拉status
.setContentText("这是一条通知")// TextView中显示的详细内容
.setWhen(when);
final int requestCodeInner = requestCode;
rx.Observable.just(url)
.map(new Func1() {
@Override
public Bitmap call(String url) {
ImageLoader imageLoader = ImageLoader.build(MainActivity.this);
return imageLoader.loadBitmap(url,192, 192);
}
})
.compose(RxUtils.applySchedulers())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
//空实现
}
@Override
public void onError(Throwable e) {
//空实现
}
@Override
public void onNext(Bitmap bitmap) {
if(bitmap != null){
builder.setLargeIcon(bitmap);
}
//在notify()调用前通过builder方法获取Notification实例并作为参数传入notify()方法
manager.notify(requestCodeInner, builder.build());
}
});
}
});
}
}
以这种方案实现就能够更加轻松的将notificaiton的通用构造过程封装起来,仅返回一个Builder对象,然后通过操作Builder对象对Notification进行个性化设置