# Gradle引用
Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
dependencies {
implementation 'com.github.Dovar66:DToast:1.1.7'
//implementation 'com.github.Dovar66:DToast:1.1.8'//for androidx
}
# 使用示例
//使用默认布局
DToast.make(mContext)
.setText(R.id.tv_content_default, msg)
.setGravity(Gravity.BOTTOM | Gravity.CENTER, 0, 30)
.show();
//通过setView()设置自定义的Toast布局
DToast.make(mContext)
.setView(View.inflate(mContext, R.layout.layout_toast_center, null))
.setText(R.id.tv_content_custom, msg)
.setGravity(Gravity.CENTER, 0, 0)
.showLong();
# 正文分析
先看看使用系统Toast存在的问题:
1.当通知权限被关闭时在华为等手机上Toast不显示;
2.Toast的队列机制在不同手机上可能会不相同;
3.Toast的BadTokenException问题;
当发现系统Toast存在问题时,不少同学都会采用自定义的TYPE_TOAST弹窗来实现相同效果。虽然大部分情况下效果都是
OK的,但其实TYPE_TOAST弹窗依然存在兼容问题:
4.Android8.0之后的token null is not valid问题;
5.Android7.1之后,不允许同时展示两个TYPE_TOAST弹窗(实测部分机型问题)。
那么,DToast使用的解决方案是:
1.通知权限未被关闭时,使用SystemToast(修复了问题2和问题3的系统Toast);
2.通知权限被关闭时,如果系统版本为Android8.0/8.1则通过hook绕过通知栏权限,否则使用DovaToast(自定义的TYPE_TOAST弹窗);
3.当使用DovaToast出现token null is not valid时,尝试使用ActivityToast(自定义的TYPE_APPLICATION_ATTACHED_DIALOG
弹窗,只有当传入Context为Activity时,才会启用ActivityToast).
相信不少同学旧项目中封装的ToastUtil都是直接使用的ApplicationContext作为上下文,然后在需要弹窗的时候直接就是ToastUtil.show(str)
,这样的使用方式对于我们来说是最方便的啦。
当然,使用DToast你也依然可以沿用这种封装方式,但这种方式在下面这个场景中可能会无法成功展示出弹窗(该场景下原生Toast也一样无法弹出),
不过请放心不会导致应用崩溃,而且这个场景出现的概率较小,有以下几个必要条件:
1.你的应用设置的targetSdkVersion>=26.
2.通知栏权限被关闭(通知栏权限默认都是打开的).
3.非MIUI设备(MIUI弹吐司不需要通知栏权限).
4.运行设备的系统版本在Android9.0及以上。
所以,如果你的应用**targetSdkVersion>=26**,又想要保证在所有场景下都能正常展示弹窗,那么请在DToast.make(context)时传入Activity作为上下文,这样在该场景下DToast会启用ActivityToast展示出弹窗。而targetSdkVersion小于26的同学可以放心使用ApplicationContext创建DToast。
想了解为什么需要区别对待targetSdkVersion26+?[点击查看API26做了什么](https://developer.android.com/reference/android/os/Build.VERSION_CODES#O)
而如果你还不了解targetSdkVersion [点击这里查看](https://chinagdg.org/2016/01/picking-your-compilesdkversion-minsdkversion-targetsdkversion/)
接下来再详细分析下上面提到的五个问题:
## 问题一:关闭通知权限时Toast不显示
看下方Toast源码中的show()方法,通过AIDL获取到INotificationManager,并将接下来的显示流程控制权
交给NotificationManagerService。
NMS中会对Toast进行权限校验,当通知权限校验不通过时,Toast将不做展示。
当然不同ROM中NMS可能会有不同,比如MIUI就对这部分内容进行了修改,所以小米手机关闭通知权限不会导致Toast不显示。
/**
* Show the view for the specified duration.
*/
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getOpPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
如何解决这个问题?只要能够绕过NotificationManagerService即可。
DovaToast通过使用TYPE_TOAST实现全局弹窗功能,不使用系统Toast,也没有使用NMS服务,因此不受通知权限限制。
## 问题二:系统Toast的队列机制在不同手机上可能会不相同
我找了四台设备,创建两个Gravity不同的Toast并调用show()方法,结果出现了四种展示效果:
* 荣耀5C-android7.0(只看到展示第一个Toast)
* 小米8-MIUI10(只看到展示第二个Toast,即新的Toast.show会中止当前Toast的展示)
* 红米6pro-MIUI9(两个Toast同时展示)
* 荣耀5C-android6.0(第一个TOAST展示完成后,第二个才开始展示)
造成这个问题的原因应该是各大厂商ROM中NMS维护Toast队列的逻辑有差异。
同样的,DToast内部也维护着自己的队列逻辑,保证在所有手机上使用DToast的效果相同。
DToast中多个弹窗连续出现时:
1.相同优先级时,会终止上一个,直接展示后一个;
2.不同优先级时,如果后一个的优先级更高则会终止上一个,直接展示后一个。
## 问题三:系统Toast的BadTokenException问题
* Toast有个内部类 TN(extends ITransientNotification.Stub),调用Toast.show()时会将TN传递给NMS;
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getOpPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
* 在NMS中会生成一个windowToken,并将windowToken给到WindowManagerService,WMS会暂时保存该token并用于之后的校验;
NotificationManagerService.java #enqueueToast源码:
synchronized (mToastQueue) {
int callingPid = Binder.getCallingPid();
long callingId = Binder.clearCallingIdentity();
try {
ToastRecord record;
int index = indexOfToastLocked(pkg, callback);
// If it's already in the queue, we update it in place, we don't
// move it to the end of the queue.
if (index >= 0) {
record = mToastQueue.get(index);
record.update(duration);
} else {
// Limit the number of toasts that any given package except the android
// package can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemToast) {
int count = 0;
final int N = mToastQueue.size();
for (int i=0; i<N; i++) {
final ToastRecord r = mToastQueue.get(i);
if (r.pkg.equals(pkg)) {
count++;
if (count >= MAX_PACKAGE_NOTIFICATIONS) {
Slog.e(TAG, "P
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
软件开发设计:PHP、QT、应用软件开发、系统软件开发、移动应用开发、网站开发C++、Java、python、web、C#等语言的项目开发与学习资料 硬件与设备:单片机、EDA、proteus、RTOS、包括计算机硬件、服务器、网络设备、存储设备、移动设备等 操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信是一个非常广泛的领域,它涉及到计算机科学、电子工程、数学等多个学科的知识。 云计算与大数据:数据集、包括云计算平台、大数据分析、人工智能、机器学习等,云计算是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需提供给计算机和其他设备。
资源推荐
资源详情
资源评论
收起资源包目录
同学,你的系统Toast可能需要修复一下!Fix Your Android Toast!.zip (57个子文件)
cm
gradle.properties 726B
gradle
wrapper
gradle-wrapper.jar 53KB
gradle-wrapper.properties 231B
assets
15427026676879.png 36KB
15427024538983.png 34KB
15427028677888.png 85KB
library
src
main
java
com
dovar
dtoast
DToast.java 2KB
inner
ActivityToast.java 2KB
DovaTN.java 9KB
DPriorityQueue.java 26KB
IToast.java 629B
SystemTN.java 4KB
SafelyHandlerWrapper.java 605B
SystemToast.java 9KB
DovaToast.java 7KB
DUtil.java 3KB
res
layout
layout_toast.xml 624B
drawable
corners.xml 193B
AndroidManifest.xml 108B
proguard-rules.pro 751B
build.gradle 315B
.gitignore 7B
app
src
main
java
com
dovar
dovatoast
SecondActivity.java 1KB
ToastUtil.java 1KB
MainActivity.java 1KB
res
anim
animate_translate_in.xml 225B
animate_translate_out.xml 225B
mipmap-xxhdpi
ic_launcher_round.png 10KB
ic_launcher.png 6KB
mipmap-hdpi
ic_launcher_round.png 5KB
ic_launcher.png 3KB
drawable-v24
ic_launcher_foreground.xml 2KB
mipmap-anydpi-v26
ic_launcher.xml 270B
ic_launcher_round.xml 270B
mipmap-mdpi
ic_launcher_round.png 3KB
ic_launcher.png 2KB
mipmap-xxxhdpi
ic_launcher_round.png 15KB
ic_launcher.png 9KB
mipmap-xhdpi
ic_launcher_round.png 7KB
ic_launcher.png 4KB
values
colors.xml 208B
strings.xml 69B
styles.xml 598B
layout
layout_toast_center.xml 729B
activity_second.xml 580B
activity_main.xml 965B
drawable
ic_launcher_background.xml 5KB
AndroidManifest.xml 787B
proguard-rules.pro 751B
build.gradle 574B
.gitignore 7B
gradlew.bat 2KB
build.gradle 619B
settings.gradle 27B
gradlew 5KB
.gitignore 137B
README.md 23KB
共 57 条
- 1
资源评论
妄北y
- 粉丝: 1w+
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功