本文源码托管在https://github.com/ASCE1885/asce-common,欢迎fork
Android项目做得多了,会发现原来很多基础的东西都是可以复用,这个系列介绍一些自己项目中常用到的公共模块代码(当然只谈技术不谈业务),一来整理好了自己以后可以直接用,二来也分享给大家,希望能稍微减少大家的加班时间,提高些许效率。
Android Notification的原理和作用这里就不作说明了,相信是个android开发者都用过不止一次了,以下只介绍如何封装成公共的模块,以供整个项目使用。
基于不同的目的,Notification的外观差别很大,对应到代码上就是布局的差异,因此,我们首先需要有一个接口供使用者来创建不同布局的Notification,接口在Java中当然是以Interface的形式存在,如代码清单IMyNotificationBuilder.java所示。
/**
* Notification接口
*
* @author asce1885
* @date 2014-06-09
*
*/
public interface IMyNotificationBuilder {
public static final String NOTIFICATION_ID = IMyNotificationBuilder.class.getSimpleName();
Notification buildNotification(String title, String content);
}
看到这里,熟悉设计模式的同学应该知道我们使用的是Builder模式来构建不同的Notification,按照惯例,通常会有一个默认的Builder实现,我们将之命名为BasicNotificationBuilder.java,它使用的是Android系统默认的通知栏布局。
/**
* 默认Notification构造器
*
* @author asce1885
* @date 2014-06-09
*
*/
public class BasicNotificationBuilder implements IMyNotificationBuilder {
private Context mContext;
private PendingIntent mPendingIntent;
public int mIconDrawableId;
public BasicNotificationBuilder(Context context, PendingIntent pendingIntent) {
mContext = context;
mPendingIntent = pendingIntent;
mIconDrawableId = PackageUtils.getAppInfo(context).icon;
}
public BasicNotificationBuilder(Context context, PendingIntent pendingIntent, int iconDrawableId) {
mContext = context;
mPendingIntent = pendingIntent;
mIconDrawableId = iconDrawableId;
}
@SuppressWarnings("deprecation")
@Override
public Notification buildNotification(String title, String content) {
Notification basicNotification = new Notification(mIconDrawableId, title,
System.currentTimeMillis());
basicNotification.setLatestEventInfo(mContext, title, content, mPendingIntent);
basicNotification.flags |= Notification.FLAG_AUTO_CANCEL;
basicNotification.defaults = Notification.DEFAULT_SOUND;
basicNotification.contentIntent = mPendingIntent;
return basicNotification;
}
}
对于其他需要自定义布局的通知栏形式,我们另外实现一个类,布局文件由使用者自定义,见代码清单CustomNotificationBuilder.java。
/**
* 自定义样式Notification构造器
*
* @author asce1885
* @date 2014-06-09
*
*/
public class CustomNotificationBuilder implements IMyNotificationBuilder {
private Context mContext;
private int mCustomeLayout;
private int mLayoutSubjectId;
private int mLayoutMessageId;
private int mLayoutIconId;
private int mStatusBarIconDrawableId;
private Uri mSoundUri;
private PendingIntent mPendingIntent;
public CustomNotificationBuilder(Context context, int customeLayout, int layoutSubjectId, int layoutMessageId, int layoutIconId, int statusBarIconDrawableId, Uri soundUri, PendingIntent pendingIntent) {
mContext = context;
mCustomeLayout = customeLayout;
mLayoutSubjectId = layoutSubjectId;
mLayoutMessageId = layoutMessageId;
mLayoutIconId = layoutIconId;
mStatusBarIconDrawableId = statusBarIconDrawableId;
mSoundUri = soundUri;
mPendingIntent = pendingIntent;
}
@SuppressWarnings("deprecation")
@Override
public Notification buildNotification(String title, String content) {
if (TextUtils.isEmpty(content)) {
return null;
}
PreFroyoNotificationStyleDiscover.getInstance().discoverStyle(mContext);
Notification customerNotification = new Notification(mStatusBarIconDrawableId, title,
System.currentTimeMillis());
RemoteViews customerRemoteView = new RemoteViews(mContext.getPackageName(), mCustomeLayout);
customerRemoteView.setTextViewText(mLayoutSubjectId, PackageUtils.getAppName(mContext));
customerRemoteView.setTextViewText(mLayoutMessageId, content);
customerRemoteView.setImageViewResource(mLayoutIconId, mStatusBarIconDrawableId);
customerNotification.flags |= Notification.FLAG_AUTO_CANCEL;
if (mSoundUri != null) {
customerNotification.sound = mSoundUri;
} else {
customerNotification.defaults = Notification.DEFAULT_SOUND;
}
customerNotification.contentIntent = mPendingIntent;
// Some SAMSUNG devices status bar cant't show two lines with the size,
// so need to verify it, maybe increase the height or decrease the font size
customerRemoteView.setFloat(mLayoutSubjectId, "setTextSize",
PreFroyoNotificationStyleDiscover.getInstance().getTitleSize());
customerRemoteView.setTextColor(mLayoutSubjectId, PreFroyoNotificationStyleDiscover
.getInstance().getTitleColor());
customerRemoteView.setFloat(mLayoutMessageId, "setTextSize",
PreFroyoNotificationStyleDiscover.getInstance().getTextSize());
customerRemoteView.setTextColor(mLayoutMessageId, PreFroyoNotificationStyleDiscover
.getInstance().getTextColor());
customerNotification.contentView = customerRemoteView;
return customerNotification;
}
/**
* A class for discovering Android Notification styles on Pre-Froyo (2.3) devices
*/
private static class PreFroyoNotificationStyleDiscover {
private Integer mNotifyTextColor = null;
private float mNotifyTextSize = 11;
private Integer mNotifyTitleColor = null;
private float mNotifyTitleSize = 12;
private final String TEXT_SEARCH_TEXT = "SearchForText";
private final String TEXT_SEARCH_TITLE = "SearchForTitle";
private static Context mContext;
private static class LazyHolder {
private static final PreFroyoNotificationStyleDiscover sInstance = new PreFroyoNotificationStyleDiscover();
}
public static PreFroyoNotificationStyleDiscover getInstance() {
return LazyHolder.sInstance;
}
private PreFroyoNotificationStyleDiscover() {
}
public int getTextColor() {
return mNotifyTextColor.intValue();
}
public float getTextSize() {
return mNotifyTextSize;
}
public int getTitleColor() {
return mNotifyTitleColor;
}
public float getTitleSize() {
return mNotifyTitleSize;
}
private void discoverStyle(Context context) {
mContext = context;
// Already done
if (null != mNotifyTextColor) {
return;
}
try {
Notification notify = new Notification();
notify.setLatestEventInfo(mContext, TEXT_SEARCH_TITLE, TEXT_SEARCH_TEXT, null);
LinearLayout group = new LinearLayout(mContext);
ViewGroup event = (ViewGroup) notify.contentView.apply(mContext, group);
recurseGroup(event);
group.removeAllViews();
} catch (Exception e) {
// Default to something
mNotifyTextColor = android.R.color.black;
mNotifyTitleColor = android.R.color.black;
}
}
private boolean recurseGroup(ViewGroup group) {
final int count = group.getChildCount();
for (int i = 0; i < count; ++i) {
if (group.getChildAt(i) instanceof TextView) {
final TextView tv = (TextView) group.getChildAt(i);
final String text = tv.getText().toString();
if (text.startsWith("SearchFor")) {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metrics);
if (TEXT_SEARCH_TEXT == text) {
mNotifyTextColor = tv.getTextColors().getDefaultColor();
mNotifyTextSize = tv.getTextSize();
mNotifyTextSize /= metrics.scaledDensity;
} else {
mNotifyTitleColor = tv.getTextColors().getDefaultColor();
mNotifyTitleSize = tv.getTextSize();
mNotifyTitleSize /= metrics.scaledDensity;
}
if (null != mNotifyTitleColor && mNotifyTextColor != null) {
return true;
}
}
} else if (group.getChildAt(i) instanceof ViewGroup) {
if (recurseGroup((ViewGroup) group.getChildAt(i))) {
return true;
}
}
}
return false;
}
}
}
Notification的构建代码至此结束,而要发出Notification,使用的是NotificationManager,我们将它封装成代码清单MyNotificationManager.java。
/**
* Notification管理器
*
* @author asce1885
* @date 2014-06-09
*
*/
public class MyNotificationManager {
private IMyNotificationBuilder mMyNotificationBuilder;
private static final int START_ID = 1000;
private static final int RANGE = 50;
private int mCurrentId = START_ID;
private MyNotificationManager() {
}
private static class LazyHolder {
private static final MyNotificationManager sInstance = new MyNotificationManager();
}
public static MyNotificationManager getInstance() {
return LazyHolder.sInstance;
}
public IMyNotificationBuilder getMyNotificationBuilder() {
return mMyNotificationBuilder;
}
public void setMyNotificationBuilder(IMyNotificationBuilder builder) {
mMyNotificationBuilder = builder;
}
public void deliverNotification(Context context, String title, String content) {
buildAndDisplayNotification(context, title, content);
}
private void buildAndDisplayNotification(Context context, String title, String content) {
if (null != mMyNotificationBuilder) {
Notification notification = mMyNotificationBuilder.buildNotification(title, content);
if (null != notification) {
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(generateNotification(), notification);
}
}
}
private int generateNotification() {
mCurrentId++;
if (mCurrentId >= START_ID + RANGE) {
mCurrentId = START_ID;
}
return mCurrentId;
}
}
最后给下使用的示例代码如下所示,只作为参考,里面的部分变量不用深究。
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra(BundleConstant.KEY_NOTIFICATION_TYPE, action);
intent.putExtra(BundleConstant.KEY_WEBVIEW_TITLE, notice.webview_title);
intent.putExtra(BundleConstant.KEY_WEBVIEW_URL, notice.webview_url);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), (int) notice.nid, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder = new BasicNotificationBuilder(getApplicationContext(), pendingIntent);
MyNotificationManager.getInstance().setMyNotificationBuilder(builder);
MyNotificationManager.getInstance().deliverNotification(getApplicationContext(), notice.notification_title, notice.notification_content);
——欢迎转载,请注明出处 http://blog.csdn.net/asce1885 ,未经本人同意请勿用于商业用途,谢谢——