Skip to content

Commit

Permalink
新增支持 Toast 排队显示策略
Browse files Browse the repository at this point in the history
新增支持局部设置 Toast 显示样式
  • Loading branch information
getActivity committed Nov 6, 2022
1 parent 20bbe4a commit 535ebed
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 200 deletions.
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/issue_template_bug.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ assignees: getActivity

* 出现问题的安卓版本【必填】:请填写出现问题的 Android 版本

* 问题信息的来源渠道【必填】:请填写问题的来源(例如:自己遇到的/Bugly 看到的/用户反馈等等)

#### 请回答

* 是部分机型还是所有机型都会出现【必答】:部分/全部(例如:某为,某 Android 版本会出现)
Expand Down
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# 吐司框架

* 项目地址:[Github](https://github.com/getActivity/ToastUtils)[码云](https://gitee.com/getActivity/ToastUtils)
* 项目地址:[Github](https://github.com/getActivity/ToastUtils)

* 博客地址:[只需体验三分钟,你就会跟我一样,爱上这款 Toast](https://www.jianshu.com/p/9b174ee2c571)

* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/ToastUtils/releases/download/10.5/ToastUtils.apk)
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/ToastUtils/releases/download/11.0/ToastUtils.apk)

![](picture/demo_code.png)

Expand Down Expand Up @@ -47,7 +47,7 @@ android {
dependencies {
// 吐司框架:https://github.com/getActivity/ToastUtils
implementation 'com.github.getActivity:ToastUtils:10.5'
implementation 'com.github.getActivity:ToastUtils:11.0'
}
```

Expand All @@ -72,6 +72,7 @@ public class XxxApplication extends Application {
// 显示 Toast
ToastUtils.show(CharSequence text);
ToastUtils.show(int id);
ToastUtils.show(ToastParams params);

// debug 模式下显示 Toast
ToastUtils.debugShow(int id);
Expand Down Expand Up @@ -140,15 +141,20 @@ ToastUtils.init(this, new ToastStrategy() {

| 功能或细节 | [ToastUtils](https://github.com/getActivity/ToastUtils) | [AndroidUtilCode](https://github.com/Blankj/AndroidUtilCode) | [Toasty](https://github.com/GrenderG/Toasty) |
| :----: | :------: | :-----: | :-----: |
| 对应版本 | 10.5 | 1.30.6 | 1.5.0 |
| 对应版本 | 11.0 | 1.30.6 | 1.5.0 |
| issues 数 | [![](https://img.shields.io/github/issues/getActivity/ToastUtils.svg)](https://github.com/getActivity/ToastUtils/issues) | [![](https://img.shields.io/github/issues/Blankj/AndroidUtilCode.svg)](https://github.com/Blankj/AndroidUtilCode/issues) | [![](https://img.shields.io/github/issues/GrenderG/Toasty.svg)](https://github.com/GrenderG/Toasty/issues) |
| **aar 包大小** | 29 KB | 500 KB | 50 KB |
| **aar 包大小** | 31 KB | 500 KB | 50 KB |
| 框架维护状态 | **维护中** | 停止维护 | 停止维护 |
| **调用代码定位** ||||
| 支持在子线程中调用显示 ||||
| 支持全局设置统一 Toast 样式 ||||
| 处理 Toast 在 Android 7.1 崩溃的问题 ||||
| 兼容通知栏权限关闭后 Toast 显示不出来的问题 ||||
| 适配 Android 11 不能在后台显示 Toast 的问题 ||||
| **支持在子线程中调用显示** ||||
| 支持设置**局部** Toast 样式 ||||
| 支持设置**全局** Toast 样式 ||||
| 支持 Toast **即显即示** ||||
| 支持 Toast **排队显示** ||||
| 支持 Toast **延迟显示** ||||
| **处理 Toast 在 Android 7.1 崩溃的问题** ||||
| **兼容通知栏权限关闭后 Toast 显示不出来的问题** ||||
| **适配 Android 11 不能在后台显示 Toast 的问题** ||||

#### 调用代码定位功能介绍

Expand All @@ -170,7 +176,7 @@ ToastUtils.init(this, new ToastStrategy() {
* 这个问题的出现是因为原生 Toast 的显示要通过 NMS(NotificationManagerService) 才会 addView 到 Window 上面,而在 NMS 中有一个 `static final boolean ENABLE_BLOCKED_TOASTS = true` 的字段,当这个常量值为 true 时,会触发 NMS 对应用通知栏权限的检查,如果没有通知栏权限,那么这个 Toast 将会被 NMS 所拦截,并输出 `Suppressing toast from package` 日志信息,而小米手机没有这个问题是因为它是将 `ENABLE_BLOCKED_TOASTS` 字段值修改成 `false`,所以就不会触发对通知栏权限的检查,另外我为什么会知道有这个事情?因为我曾经和一名 MIUI 工程师一起确认过这个事情。

* 框架处理这个问题的方式有两种,先判断当前应用是否处于前台状态,如果是则使用自定义的 WindowManager 代替 Toast 来显示,如果当前应用处于后台状态,则会通过 Hook Toast 中的 INotificationManager 接口,将 enqueueToast 方法传递的包名参数修改成 `android` 来欺骗 NotificationManagerService,因为 NotificationManagerService 已经将 `android` 包名的应用纳入白名单,会自动放行,需要注意的是,这种方式在 Android 10 上面已经失效了,已经被系统纳入反射黑名单,但是好消息是,通过查看和对比 NotificationManagerService 源码发现,这个问题(关闭通知栏权限后无法在前台弹 Toast 的问题)已经在 Android 10.0 的版本上面被修复了,所以框架只在 Android 9.0 及以下版本并且在关闭了通知栏权限的情况下才去 Hook INotificationManager,另外我还找到了官方关于这块的代码提交记录:[Always allow toasts from foreground apps](https://cs.android.com/android/_/android/platform/frameworks/base/+/58b2453ed69197d765c7254241d9966ee49a3efb),大家可以感兴趣可以看看,还有一个问题,如果你想在 Android 10 之后仍然能在后台显示 Toast,请保证应用的通知栏权限或者悬浮窗权限处于开启的状态。
* 框架处理这个问题的方式有两种,先判断当前应用是否处于前台状态,如果是则使用自定义的 WindowManager 代替 Toast 来显示,如果当前应用处于后台状态,则会通过 Hook Toast 中的 INotificationManager 接口,将 enqueueToast 方法传递的包名参数修改成 `android` 来欺骗 NotificationManagerService,因为 NotificationManagerService 已经将 `android` 包名的应用纳入白名单,会自动放行,需要注意的是,这种方式在 Android 10 上面已经失效了,已经被系统纳入反射黑名单,但是好消息是,通过查看和对比 NotificationManagerService 源码发现,这个问题(关闭通知栏权限后无法在前台弹 Toast 的问题)已经在 Android 10.0 的版本上面被修复了,所以框架只在 Android 9.0 及以下版本并且在关闭了通知栏权限的情况下才去 Hook INotificationManager,另外我还找到了官方关于这块的代码提交记录:[Always allow toasts from foreground apps](https://cs.android.com/android/_/android/platform/frameworks/base/+/58b2453ed69197d765c7254241d9966ee49a3efb),大家可以感兴趣可以看看,还有一个问题,如果你想在 Android 10 之后仍然能在后台显示 Toast,请保证应用的通知栏权限或者悬浮窗权限处于开启的状态,如果你一定要求在后台要 100% 能显示 Toast,请保证应用有悬浮窗权限,因为在某些厂商的手机上,就算有通知栏权限也是无法在后台显示 Toast,例如我用 HarmonyOS 2.0 测试就不行,所以具体要看产品怎么斟酌

#### Android 11 不能在后台显示 Toast 的问题介绍

Expand Down Expand Up @@ -253,6 +259,8 @@ new Toast

* Android 代码规范:[AndroidCodeStandard](https://github.com/getActivity/AndroidCodeStandard) ![](https://img.shields.io/github/stars/getActivity/AndroidCodeStandard.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidCodeStandard.svg)

* Android 资源大汇总:[AndroidIndex](https://github.com/getActivity/AndroidIndex) ![](https://img.shields.io/github/stars/getActivity/AndroidIndex.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidIndex.svg)

* Android 开源排行榜:[AndroidGithubBoss](https://github.com/getActivity/AndroidGithubBoss) ![](https://img.shields.io/github/stars/getActivity/AndroidGithubBoss.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidGithubBoss.svg)

* Studio 精品插件:[StudioPlugins](https://github.com/getActivity/StudioPlugins) ![](https://img.shields.io/github/stars/getActivity/StudioPlugins.svg) ![](https://img.shields.io/github/forks/getActivity/StudioPlugins.svg)
Expand Down
12 changes: 7 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "com.hjq.toast.demo"
minSdkVersion 16
targetSdkVersion 31
versionCode 1050
versionName "10.5"
versionCode 1100
versionName "11.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

Expand Down Expand Up @@ -62,14 +62,16 @@ dependencies {
implementation 'com.google.android.material:material:1.4.0'

// 标题栏框架:https://github.com/getActivity/TitleBar
implementation 'com.github.getActivity:TitleBar:9.3'
implementation 'com.github.getActivity:TitleBar:9.5'

// 权限请求框架:https://github.com/getActivity/XXPermissions
implementation 'com.github.getActivity:XXPermissions:13.6'
implementation 'com.github.getActivity:XXPermissions:16.2'

// 悬浮窗框架:https://github.com/getActivity/XToast
implementation 'com.github.getActivity:XToast:8.5'

// 内存泄漏捕捉:https://github.com/square/leakcanary
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'

implementation 'com.tencent.mars:mars-xlog:1.2.6'
}
40 changes: 31 additions & 9 deletions app/src/main/java/com/hjq/toast/demo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
import com.hjq.bar.TitleBar;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.hjq.toast.ToastParams;
import com.hjq.toast.ToastStrategy;
import com.hjq.toast.ToastUtils;
import com.hjq.toast.style.BlackToastStyle;
import com.hjq.toast.style.CustomViewToastStyle;
import com.hjq.toast.style.WhiteToastStyle;
import com.hjq.xtoast.XToast;

Expand Down Expand Up @@ -44,16 +47,22 @@ public void onTitleClick(TitleBar titleBar) {
});
}

public void show1(View v) {
public void showToast(View v) {
ToastUtils.show("我是普通的 Toast");
}

public void show2(View v) {
public void showThriceToast(View v) {
for (int i = 0; i < 3; i++) {
ToastUtils.show("我是第 " + (i + 1) + " 个 Toast");
}
}

public void delayShowToast(View v) {
ToastUtils.delayedShow("我是延迟 2 秒显示的 Toast", 2000);
}

@SuppressWarnings("AlibabaAvoidManuallyCreateThread")
public void show3(View v) {
public void threadShowToast(View v) {
new Thread(new Runnable() {

@Override
Expand All @@ -63,23 +72,36 @@ public void run() {
}).start();
}

public void show4(View v) {
public void switchToastStyleToWhite(View v) {
ToastUtils.setStyle(new WhiteToastStyle());
ToastUtils.show("动态切换白色吐司样式成功");
}

public void show5(View v) {
public void switchToastStyleToBlack(View v) {
ToastUtils.setStyle(new BlackToastStyle());
ToastUtils.show("动态切换黑色吐司样式成功");
}

public void show6(View v) {
public void customLocalToastStyle(View v) {
ToastParams params = new ToastParams();
params.text = "我是自定义布局的 Toast(局部生效)";
params.style = new CustomViewToastStyle(R.layout.toast_custom_view);
ToastUtils.show(params);
}

public void customGlobalToastStyle(View v) {
ToastUtils.setView(R.layout.toast_custom_view);
ToastUtils.setGravity(Gravity.CENTER);
ToastUtils.show("自定义 Toast 布局");
ToastUtils.show("我是自定义布局的 Toast(全局生效)");
}

public void switchToastStrategy(View v) {
ToastUtils.setStrategy(new ToastStrategy(ToastStrategy.SHOW_STRATEGY_TYPE_QUEUE));
ToastUtils.show("切换到排队显示策略成功,请点击下方文本来体验效果");
findViewById(R.id.tv_main_thrice_show).setVisibility(View.VISIBLE);
}

public void show7(View v) {
public void toBackgroundShowToast(View v) {
Snackbar.make(getWindow().getDecorView(), "温馨提示:安卓 10 在后台显示 Toast 需要有通知栏权限或者悬浮窗权限的情况下才可以显示", Snackbar.LENGTH_SHORT).show();

v.postDelayed(new Runnable() {
Expand Down Expand Up @@ -107,7 +129,7 @@ public void run() {
}, 3000);
}

public void show8(View v) {
public void combinationXToastShow(View v) {
new XToast<>(this)
.setDuration(1000)
// 将 ToastUtils 中的 View 转移给 XToast 来显示
Expand Down
59 changes: 43 additions & 16 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,63 +34,90 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="show1"
android:onClick="showToast"
android:text="简简单单显示 Toast" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show2"
android:layout_marginTop="15dp"
android:onClick="delayShowToast"
android:text="延迟 2 秒显示 Toast" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show3"
android:layout_marginTop="15dp"
android:onClick="threadShowToast"
android:text="在子线程中显示吐司" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show4"
android:layout_marginTop="15dp"
android:onClick="switchToastStyleToWhite"
android:text="切换吐司的样式为白色" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show5"
android:layout_marginTop="15dp"
android:onClick="switchToastStyleToBlack"
android:text="切换吐司的样式为黑色" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show6"
android:text="点我自定义 Toast 布局" />
android:layout_marginTop="15dp"
android:onClick="customLocalToastStyle"
android:text="自定义 Toast 布局(局部生效)" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show7"
android:layout_marginTop="15dp"
android:onClick="customGlobalToastStyle"
android:text="自定义 Toast 布局(全局生效)" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:onClick="switchToastStrategy"
android:text="切换成 Toast 排队显示策略" />

<TextView
android:id="@+id/tv_main_thrice_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:onClick="showThriceToast"
android:text="点我连续显示 3 个 Toast"
android:visibility="gone"
tools:visibility="visible" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:onClick="toBackgroundShowToast"
android:text="在后台状态下显示 Toast" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:onClick="show8"
android:layout_marginTop="15dp"
android:onClick="combinationXToastShow"
android:text="搭配 XToast 悬浮窗框架" />

</LinearLayout>
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/res/layout/toast_custom_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
android:padding="10dp">

<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher" />

<TextView
Expand All @@ -18,5 +18,5 @@
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="#FFFFFFFF"
android:textSize="16sp" />
android:textSize="14sp" />
</LinearLayout>
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ android {

defaultConfig {
minSdkVersion 14
versionCode 1050
versionName "10.5"
versionCode 1100
versionName "11.0"
}

// 使用 JDK 1.8
Expand Down
Loading

0 comments on commit 535ebed

Please sign in to comment.