通过实例学安卓开发
序
大家如果是要跟着我文章来实践的话,还是从头看到尾,依据已经给出的截图及实现过程先自行完成,源码贴在最后,各有各的写法,只要能实现都是了不起的。加油吧,一起努力!
实例
题目
通知Notification的发布与清除(含快显信息Toast的使用)。
程序结果展示界面
涉及到的知识点
通知与通知类Notification
在Android中,通知Notification能够通过多种方式提供给用户,例如,发出声音,设备震动,或在位于手机屏幕顶部的状态栏里放置一个持久的图标等。
当手指从状态栏向下滑过时,会展开所有的通知信息,能够查看到通知的标题和内容等信息(如未查看的短信),还能清除通知;当手指从下方向上滑动时将隐藏通知。
当手机短信到来或来电未接时,都会有应用程序自动产生一个通知。系统时间的数字文本、手机网络连接方式的图标、手机充电指示图标等表示系统特定的状态信息,都在手机的状态栏中显示。
注意:通知Notification不属于任何Activity。
Android系统提供了对通知进行描述的类Notification,Android API 16 及以后的版本都推荐使用Notification的内部构造器类Builder来创建一个Notification对象,Notification类封装了在状态栏里设置发布通知的标题、内容、时间、通知到来时的提示音和标题前的小图标等。
注意:作为消息提醒机制,Notification与Toast类似,但Toast位于android.widget包;而Notification不属于Activity,它位于android.app包,需要使用特定的管理器进行管理。
通知管理类NotificationManager
通知是由NotificationManager类型的对象进行管理的,而NotificationManager对象需要调用系统服务Context.NOTIFICATION_SERVICE来创建,代码如下:
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager nm = (NotificationManager)getSystemService(ns);
通知管理器类NotificationManager主要提供了发通知、取消通知两个方法。
实现过程
- 新建名为
Notification
的应用工程 - 修改默认布局文件
activity_main.xml
,采用垂直线性布局,依次添加两个命令按钮 - 编写程序
MainActivity.java
源码
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="产生一个通知"
android:id="@+id/btn1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消指定的通知"
android:id="@+id/btn2"/>
</LinearLayout>
MainActivity.java
package com.example.myapplication;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private NotificationManager notificationManager;
private Notification notification;
private static final int NOTIFICATION_ID = 1;
private Button notifyButton;
private Button cancelButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
notifyButton=(Button) this.findViewById(R.id.btn1);
notifyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String ns = Context.NOTIFICATION_SERVICE;
notificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.ic_launcher_background;
long when = System.currentTimeMillis();
Notification.Builder builder = new Notification.Builder(MainActivity.this);
builder.setContentTitle("我是通知的标题")
.setContentText("我是通知的内容")
.setSmallIcon(icon)
.setWhen(when)
.setDefaults(Notification.DEFAULT_SOUND);
notification = builder.build();
notificationManager.notify(NOTIFICATION_ID,notification);
}
});
cancelButton=(Button) this.findViewById(R.id.btn2);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
notificationManager.cancel(NOTIFICATION_ID);
Toast.makeText(MainActivity.this,"已经取消了指定的通知,可查验!",Toast.LENGTH_LONG).show();
}
});
}
}
可能遇到的错误及解决方案
如果你按照上述代码敲完后,出现如下错误,则说明:
在Android8.0 (API26)以前手机上运行通知栏要么全部屏蔽通知栏(防止骚扰),要么全部正常运行通知栏。我们用Notification.Builder类实现是完全没有问题的。
自从Android8.0(API26)出现时,为了让用户更好的体验,于是新增通道功能(也就是NotificationChannel类),通过通道功能(也就是NotificationChannel类)能够让用户有选择的权利,用户可以设置屏蔽无关重要的垃圾通告,用户也可以设置开启选择重要的通告。
也就是说我们在Android8.0(API26)及以上的版本实现通告栏功能用Notification.Builder类,是无法正常运行的就会导致我们出现报错现象出现:Developer warning for package "com.example.my"Failed to post notification on channel ‘default’ See log for more details的错误问题
解决方案
将MainActivity.java文件修改如下:
package com.example.myapplication;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private NotificationManager notificationManager;
private Notification notification;
private static final int NOTIFICATION_ID = 1;
private Button notifyButton;
private Button cancelButton;
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
notifyButton=(Button) this.findViewById(R.id.btn1);
notifyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String id = "channel_1";
String description = "123";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(id,description,importance);
String ns = Context.NOTIFICATION_SERVICE;
notificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.ic_launcher_background;
long when = System.currentTimeMillis();
notificationManager.createNotificationChannel(mChannel);
Notification.Builder builder = new Notification.Builder(MainActivity.this,id);
builder.setContentTitle("我是通知的标题")
.setContentText("我是通知的内容")
.setSmallIcon(icon)
.setWhen(when)
.setDefaults(Notification.DEFAULT_SOUND);
notification = builder.build();
notificationManager.notify(NOTIFICATION_ID,notification);
}
});
cancelButton=(Button) this.findViewById(R.id.btn2);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
notificationManager.cancel(NOTIFICATION_ID);
Toast.makeText(MainActivity.this,"已经取消了指定的通知,可查验!",Toast.LENGTH_LONG).show();
}
});
}
}
注意
获取通道(channel)之前一定要先获取系统通知的服务,否则运行时会闪退,按钮的监听事件分清楚onClick和id。