[关闭]
@cxm-2016 2016-12-15T09:19:20.000000Z 字数 4156 阅读 4485

Android:使用RemoteViews自定义通知栏样式

Android

版本:1
作者:陈小默
声明:禁止商业,禁止转载

一、普通通知栏

首先我们来演示一下最简单的通知发送方式

  1. val Activity.notificationManager: NotificationManager
  2. get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
  3. class MainActivity : AppCompatActivity() {
  4. private var viewHolder = MainViewHolder()
  5. override fun onCreate(savedInstanceState: Bundle?) {
  6. super.onCreate(savedInstanceState)
  7. setContentView(R.layout.activity_main)
  8. viewHolder.bind(this)
  9. //send是一个button
  10. viewHolder.send?.setOnClickListener { view ->
  11. sendNotification()
  12. }
  13. }
  14. private fun sendNotification() {
  15. val manager = notificationManager
  16. val builder = NotificationCompat.Builder(this)
  17. builder.setContentTitle("title").setContentText("text").setSmallIcon(R.drawable.ic_launcher)
  18. .setDefaults(0)
  19. .setAutoCancel(true)
  20. val notification = builder.build()
  21. manager.notify(0, notification)
  22. }
  23. }

处理点击事件

假如我们想要点击通知消息之后处理某些事件,比如打开浏览器之类的,这里我们选择演示点击通知后使用浏览器打开我的博客主页

  1. val intent = Intent()
  2. intent.action = "android.intent.action.VIEW"
  3. val uri = Uri.parse("http://blog.csdn.net/qq_32583189/")
  4. intent.data = uri
  5. val pIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
  6. builder.setContentIntent(pIntent)

二、使用RemoteViews替换普通通知栏

首先,我们要先定义一个用于在通知栏展示的布局文件

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:background="#56ac58"
  5. android:gravity="center"
  6. android:orientation="vertical">
  7. <TextView
  8. android:id="@+id/tv"
  9. android:layout_width="match_parent"
  10. android:layout_height="100dp"
  11. android:gravity="center"
  12. android:text="hello world" />
  13. </LinearLayout>

以下为修改后的发送通知的代码(注意:所有类型的通知都必须设置小图标)

  1. private fun sendNotification() {
  2. val manager = notificationManager
  3. val builder = NotificationCompat.Builder(this)
  4. val view = RemoteViews(packageName, R.layout.notification_layout)
  5. builder.setSmallIcon(R.drawable.ic_launcher)
  6. .setDefaults(0)
  7. .setAutoCancel(true)
  8. .setContent(view)
  9. val notification = builder.build()
  10. manager.notify(0, notification)
  11. }

这是弹出的对话框的样子

处理点击事件

现在我们如何达到上述点击后打开浏览器的效果呢

  1. private fun sendNotification() {
  2. val manager = notificationManager
  3. val builder = NotificationCompat.Builder(this)
  4. val view = RemoteViews(packageName, R.layout.notification_layout)
  5. builder.setSmallIcon(R.drawable.ic_launcher)
  6. .setDefaults(0)
  7. .setAutoCancel(true)
  8. .setContent(view)
  9. val intent = Intent()
  10. intent.action = "android.intent.action.VIEW"
  11. val uri = Uri.parse("http://blog.csdn.net/qq_32583189/")
  12. intent.data = uri
  13. val pIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
  14. view.setOnClickPendingIntent(R.id.tv, pIntent)
  15. val notification = builder.build()
  16. manager.notify(0, notification)
  17. }

这里解释一下view.setOnClickPendingIntent(R.id.tv, pIntent)里面第一个参数的意思是该点击事件的接收控件,这里设置的是当TextView被点击的时候打开浏览器。

三、RemoteViews如何更新View

假如我们向每点通知后更新其中的UI应该怎么办?其实通知和我们的应用是两个不同的进程,也就是说通知和我们的进程的内存是不能共享的,而RemoteViews的作用就是用来跨进程发送View,所以我们不能通过直接操作通知栏的内存来修改View,只能通过RemoteViews提供的操作方法来更新

这是更新后的java代码,注意此时需要将配置文件中的启动模式设计为单例模式<activity android:launchMode="singleInstance">
下面代码所做的工作就是当点击TextView的使用重新显示当前Activity并调用onNewIntent方法,于是就产生了两种效果,一种是Activity已经退出,此时重新打开Activity并不会调用onNewIntent方法所以显示的字仍是Hello World,如果Activity没有退出,则会显示新字符串hello remoteViews

  1. val Activity.notificationManager: NotificationManager
  2. get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
  3. class MainActivity : AppCompatActivity() {
  4. private var viewHolder = MainViewHolder()
  5. override fun onCreate(savedInstanceState: Bundle?) {
  6. super.onCreate(savedInstanceState)
  7. setContentView(R.layout.activity_main)
  8. viewHolder.bind(this)
  9. viewHolder.send?.setOnClickListener { view ->
  10. sendNotification("hello world")
  11. }
  12. }
  13. private fun sendNotification(message: String) {
  14. val manager = notificationManager
  15. val builder = NotificationCompat.Builder(this)
  16. val view = RemoteViews(packageName, R.layout.notification_layout)
  17. builder.setSmallIcon(R.drawable.ic_launcher)
  18. .setDefaults(0)
  19. .setAutoCancel(true)
  20. .setContent(view)
  21. val intent = Intent()
  22. intent.setClass(this, MainActivity::class.java)
  23. val pIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
  24. view.setTextViewText(R.id.tv, message)
  25. view.setOnClickPendingIntent(R.id.tv, pIntent)
  26. val notification = builder.build()
  27. manager.notify(0, notification)
  28. }
  29. override fun onNewIntent(intent: Intent?) {
  30. sendNotification("hello remoteViews")
  31. }
  32. }

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注