失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 常驻通知栏

常驻通知栏

时间:2020-03-25 12:46:49

相关推荐

常驻通知栏

常驻通知栏

不废话,上代码

//创建一个通知管理器NotificationManager notificationManager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 获取Notification实例Notification notification=new NotificationCompat.Builder(this,channelId).setContentTitle("title").setContentText("content").setWhen(System.currentTimeMillis())// .setAutoCancel(false) 点击通知栏后是否消失.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.icon))// .setCustomContentView(remoteView) // 设置自定义的RemoteView,需要API最低为24.setSmallIcon( R.mipmap.instant)// 设置点击通知栏后跳转地址.setContentIntent( PendingIntent.getActivity(this, 0, new Intent(this, SecondActivity.class), 0)).build();// 添加渠道if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){NotificationChannel channel = new NotificationChannel(channelId, "subscribeName", NotificationManager.IMPORTANCE_DEFAULT);channel.setDescription("description");notificationManager.createNotificationChannel(channel);}// 设置常驻 Flagnotification.flags = Notification.FLAG_ONGOING_EVENT;//展示通知栏notificationManager.notify(notificationId,notification);

展示效果如下

注意

在8.0以下手机是不用添加渠道的,但在之上不添加渠道不展示通知栏,9.0手机不设置setDescription()依旧不展示通知栏【华为mate10 9.0版本测试】;

自定义通知栏

有时间我们不想展示系统给的固定的展示效果,想自己写一个效果,只需要在代码中添加RemoteViews。

//通过xml创建RemoteViews,并且动态改变布局中的内容RemoteViews remoteView = new RemoteViews(getPackageName(), R.layout.bar_notification);remoteView.setImageViewResource(R.id.iv_icon, R.mipmap.ic_launcher);remoteView.setTextViewText(R.id.tv_title, "my title");remoteView.setTextViewText(R.id.tv_content, "my content");Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");String time = sdf.format(date);remoteView.setTextViewText(R.id.tv_time, time);

并放开setCustomContentView()功能,这时Notification中设置的方法基本都不可用了,但是setSmallIcon()必须有(虽然没展示效果),不管是不是自定义布局都要有,否则就会报错。

关闭通知栏

/*** 取消常驻通知** @param context*/public static void delNotification(Context context) {NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);notificationManager.cancel(notificationId);}

这里的notificationId即为最开始notificationManager.notify(notificationId,notification)中的notificationId。

手机设置里修改通知状态

public void setting(View view) {Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);intent.putExtra(Settings.EXTRA_CHANNEL_ID, channelId);intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());startActivity(intent);}

这里的channelId 就是我们在添加渠道时设置的Id

防止多创建界面

我们在 设置setContentIntent方法时是直接getActivity,这样会导致new出一个activity,点击返回键会返回到原来未点通知之前的界面

/*** 构造一个合成的回退栈,主要用于跨任务导航*/Intent resultIntent = new Intent(context, MainActivity.class);TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);stackBuilder.addParentStack(MainActivity.class);stackBuilder.addNextIntent(resultIntent);PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

将resultPendingIntent 传入.setContentIntent()即可

其实到这里,基本效果已经好了,市面上大部分APP的通知栏都是系统自带的效果,自定义的都不是,就算是自定义的大部分也不需要进行网络图片的加载!!!

加载网路数据

既然加了图片,很大可能是从服务器发送来的照片

这时setImageViewResource()功能就不行了,还好,remoteView里有另外两种方法

remoteView.setImageViewUri(R.id.iv_icon, uri);remoteView.setImageViewBitmap(R.id.iv_icon,bitmap);

看源码发现方式与ImageView的setImageURI(Uri)和setImageBitmap(Bitmap)类似,

这就好办了

Uri uri = Uri.parse("/timg?image&quality=80&size=b9999_10000&sec=1565676565588&di=14318ae342c65b768a272ef158a6fd78&imgtype=0&src=http%3A%2F%%2F00%2F51%2F76%2F16pic_5176356_b.jpg");remoteView.setImageViewUri(R.id.iv_click, uri);

发现一点也不行,以为是图片过大或者图片是jpg 格式的问题,后来才发现这个方式原来针对的是本地图片,都说了类似imageview了,狠狠地打脸啊,在此记录一下!!!

imageview.setImageURI(Uri.parse("file:///assets/xxx.jpg"))

