• 【直接拿来用のandroid公共代码模块解析与分享】の Notification和NotificationManager


    本文源代码托管在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 ,未经本人允许请勿用于商业用途。谢谢——
  • 相关阅读:
    使用shape来定义控件的一些显示属性
    Button颜色选择器进阶
    android用于打开各种文件的intent
    虚拟机操作
    二维码生成与读取
    input框只能输入整数
    实现FF背景透明,文字不透明
    打日志
    多选框
    时间戳
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6964821.html
Copyright © 2020-2023  润新知