本人为android的新手,如果有写的不对的地方,希望各路大神多多指教哈。。。
我们经常遇见的Noticication的例子,莫过于使用qq时,手机状态栏会显示有多少条消息处于未读状态。Notification类就是实现这样的功能。
Notification通知的布局有两种:
1.使用系统默认的布局
2.使用自定义的布局
首先使用系统默认布局:
1.首先获取NotificationManager对象。NotificationManager是系统提供的服务
2.创建Notification类对象
Notification notification = new Notification.Builder(MainActivity.this) //1 .setAutoCancel(true) //2 .setTicker("新消息...") //3 .setSmallIcon(R.drawable.notificationsmall) //4 //5 .setContentTitle("笑递消息") //5 .setContentText("笑递笑递内容") //6 .setContentIntent(pendingIntent) //7 .setNumber(i) //8 .setLargeIcon(bitmap) //9 .setWhen(System.currentTimeMillis()) //10 .build(); //11根据上图中的每一行后面的数字匹配
对应上面的3
这里的3是对应设置的数据,注解第八行,3上面的就是第10行的setWhen
相应的解释:
2.设置可以在下拉状态栏中通过滑动取消通知
4.设置小图标一定要有
7.设置在下拉状态栏点击通知后跳转到相应的界面
这里使用的是PendingIntent.
下面解释一下PendingIntent 和Intent的区别
Intent和PendingIntent的区别,PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来处理马上发生的意图。而对于通知来说,它是一个系统级的全局的通知,并不确定这个意图被执行的时间。当在应用外部执行PendingIntent时,因为它保存了触发App的Context,使得外部App可以如果当前App一样执行PendingIntent里的Intent,就算执行时触发通知的App已经不存在了,也能通过存在PendingIntent里的Context照常执行Intent,并且还可以处理Intent所带来的额外的信息。
PendingIntent提供了多个静态的getXxx()方法,用于获得适用于不同场景的PendingIntent对象。一般需要传递的几个参数都很常规,只介绍一个flag参数,用于标识PendingIntent的构造选择:
FLAG_CANCEL_CURRENT:如果构建的PendingIntent已经存在,则取消前一个,重新构建一个。
FLAG_NO_CREATE:如果前一个PendingIntent已经不存在了,将不再构建它。
FLAG_ONE_SHOT:表明这里构建的PendingIntent只能使用一次。
FLAG_UPDATE_CURRENT:如果构建的PendingIntent已经存在,则替换它,常用。
下面说明如何构建PendingIntent对象:
Intent intent = new Intent(MainActivity.this,Main2Activity.class); Intent intent2 = new Intent(MainActivity.this,Main3Activity.class); /** * 表示启动两个,是按照顺序启动的 * */ Intent intentlist[] = new Intent[]{intent,intent2}; PendingIntent pendingIntent = PendingIntent.getActivities(MainActivity.this,0, intentlist,PendingIntent.FLAG_UPDATE_CURRENT);1.首先定义相应的Intent
2.然后定义Intent[]数组,把Intent对象放到数组中。数组中所有Intent在点击通知后都会执行,是按照顺序执行
3.通过PendingIntent的get方法获取PendingIntent对象。
四个参数的意思:
最后一步使用NotificationManager通知我们定义的Notification对象
在这里,大家可能发现有一个大写的常量,这个是我定义的
定义这个的用途主要是唯一的标志这个Notification通知。
当NotificationManager使用同样的标志通知Notification对象时,之前的是这个标志的Notification对象就会被现在这个Notification对象更新。
也就是说同一个标志只能发送一个通知,后发送的会更新之前发送的。
但是使用不同的标志可以再发送另一个通知。
if(i==1) nm.notify(111,notification); else nm.notify(NOTIFICATION_ID,notification);
使用自定义的布局实现Notification
- 通知也可以使用自定义的XML来自定义样式,但是对于通知而言,因为它的全局性,并不能简单的通过inflate膨胀出一个View,因为可能触发通知的时候,响应的App已经关闭,无法获取当指定的XML布局文件。所以需要使用单独的一个RemoteViews类来操作。
RemoteViews,描述了一个视图层次的结构,可以显示在另一个进程。层次结构也是从布局文件中“膨胀”出一个视图,这个类,提供了一些基本的操作求改其膨胀的内容。
RemoteViews提供了多个构造函数,一般使用RemoteViews(String packageName,int layoutId)。第一个参数为包的名称,第二个为layout资源的Id。当获取到RemoteViews对象之后,可以使用它的一系列setXxx()方法通过控件的Id设置控件的属性。最后使用NotificationCompat.Builder.setContent(RemoteViews)方法设置它到一个Notification中。- 例子代码:
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.layout); remoteViews.setImageViewResource(R.id.id_image_view,R.drawable.notification); remoteViews.setTextViewText(R.id.id_txt1,"文本1"); remoteViews.setTextViewText(R.id.id_txt2,"文本2"); remoteViews.setTextViewText(R.id.id_txt3,"文本3"); Intent intent = new Intent(MainActivity.this,Main2Activity.class); //Intent额外绑定的数据 intent.putExtra("data","shuju1"); Intent intent2 = new Intent(MainActivity.this,Main3Activity.class); intent2.putExtra("data","shuju2"); Intent intentlist[] = new Intent[]{intent,intent2}; PendingIntent pendingIntent = PendingIntent.getActivities(MainActivity.this,0, intentlist,PendingIntent.FLAG_UPDATE_CURRENT); Notification notification = new Notification.Builder(MainActivity.this) .setAutoCancel(true) .setTicker("新消息...") .setSmallIcon(R.drawable.notificationsmall)//就算是自定义的视图也必须要 .setContent(remoteViews) .setContentIntent(pendingIntent).build(); if(i==1) nm.notify(111,notification); else nm.notify(NOTIFICATION_ID,notification); i++;从上面的代码可以看出,使用自定义布局时
.setContentTitle("笑递消息") .setContentText("笑递笑递内容") .setNumber(i) .setLargeIcon(bitmap) .setWhen(System.currentTimeMillis())点击通知后看到的内容:
回到的intentlist数组的第一个intent中封装的activity。这里也验证的上面的说法。会将intentlist中的intent所包含的activity依次打开。
下面上整个程序的代码:
主程序类:
package com.example.notificationtest;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RemoteViews;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private final int NOTIFICATION_ID=0x123;
private NotificationManager nm;
private Button btn1;
private Button btn2;
private Button btn3;
private Bitmap bitmap = null;
private int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
initView();
initEvent();
}
private void initEvent() {
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
Intent intent2 = new Intent(MainActivity.this,Main3Activity.class);
/**
* 表示启动两个,是按照顺序启动的
*
*/
Intent intentlist[] = new Intent[]{intent,intent2};
PendingIntent pendingIntent = PendingIntent.getActivities(MainActivity.this,0,
intentlist,PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(MainActivity.this)
.setAutoCancel(true)
.setTicker("新消息...")
.setSmallIcon(R.drawable.notificationsmall) //5
.setContentTitle("笑递消息")
.setContentText("笑递笑递内容")
.setNumber(i)
.setLargeIcon(bitmap)
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.build();
if(i==1)
nm.notify(111,notification);
else
nm.notify(NOTIFICATION_ID,notification);
i++;
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.layout);
remoteViews.setImageViewResource(R.id.id_image_view,R.drawable.notification);
remoteViews.setTextViewText(R.id.id_txt1,"文本1");
remoteViews.setTextViewText(R.id.id_txt2,"文本2");
remoteViews.setTextViewText(R.id.id_txt3,"文本3");
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("data","shuju1");
Intent intent2 = new Intent(MainActivity.this,Main3Activity.class);
intent2.putExtra("data","shuju2");
Intent intentlist[] = new Intent[]{intent,intent2};
PendingIntent pendingIntent = PendingIntent.getActivities(MainActivity.this,0,
intentlist,PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(MainActivity.this)
.setAutoCancel(true)
.setTicker("新消息...")
.setSmallIcon(R.drawable.notificationsmall)//就算是自定义的视图也必须要
.setContent(remoteViews)
.setContentIntent(pendingIntent).build();
if(i==1)
nm.notify(111,notification);
else
nm.notify(NOTIFICATION_ID,notification);
i++;
}
});
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nm.cancel(NOTIFICATION_ID);
nm.cancel(111);
Toast.makeText(MainActivity.this,""+NOTIFICATION_ID,Toast.LENGTH_SHORT).show();
}
});
}
private void initView() {
btn1 = (Button) findViewById(R.id.id_btn1);
btn2 = (Button) findViewById(R.id.id_btn2);
btn3 = (Button) findViewById(R.id.id_btn3);
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.notification);
}
}
第二个activity
package com.example.notificationtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextPaint;
import android.widget.TextView;
public class Main2Activity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
textView = (TextView) findViewById(R.id.id_shuju1);
textView.setText(getIntent().getStringExtra("data"));
}
}
第三个activity
package com.example.notificationtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class Main3Activity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
textView = (TextView) findViewById(R.id.id_shuju2);
textView.setText(getIntent().getStringExtra("data"));
}
}
主布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/id_btn1"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="简单通知"/>
<Button
android:id="@+id/id_btn2"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="自定义通知"/>
<Button
android:id="@+id/id_btn3"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="取消通知"/>
</LinearLayout>
第二个activity布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/id_shuju1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="diergejiemian"/>
</LinearLayout>
第三个activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/id_shuju2"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="第三个界面"/>
</LinearLayout>
自定义通知的布局文件layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/id_image_view"
android:layout_width="64dp"
android:layout_height="64dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="64dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_marginRight="10dp">
<TextView
android:id="@+id/id_txt1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:id="@+id/id_txt2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:id="@+id/id_txt3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
源码