相对应的

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.a)

这也是本地图片,既然写到这里记录一下图片转化bitmap的方法吧,省得自己再被打脸

// 一、加载R文件下的图片//最简单的方式Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.loading);//二、文件流的方式转化bitmapFileInputStream fis = null;try {fis = new FileInputStream(dir + "/" + fileName);} catch (FileNotFoundException e) {e.printStackTrace();}Bitmap bitmap = BitmapFactory.decodeStream(fis);// 三、网络url转化为bitmapURL url = new URL(imgUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();InputStream is = conn.getInputStream();Bitmap bm = BitmapFactory.decodeStream(is);

前两种转化为bitmap时,都可能会因为图片过大导致溢出,

第一种方式可以参照大佬android避免decodeResource图片时占用太大的内存

/** * 我们知道调用BitmapFactory.decodeResource时,如果手机屏幕的密度很大时,如果只是在hdpi放了图片, decode出来的* bitmap会自动的scale放大。 而且如果按照ARGB_8888模式decode的话一个像素需要4个字节,这样343*433分辨率的图* * 片decode大概会占用2M多内存。 所以从2方面控制,一个是禁止scale, 一个是使用ALPHA_8模式decode。注意:这里* * 需要看看效果是否ok, 因为使用低质量的模式decode图片可能会修饰一些图片的细节。* 因为目前我们只有一套资源文件,全都放在hdpi下面,这样如果是遇到高密度手机, 系统会按照 * scale = (float) targetDensity / density 把图片放到几倍,这样会使得在高密度手机上经常会发生OOM。 * * 这个方法用来解决在如果密度大于hdpi(240)的手机上,decode资源文件被放大scale,内容浪费的问题。 * * @param resources * @param id * @return */ public static Bitmap decodeResource(Resources resources, int id) { int densityDpi = resources.getDisplayMetrics().densityDpi; Bitmap bitmap; TypedValue value = new TypedValue(); resources.openRawResource(id, value); BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inPreferredConfig = Bitmap.Config.ALPHA_8; if (densityDpi > DisplayMetrics.DENSITY_HIGH) { opts.inTargetDensity = value.density; bitmap = BitmapFactory.decodeResource(resources, id, opts); }else{ bitmap = BitmapFactory.decodeResource(resources, id); } return bitmap; }

第二种方式可以参照大佬图片文件和Bitmap之间的转换

言归正传,我们以remoteView.setImageViewBitmap(R.id.iv_icon,bitmap)为例,这里需要设置网络图片转为bitmap的方法,也就是如上第三种方式,图片加载需要设置异步,这里使用Thread+Handler模式,代码如下:

public void setNotification(Context mContext) {context = mContext;final String iconUrl = SpUtils.getSpUtils(context).getNotificationIconUrl();if (TextUtils.isEmpty(iconUrl)) {return;}new Thread() {@Overridepublic void run() {getBitmap(iconUrl);}}.start();}/*** @param* @author admin* @Description: 获取Bitmap<br/>*/private void getBitmap(String resUrl) {URL fileUrl = null;Bitmap bitmap = null;try {fileUrl = new URL(resUrl);} catch (MalformedURLException e) {e.printStackTrace();}try {HttpURLConnection conn = (HttpURLConnection) (fileUrl != null ? fileUrl.openConnection() : null);assert conn != null;conn.setDoInput(true);conn.connect();InputStream is = conn.getInputStream();bitmap = BitmapFactory.decodeStream(is);is.close();Message message = Message.obtain();message.obj = bitmap;handler.sendMessage(message);} catch (Exception e) {e.printStackTrace();}}private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {showNotivication((Bitmap) msg.obj);}};

到这里,我们需要的bitmap即可在最开始的代码里通过 showNotivication((Bitmap) msg.obj) 引用了。

到这里网络加载也基本上可以结束了。但是,但是,当发现公司要求通知栏里展示两张图片的时候,我又纳闷了,用Thread+Handler,最常见的是异步加载一个请求呀!没见过new 两个 thread的(据说new两个会数据会串,俺也不知道,俺也没地方问),就算可以,讲个异步操作都执行完在去执行show通知栏会不会很麻烦(其实不算麻烦,既然是异步,总有先后,当后加载好的图片加载完成后再去调用通知栏方法就好了嘛)?当然也可以用AsyncTask加载更多图片

如果觉得《常驻通知栏》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。