1.Notification的使用
??Notification的創(chuàng)建使用建造者模式踱侣,通過Builder構(gòu)造器來創(chuàng)建Notification對(duì)象,并通過NotificationManager來對(duì)Notification進(jìn)行管理
??但是由于android各個(gè)版本對(duì)這個(gè)功能有部分的修改探膊,因此我們最好使用support-v7庫中提供的NotificationCompat類待榔,使用這個(gè)類的Builder構(gòu)造器來構(gòu)建Notification就能解決不同版本android系統(tǒng)的兼容問題
//通過Context獲取到NotificationManager
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
//構(gòu)建PendingIntent
//第一個(gè)參數(shù)為Context
//第二個(gè)參數(shù)為requestCode,類似于startActivityForResult()中的requestCode吧(不確定)
//第三個(gè)傳入Intent腌闯,表示觸發(fā)時(shí)要做的行為
//第四個(gè)參數(shù)則用于確定PendingIntent的模式雕憔,有FLAG_ONE_SHOT、FLAG_NO_CREATE 分瘦、FLAG_CANCEL_CURRENT琉苇、FLAG_UPDATE_CURRENT等4個(gè)值可選
Intent intent = new Intent(this, NofiticationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, FLAG_UPDATE_CURRENT);
//通過NotificationCompat.Builder(Context context)構(gòu)建Notification,使用build()獲取到Notification實(shí)例
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("通知")// 設(shè)置在下拉status
.setContentText("這是一條通知")// TextView中顯示的詳細(xì)內(nèi)容
.setContentIntent(mPendingIntent) // 關(guān)聯(lián)PendingIntent
.setNumber(pushBean.id) // 在TextView的右方顯示的數(shù)字,可放大圖片看拜马,在最右側(cè)沐绒。這個(gè)number同時(shí)也起到一個(gè)序列號(hào)的左右,如果多個(gè)觸發(fā)多個(gè)通知(同一ID)扮超,可以指定顯示哪一個(gè)
.setAutoCancel(true) //設(shè)置是否點(diǎn)擊后通知自動(dòng)消失蹋肮,也可以手動(dòng)調(diào)用manager.cancel(id),id對(duì)應(yīng)后面每個(gè)通知所指定的id
//進(jìn)階功能
//.setSound(Uri.parse("android.resource://" + packageName + File.separator + R.raw.ring_6))
.setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg"))) //設(shè)置聲音
.setVibrate(new long[]{0, 1000, 1000, 1000})//設(shè)置震動(dòng),手機(jī)靜止時(shí)長(zhǎng)-振動(dòng)時(shí)長(zhǎng)-靜止時(shí)長(zhǎng)-震動(dòng)時(shí)長(zhǎng)....(以此類推)
.setLights(Color.GREEN, 1000, 1000) //設(shè)置LED燈的顏色馁龟、亮起時(shí)長(zhǎng)漆魔、暗去時(shí)長(zhǎng)
//.setDefaults(android.support.v7.app.NotificationCompat.DEFAULT_ALL) //設(shè)置默認(rèn)模式却音,自動(dòng)選擇聲音矢炼、震動(dòng)句灌、燈光
.build();
//發(fā)出通知
manager.notify(id, notification); //第一個(gè)參數(shù)為id,要保證每個(gè)通知所指定的id都是不同的
關(guān)于Notification的largeIcon無法更改的問題
??在項(xiàng)目中我需要通過后臺(tái)傳入的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)
//在這里設(shè)置默認(rèn)的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<String, Bitmap>() {
@Override
public Bitmap call(String url) {
//根據(jù)url對(duì)圖片進(jìn)行加載爹谭,并裁剪為192 X 192的尺寸
ImageLoader imageLoader = ImageLoader.build(MainActivity.this);
return imageLoader.loadBitmap(url,192, 192);
}
})
.compose(RxUtils.<Bitmap>applySchedulers())
.subscribe(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
//空實(shí)現(xiàn)
}
@Override
public void onError(Throwable e) {
//空實(shí)現(xiàn)
}
@Override
public void onNext(Bitmap bitmap) {
if(bitmap != null){
//將bitmap設(shè)置到notification當(dāng)中
notification.largeIcon = bitmap;
}
manager.notify(requestCodeInner, notification);
}
});
}
});
}
}
??程序運(yùn)行的結(jié)果是largeIcon仍然顯示為我在構(gòu)建notification時(shí)的默認(rèn)icon诺凡,而不是通過網(wǎng)絡(luò)url加載的icon践惑。
??剛開始我以為是因?yàn)槟涿麅?nèi)部類導(dǎo)致外部Notification對(duì)象必須定義為final而導(dǎo)致不可修改,但是我們知道final在修飾一個(gè)對(duì)象的時(shí)候只是會(huì)使這個(gè)對(duì)象始終指向同一個(gè)地址凉袱,而不會(huì)限制對(duì)象中成員變量的修改侦铜。
??因此我嘗試對(duì)程序打斷點(diǎn),結(jié)果發(fā)現(xiàn)涤躲,在最后調(diào)用manager.notify()的時(shí)候贡未,notification中的largeIcon實(shí)際上已經(jīng)被替換為了新加載的bitmap,因此我猜測(cè)在Builder構(gòu)建的時(shí)候設(shè)置LargeIcon會(huì)將其設(shè)置到一個(gè)map當(dāng)中俊卤,在manager.notify()的時(shí)候會(huì)優(yōu)先從map中進(jìn)行取值消恍,為空才會(huì)查詢notification的largeIcon字段,因此這種方式無法成功加載網(wǎng)絡(luò)圖片哺哼,那么解決方案就有兩種:
- 第一種方案:在Builder構(gòu)建notification的時(shí)候不設(shè)置largeIcon,但是這種方式不優(yōu)雅
- 第二種方案: Builder構(gòu)建notification時(shí)不直接調(diào)用build獲取Notificaition實(shí)例,而是在manager.notify()調(diào)用前再調(diào)用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對(duì)象
final NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
//給Builder對(duì)象設(shè)置默認(rèn)屬性
builder.setLargeIcon(BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.icon_spring_festival_logo))
.setSmallIcon(R.mipmap.icon_main_app_small_logo)
.setContentTitle("通知")// 設(shè)置在下拉status
.setContentText("這是一條通知")// TextView中顯示的詳細(xì)內(nèi)容
.setWhen(when);
final int requestCodeInner = requestCode;
rx.Observable.just(url)
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String url) {
ImageLoader imageLoader = ImageLoader.build(MainActivity.this);
return imageLoader.loadBitmap(url,192, 192);
}
})
.compose(RxUtils.<Bitmap>applySchedulers())
.subscribe(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
//空實(shí)現(xiàn)
}
@Override
public void onError(Throwable e) {
//空實(shí)現(xiàn)
}
@Override
public void onNext(Bitmap bitmap) {
if(bitmap != null){
builder.setLargeIcon(bitmap);
}
//在notify()調(diào)用前通過builder方法獲取Notification實(shí)例并作為參數(shù)傳入notify()方法
manager.notify(requestCodeInner, builder.build());
}
});
}
});
}
}
??以這種方案實(shí)現(xiàn)就能夠更加輕松的將notificaiton的通用構(gòu)造過程封裝起來,僅返回一個(gè)Builder對(duì)象栏豺,然后通過操作Builder對(duì)象對(duì)Notification進(jìn)行個(gè)性化設(shè)置