diff --git a/.github/ISSUE_TEMPLATE/issue_template_bug.md b/.github/ISSUE_TEMPLATE/issue_template_bug.md index c23ccae..3ee27d2 100644 --- a/.github/ISSUE_TEMPLATE/issue_template_bug.md +++ b/.github/ISSUE_TEMPLATE/issue_template_bug.md @@ -22,6 +22,8 @@ assignees: getActivity * 出现问题的安卓版本【必填】:请填写出现问题的 Android 版本 +* 问题信息的来源渠道【必填】:请填写问题的来源(例如:自己遇到的/Bugly 看到的/用户反馈等等) + #### 请回答 * 是部分机型还是所有机型都会出现【必答】:部分/全部(例如:某为,某 Android 版本会出现) diff --git a/README.md b/README.md index 09a58ad..c45142d 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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' } ``` @@ -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); @@ -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 的问题** | ✅ | ❌ | ❌ | #### 调用代码定位功能介绍 @@ -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 的问题介绍 @@ -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) diff --git a/app/build.gradle b/app/build.gradle index 5ab94b7..e483d75 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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" } @@ -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' } \ No newline at end of file diff --git a/app/src/main/java/com/hjq/toast/demo/MainActivity.java b/app/src/main/java/com/hjq/toast/demo/MainActivity.java index f219571..c18ef5a 100644 --- a/app/src/main/java/com/hjq/toast/demo/MainActivity.java +++ b/app/src/main/java/com/hjq/toast/demo/MainActivity.java @@ -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; @@ -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 @@ -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() { @@ -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 来显示 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index dc79f2e..8e0d888 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -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" />