精华内容
下载资源
问答
  • 解决通知关闭Toast失效问题

    千次阅读 2018-12-28 12:21:52
    下图是系统INotificationManager的实现源码 当pkg = “android”时不会校验通知关闭逻辑 所以只需要hook INotificationManager 将参数pkg始终传“android” 就行了  实现代码:  /** * Created by linjinfa...

    下图是系统INotificationManager的实现源码 当pkg = “android”时不会校验通知关闭逻辑
    所以只需要hook INotificationManager 将参数pkg始终传“android” 就行了 


    实现代码: 

    
    /**
     * Created by linjinfa on 2018/2/5.
     * email 331710168@qq.com
     */
    public class ToastUtil {
    
        private static Object iNotificationManagerObj;
    
        /**
         * @param context
         * @param message
         */
        public static void show(Context context, String message) {
            show(context, message, Toast.LENGTH_SHORT, Gravity.BOTTOM);
        }
    
        /**
         *
         * @param context
         * @param message
         */
        public static void showCenter(Context context, String message) {
            show(context, message, Toast.LENGTH_SHORT, Gravity.CENTER);
        }
    
        /**
         * @param context
         * @param message
         */
        public static void show(Context context, String message, int duration, int gravity) {
            if (TextUtils.isEmpty(message)) {
                return;
            }
            //后setText 兼容小米默认会显示app名称的问题
            Toast toast = Toast.makeText(context, null, duration);
            toast.setText(message);
            toast.setGravity(gravity, 0, 0);
            if(isNotificationEnabled(context)){
                toast.show();
            }else{
                showSystemToast(toast);
            }
        }
    
        /**
         * 业务相关的toast
         * @param context
         * @param message
         */
        public static void showCenterForBusiness(final Context context, final String message) {
            if (context != null) {
                if (context instanceof Activity) {
                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            show(context, message, Toast.LENGTH_SHORT, Gravity.CENTER);
                        }
                    });
                } else {
                    show(context, message, Toast.LENGTH_SHORT, Gravity.CENTER);
                }
            }
        }
    
        /**
         * 显示系统Toast
         */
        private static void showSystemToast(Toast toast){
            try{
                Method getServiceMethod = Toast.class.getDeclaredMethod("getService");
                getServiceMethod.setAccessible(true);
                //hook INotificationManager
                if(iNotificationManagerObj == null){
                    iNotificationManagerObj = getServiceMethod.invoke(null);
    
                    Class iNotificationManagerCls = Class.forName("android.app.INotificationManager");
                    Object iNotificationManagerProxy = Proxy.newProxyInstance(toast.getClass().getClassLoader(), new Class[]{iNotificationManagerCls}, new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //强制使用系统Toast
                            if("enqueueToast".equals(method.getName())
                                    || "enqueueToastEx".equals(method.getName())){  //华为p20 pro上为enqueueToastEx
                                args[0] = "android";
                            }
                            return method.invoke(iNotificationManagerObj, args);
                        }
                    });
                    Field sServiceFiled = Toast.class.getDeclaredField("sService");
                    sServiceFiled.setAccessible(true);
                    sServiceFiled.set(null, iNotificationManagerProxy);
                }
                toast.show();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        /**
         * 消息通知是否开启
         * @return
         */
        private static boolean isNotificationEnabled(Context context) {
            NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
            boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
            return areNotificationsEnabled;
        }
    
    }
    
    展开全文
  • } 显示效果: 因为本工程中自定义弹出框和 自定义Toast 通知都为系统级别的,所以所有的页面共享这个 单一实例。如果页面只有在推出时,询问用户 “是否退出应用” 则只需要参考自定义控件,把它 简化后,添加到 ...

    注:这篇文章主要介绍在 应用全局所有页面使用的自定义弹出框,如果仅在 MainPage 页面询问用户是否

    1、 首先介绍如何自定义弹出框

    在 WP 中,系统默认的弹出框有几个问题,首先是背景比较简陋,而且样式的扩展性比较低,另一个问题就

    是会阻碍 UI 线程。当在页面的调用下面的代码:

    if(MessageBoxResult.OK != MessageBox.Show("确定要退出吗?", "温馨提示", MessageBoxButton.OKCancel))

    {

    e.Cancel= true;

    }

    当在 MainPage 页面点击 Back 键,会弹出:

    当在10秒钟的时候,如果用户没有回馈,那么应用就会被系统终结了。

    下面开始做一个自定义的弹出框:

    1)自定义一个控件,定义在 MyDialog.xaml 文件中:

    相应的 C# 页面:

    publicMyDialog()

    {

    InitializeComponent();

    gridDialog.Visibility=System.Windows.Visibility.Collapsed;//把第一个实例赋值给全局静态对象

    if (_instance == null)

    _instance= this;

    }#region “确定”弹出框

    //用来控制异步线程中 弹出框 结果返回的时机

    private static AutoResetEvent myResetEvent = new AutoResetEvent(false);staticMessageBoxResult messageBoxResult;//用一个单一实例,使得应用中的所有页面使用同一个实例

    staticMyDialog _instance;staticMyDialog Instance

    {get{//if (_instance == null)//_instance = new MyDialog();

    return_instance;

    }

    }//用来控制当弹出框显示的时候,如果用户点击 Back 按键,则隐藏弹出框,//在 App.xaml.cs 中的 RootFrame_Navigating 事件中调用

    public static boolDialogIsOpen

    {get{if (Instance != null && Instance.gridDialog.Visibility ==Visibility.Visible)

    {

    Instance.btnCancle_Click(null, null);return true;

    }else{return false;

    }

    }

    }///

    ///显示包含指定文本和“确定”按钮的消息框///

    /// 要显示的消息

    /// 在所有情况下均为 System.Windows.MessageBoxResult.OK

    public static Task Show(stringmessageBoxText)

    {return Task.Factory.StartNew(() =>{

    Instance.Dispatcher.BeginInvoke(delegate{

    Instance.gridDialog.Visibility=Visibility.Visible;

    Instance.contentContainer.Content=messageBoxText;

    Instance.txtTitle.Text= "";

    Instance.btnCancle.Visibility=Visibility.Collapsed;

    Instance.ShowMessageBoxSB.Stop();

    Instance.ShowMessageBoxSB.Begin();

    });

    myResetEvent.WaitOne();returnmessageBoxResult;

    });

    }///

    ///显示包含指定文本、标题栏标题和响应按钮的消息框///

    /// 要显示的消息

    /// 消息框的标题

    /// 一个值,用于指示要显示哪个按钮或哪些按钮

    /// 一个值,用于指示用户对消息的响应

    public static Task Show(string messageBoxText, stringcaption, MessageBoxButton button)

    {return Task.Factory.StartNew(() =>{

    Instance.Dispatcher.BeginInvoke(delegate{

    Instance.gridDialog.Visibility=Visibility.Visible;

    Instance.contentContainer.Content=messageBoxText;

    Instance.txtTitle.Text=caption;if (button ==MessageBoxButton.OKCancel)

    {

    Instance.btnCancle.Visibility=Visibility.Visible;

    }else{

    Instance.btnCancle.Visibility=Visibility.Collapsed;

    }//Instance.UpdateLayout();

    Instance.ShowMessageBoxSB.Stop();

    Instance.ShowMessageBoxSB.Begin();

    });

    myResetEvent.WaitOne();returnmessageBoxResult;

    });

    }private void btnOk_Click(objectsender, RoutedEventArgs e)

    {

    txtTitle.Text= "";

    contentContainer.Content= null;

    gridDialog.Visibility=System.Windows.Visibility.Collapsed;

    messageBoxResult=MessageBoxResult.OK;//使异步线程的 Show() 方法继续执行

    myResetEvent.Set();

    }private void btnCancle_Click(objectsender, RoutedEventArgs e)

    {

    txtTitle.Text= "";

    contentContainer.Content= null;

    gridDialog.Visibility=System.Windows.Visibility.Collapsed;

    messageBoxResult=MessageBoxResult.Cancel;

    myResetEvent.Set();

    }#endregion

    另一个问题就是,让这个自定义控件变成全局的,也就是所有工程里的页面,共享

    这一个实例。思路就是,因为 App 类中的一个 RootFrame 对象,它是 PhoneApplicationFrame 类型的

    ,它是用来显示工程内所有页面的对象,并且控制各个页面的导航等功能的,它有一个 Template 属性,只要在

    默认的框架上,加入自定义的控件,那么这个控件就可以在所有页面中显示了,相应的样式(在 App.xaml 中定义):

    在 App 的构造函数中,重新设置 RootFrame 的样式,为上面定义的样式:

    RootFrame.Style = App.Current.Resources["MyPhoneApplicationFrameStyle"] as Style;

    在 App 的 InitializePhoneApplication() 方法中,注册 Navigating 事件:

    RootFrame.Navigating += RootFrame_Navigating;

    相应的函数:

    void RootFrame_Navigating(objectsender, NavigatingCancelEventArgs e)

    {//如果自定义弹出框在显示,则隐藏它,并且取消导航

    if (MyDialog.DialogIsOpen && e.NavigationMode ==NavigationMode.Back)

    {

    e.Cancel= true;

    }

    }

    在页面中调用弹出框的方法:

    private async void Button_Click_OkAndCancel(objectsender, RoutedEventArgs e)

    {if (MessageBoxResult.OK == await MyDialog.Show("Hello 北京天安门", "提示", MessageBoxButton.OKCancel))

    {

    txtTile.Text= "点击了OK";

    }else{

    txtTile.Text= "点击了Cancle";

    }

    }

    显示结果:

    当用户在 MainPage 页面,点击 Back 物理按键时,因为此时不会触发 RootFrame.Navigating 的导航事件,所以

    需要在 MainPage 中判断一下是否有其它的弹出框,判断如果没有其它的弹出框,则弹出询问用户

    是否关闭当前应用的弹出框:

    protected override async voidOnBackKeyPress(System.ComponentModel.CancelEventArgs e)

    {//首先取消默认 Back 键关闭应用

    e.Cancel = true;//如果 MainPage 页面中,弹出了其它的弹出框,关闭它,//在 DialogIsOpen 属性中实现

    if(MyDialog.DialogIsOpen)

    {//可以做其它事情

    }else{if (MessageBoxResult.OK == await MyDialog.Show("确定要退出吗?", "温馨提示:", MessageBoxButton.OKCancel))

    {//终止当前应用程序。该方法是在 WP8 中加入的,WP7 中木有

    App.Current.Terminate();

    }

    }base.OnBackKeyPress(e);

    }

    显示效果:

    因为本工程中自定义弹出框和 自定义Toast 通知都为系统级别的,所以所有的页面共享这个

    单一实例。如果页面只有在推出时,询问用户 “是否退出应用” 则只需要参考自定义控件,把它

    简化后,添加到 MainPage 中使用即可,不需要放到 PhoneApplicationFrame 的 Template

    属性中。

    2) 自定义一个 Toast 通知,目的是增加对消息样式的控制,并且可以增加消息弹出的动画等。

    自定义的 Toast 显示框已经在 上面的 MyDialog.xaml 文件中定义了,下面定义 C# 页面:

    #region 自定义 Toast 消息框

    const string myToast = @"

    ";//把上面动画字符串转换成相应的 XAML 动画对象

    Storyboard StoryBoardToast = System.Windows.Markup.XamlReader.Load(myToast) asStoryboard;//显示自定义 Toast 消息

    public static void ShowToastMessage(stringmessage)

    {

    Instance.StoryBoardToast.Stop();

    Instance.txtToast.Text=message;foreach (var t inInstance.StoryBoardToast.Children)

    Storyboard.SetTarget(t, Instance.borderToast);

    Instance.StoryBoardToast.Begin();

    }#endregion

    在任何一个 Page 页面中调用:

    private void Button_Click_Toast(objectsender, RoutedEventArgs e)

    {

    MyDialog.ShowToastMessage("收到 10 条新消息");

    }

    则,显示结果:

    展开全文
  • <LinearLayout android:id="@+id/toast_linear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginBottom="50dp" android:...
    package common;
    
    import android.app.Activity;
    import android.content.Context;
    import android.os.Handler;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.animation.AlphaAnimation;
    import android.view.animation.Animation;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import java.util.List;
    import java.util.Stack;
    import java.util.Vector;
    
    import video.bwgc.com.bwgclibrary.R;
    
    /**
     * <b>类   名:</b>${TYPE_NAME} <br/>
     * <b>类描述:</b> <br/>
     * <b>创建人:</b>zhangqi<br/>
     * <b>创建时间:</b>2017/6/6<br/>
     * <b>修改人:</b>zhangqi<br/>
     * <b>修改时间:</b>2017/6/6<br/>
     * <b>修改备注:</b><br/>
     *
     * @version 1.0.0<br/>
     */
    public class ToastUtil {
        public static final int LENGTH_SHORT = 0x00;
        public static final int LENGTH_LONG = 0x01;
    
        private final int ANIMATION_DURATION = 600;
    
        public Context mContext;
        public String msg;
        private int HIDE_DELAY = 2000;
    
        public static boolean isRunning=false;
    
        private Handler mHandler = new Handler();
    
        public static Stack<ToastUtil> stack = new Stack();
        // 表示吐司里显示的文字
        public static ToastUtil makeText(Context context, String message,
                                          int HIDE_DELAY) {
            ToastUtil utils=new ToastUtil();
            utils.mContext=context;
            utils.msg=message;
    
            if (HIDE_DELAY == LENGTH_LONG) {
                utils.HIDE_DELAY= 2500;
            } else {
                utils.HIDE_DELAY= 1500;
            }
    
            return utils;
        }
    
        public static void wakeUp(){
            isRunning=true;
            if (!stack.empty()) {
                ToastUtil util=stack.pop();
                util.doshow();
    
            }else{
                isRunning=false;
            }
    
    
        }
    
        public void doshow(){
            final ViewGroup container = (ViewGroup) ((Activity) mContext)
                    .findViewById(android.R.id.content);
            final View mView = ((Activity) mContext).getLayoutInflater().inflate(
                    R.layout.toast_layout, null);
            container.addView(mView);
    
            final LinearLayout mContainer = (LinearLayout) mView.findViewById(R.id.mbContainer);
            mContainer.setVisibility(View.GONE);
            TextView mTextView = (TextView) mView.findViewById(R.id.mbMessage);
            mTextView.setText(msg);
    
            // 显示动画
            AlphaAnimation mFadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
            // 消失动画
            final AlphaAnimation mFadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
            mFadeOutAnimation.setDuration(ANIMATION_DURATION);
            mFadeOutAnimation
                    .setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {
                            // 消失动画后更改状态为 未显示
    
                        }
    
                        @Override
                        public void onAnimationEnd(Animation animation) {
                            // 隐藏布局,不使用remove方法为防止多次创建多个布局
                            mContainer.setVisibility(View.GONE);
                            container.removeView(mView);
                            wakeUp();
                        }
    
                        @Override
                        public void onAnimationRepeat(Animation animation) {
    
                        }
                    });
            mContainer.setVisibility(View.VISIBLE);
    
            mFadeInAnimation.setDuration(ANIMATION_DURATION);
    
            mContainer.startAnimation(mFadeInAnimation);
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mContainer.startAnimation(mFadeOutAnimation);
                }
            }, HIDE_DELAY);
        }
    
        public void show() {
            stack.push(this);
            if(!isRunning){
                wakeUp();
    
            }
        }
    
    }


    toast_layout.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mbContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="60dp"
        android:gravity="bottom|center"
        android:orientation="vertical"
        android:paddingLeft="50dp"
        android:paddingRight="50dp">
    
        <LinearLayout android:id="@+id/toast_linear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_marginBottom="50dp"
            android:padding="8dp">
    
            <TextView android:id="@+id/mbMessage"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_margin="5dp"
                android:paddingTop="10dp"
                android:paddingBottom="10dp"
                android:paddingLeft="20dp"
                android:paddingRight="20dp"
                android:layout_weight="1"
                android:gravity="center"
                android:background="@drawable/shape_toastutils_bg"
                android:shadowColor="#BB000000"
                android:shadowRadius="2.75"
                android:textSize="12sp"
                android:textColor="#ffffff" />
        </LinearLayout>
    </LinearLayout>


    shape_toastutils_bg.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="#70000000" />
        <corners android:radius="12dp" />
    </shape>

    使用方法:

    ToastUtil.makeText(context,msg,ToastUtil.LENGTH_SHORT).show();


    展开全文
  • Android Toast,即便关闭通知权限也会正常显示
  • 最近项目中出现一个问题,就是有的手机在关闭系统通知,结果项目中使用的原生Toast在有的手机上竟然不显示了,然后就去查系统源码,发现原来原生的Toast是基于NotificaitionManagerService实现的,难怪有些手机不...
  • Toast customToast = Toast.makeText(MyApplication.getInstance().getApplicationContext(), message, Toast.LENGTH_SHORT); if (isNotificationsEnabled()) { customToast.show(); } else { Activity current...

    解决办法就是就是利用dialog来显示

    一、准备actvity

    dialog是依附于activity创建的,利用Application.ActivityLifecycleCallbacks获得activity

    /**
     * 类描述:MyApplication 生命周期
     */
    public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
        private Activity mActivity;
    
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            this.mActivity = activity;
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
            this.mActivity = activity;
        }
    
        @Override
        public void onActivityResumed(Activity activity) {
            this.mActivity = activity;
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
    
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
    
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
        }
    
        @Override
        public void onActivityDestroyed(Activity activity) {
    
        }
    
        public Activity getCurrentActivity() {
            return mActivity;
        }
    }
    

     二在MyApplication内注册

    public class MyApplication extends Application {
        @SuppressLint("StaticFieldLeak")
        private static MyApplication instance;
     
        private MyActivityLifecycleCallbacks activityLifecycleCallbacks;
    
        @Override
        public void onCreate() {
            super.onCreate();
            //initMyActivityLifecycleCallbacks 
            initMyActivityLifecycleCallbacks ();
        }
    
        public static MyApplication getInstance() {
            return instance;
        }
      
        private void initMyActivityLifecycleCallbacks () {
            activityLifecycleCallbacks = new MyActivityLifecycleCallbacks();
            registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
        }
    
        public Activity getCurrentActivity() {
            if (activityLifecycleCallbacks != null) {
                return activityLifecycleCallbacks.getCurrentActivity();
            } 
        }
    }

     三创建Toast

    /**
     * ToastUtil
     */
    public class ToastUtil {
        private static Handler mHandler = new Handler(Looper.getMainLooper());
    
        public static void showRealToast(String message) {
            Toast customToast = Toast.makeText(MyApplication.getInstance().getApplicationContext(), message, Toast.LENGTH_SHORT);
            if (isNotificationsEnabled()) {
                customToast.show();
            } else {
                Activity currentActivity = MyApplication.getInstance().getCurrentActivity();
                if (currentActivity != null) {
                    showToastDialog(currentActivity, customToast);
                }
            }
        }
    
        private static boolean isNotificationsEnabled() {
            boolean isOpened = false;
            Context applicationContext = MyApplication.getInstance().getApplicationContext();
            try {
                //android api 24
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    isOpened = NotificationManagerCompat.from(applicationContext).areNotificationsEnabled();
                } else {
                    isOpened = isAppOpsManagerNotificationEnable(applicationContext);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return isOpened;
        }
    
        private static boolean isAppOpsManagerNotificationEnable(Context applicationContext) {
            AppOpsManager mAppOps = (AppOpsManager) applicationContext.getSystemService(APP_OPS_SERVICE);
            ApplicationInfo appInfo = applicationContext.getApplicationInfo();
    
            String pkg = applicationContext.getApplicationContext().getPackageName();
            int uid = appInfo.uid;
    
            Class appOpsClass = null;
            /* Context.APP_OPS_MANAGER */
            try {
                appOpsClass = Class.forName(AppOpsManager.class.getName());
                Method checkOpNoThrowMethod = appOpsClass.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE, String.class);
    
                Field opPostNotificationValue = appOpsClass.getDeclaredField("OP_POST_NOTIFICATION");
                int value = (int) opPostNotificationValue.get(Integer.class);
                return ((int) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
    
        private static AppCompatDialog toastDialog;
    
        private static void showToastDialog(Activity currentActivity, Toast customToast) {
            dismissToastDialog();
            toastDialog = new AppCompatDialog(currentActivity, R.style.Style_Toast_Dialog);
            toastDialog.setCancelable(false);
            toastDialog.setCanceledOnTouchOutside(false);
            toastDialog.setContentView(customToast.getView());
            Window toastDialogWindow = toastDialog.getWindow();
            if (toastDialogWindow != null) {
                WindowManager.LayoutParams layoutParams = toastDialogWindow.getAttributes();
                layoutParams.gravity = customToast.getGravity();
                layoutParams.horizontalMargin = customToast.getHorizontalMargin();
                layoutParams.verticalMargin = customToast.getVerticalMargin();
                toastDialogWindow.setAttributes(layoutParams);
            }
            toastDialog.show();
            //2s消失
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    toastDialog.dismiss();
                }
            }, 2000);
        }
    
        private static void dismissToastDialog() {
            if (toastDialog != null) {
                mHandler.removeCallbacksAndMessages(null);
                toastDialog.dismiss();
                toastDialog = null;
            }
        }
    }

    Style资源

    <style name="Style_Toast_Dialog" parent="@android:style/Theme.Dialog">
            <item name="android:windowFrame">@null</item>
            <item name="android:windowIsFloating">true</item>
            <item name="android:windowContentOverlay">@null</item>
            <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
            <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
            <item name="android:windowBackground">@android:color/transparent</item>
            <item name="android:windowNoTitle">true</item>
            <item name="android:backgroundDimEnabled">false</item>
        </style>

    最后调用ToastUtil.showRealToast(String message);

     

    展开全文
  • toast 在应用关闭通知显示时,某些手机上会不在显示toast; 原因简单的说就是toast使用了通知管理器INotificationManager类,而此类因为禁止了通知栏权限而不显示toast; 有兴趣的可以追下源码; 重点说下3种解决方法把: ...
  • Toast工作原理依赖于通知关闭应用通知权限后,Toast无法显示。在发布SmartShow1.0.0版的时候,我注意到了这个问题,立即用自己的手机(魅族pro 6 plus)对淘宝、优酷等知名app进行测试,发现关闭通知权限后,它们...
  • 关闭toast权限后自定义解决方式

    千次阅读 2016-12-19 19:27:52
    不知道大家是否遇到了当你们的App在5.0以上系统中被用户关闭消息通知后(其实用户本身只是想关闭Notification的,猜测),系统的Toast也神奇的无法显示。当然这个问题并不复杂,有很多种解决方案,我们逐一探讨一下...
  • 最近项目中出现一个问题,就是有的手机在关闭系统通知,结果项目中使用的原生Toast在有的手机上竟然不显示了,然后就去查系统源码,发现原来原生的Toast是基于NotificaitionManagerService实现的,难怪有些手机不...
  • 9.1 Toast通知 Toast通知是在屏幕最顶上弹出来的临时通知,是Windows Phone通用的弹出式短暂的...通知显示的时间是7秒钟,7秒钟后会自动消失,如果你想快速关闭通知,可以采用在Toast通知上面向右滑动的手势便可以...
  • 相信很多朋友发现了华为等部分手机把通知权限关闭之后会导致Toast无法正常弹出的情况。 原因:谷歌为了让应用的 Toast 能够显示在其他应用上面,所以使用了通知栏相关的 API,但是这个 API 随着用户屏蔽通知栏而变得...
  • 直接跟踪Toast的源码,发现Toast其实是通过NotificationManagerService维护一个toast队列,然后通知Toast的客户端TN调用WindowManager添加view,所以当关闭消息通知权限时toast是无法显示。/** * Show the view for...
  • 本文章已授权鸿洋微信公众号转载:Toast不显示了? 吐司弹不出来完美的解决方案:ToastUtils,接下来让我们来一步步开始分析这个...为什么关闭通知栏权限弹不出来? 为什么有的机型可以弹有的却不行? 解答 ...
  • 关闭通知导致Toast无法正常显示到Java中的反射遇到的问题在Android开发中遇见因为关闭了消息通知导致Toast无法正常使用,所以采取了自己维护消息队列的方法来解决这个算是系统的小bug。 在解决的过程中用到了反射...
  • Android在8.0中针对通知一块在功能上做了较大的改动。 Toast被纳入到了通知管理,其实这在Android 4.4(API 19)以上就已经有...但是8.0上针对通知部分(主要针对下拉通知)做了较大修改,其中牵连到Toast,且APP...
  • 关闭之后通知toast都不显示了,于是老大让我去找找有没有办法检测这个按钮的状态,先把检测代码贴上/** * @param context * @return true 代表有有权限,或者检测失败 返回false代表没有权限 */
  • 前言不知道大家是否遇到了当你们的App在5.0以上系统中被用户关闭消息通知后(其实用户本身只是想关闭Notification的,猜测),系统的Toast也神奇的无法显示。当然这个问题并不复杂,有很多种解决方案,我们逐一探讨...
  • 自定义Toast (解决小米手机不能弹出对话框或用户关闭通知不显示)
  • 不知道大家是否遇到了当你们的App在5.0以上系统中被用户关闭消息通知后(其实用户本身只是想关闭Notification的,猜测),系统的Toast也神奇的无法显示。当然这个问题并不复杂,有很多种解决方案,我们逐一探讨一下...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 196
精华内容 78
关键字:

关闭toast通知