安卓8.0后通知栏Notification【判断APP通知栏权限是否开启,以及关闭了通知权限后设置或者自定义通知栏消息显示】

前言

当APP有推送功能时,需要判断当前app在手机中是否开启了允许消息推送,否则即使添加了推送代码仍然收不到通知,所以需要要么跳转至设置界面设置,要么自定义消息通知。

效果图

方法一:跳转到应用程序设置界面

1、将NotificationSetUtil.java类复制到项目中

package com.php.project.notificationsetutildemo.utils;

import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationManagerCompat;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by peihp
 * Used 判断是否开启消息通知,没有开启的话跳转到手机系统设置界面
 */
public class NotificationSetUtil {

    //判断是否需要打开设置界面
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static void OpenNotificationSetting(Context context, OnNextLitener mOnNextLitener) {
        if (!isNotificationEnabled(context)) {
            gotoSet(context);
        } else {
            if (mOnNextLitener != null) {
                mOnNextLitener.onNext();
            }
        }
    }

    //判断该app是否打开了通知
    /**
     * 可以通过NotificationManagerCompat 中的 areNotificationsEnabled()来判断是否开启通知权限。NotificationManagerCompat 在 android.support.v4.app包中,是API 22.1.0 中加入的。而 areNotificationsEnabled()则是在 API 24.1.0之后加入的。
     * areNotificationsEnabled 只对 API 19 及以上版本有效,低于API 19 会一直返回true
     * */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static boolean isNotificationEnabled(Context context) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
            boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
            return areNotificationsEnabled;
        }

        String CHECK_OP_NO_THROW = "checkOpNoThrow";
        String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        ApplicationInfo appInfo = context.getApplicationInfo();
        String pkg = context.getApplicationContext().getPackageName();
        int uid = appInfo.uid;

        Class appOpsClass = null;
        /* Context.APP_OPS_MANAGER */
        try {
            appOpsClass = Class.forName(AppOpsManager.class.getName());
            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE,
                    String.class);
            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);

            int value = (Integer) opPostNotificationValue.get(Integer.class);
            return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;

    }

    //打开手机设置页面
    /**
     * 假设没有开启通知权限,点击之后就需要跳转到 APP的通知设置界面,对应的Action是:Settings.ACTION_APP_NOTIFICATION_SETTINGS, 这个Action是 API 26 后增加的
     * 如果在部分手机中无法精确的跳转到 APP对应的通知设置界面,那么我们就考虑直接跳转到 APP信息界面,对应的Action是:Settings.ACTION_APPLICATION_DETAILS_SETTINGS*/
    private static void gotoSet(Context context) {

        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT >= 26) {
            // android 8.0引导
            intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
            intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
        } else if (Build.VERSION.SDK_INT >= 21) {
            // android 5.0-7.0
            intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
            intent.putExtra("app_package", context.getPackageName());
            intent.putExtra("app_uid", context.getApplicationInfo().uid);
        } else {
            // 其他
            intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
            intent.setData(Uri.fromParts("package", context.getPackageName(), null));
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    /*=====================添加Listener回调================================*/
    public interface OnNextLitener {
        /**
         * 不需要设置通知的下一步
         */
        void onNext();
    }

    private OnNextLitener mOnNextLitener;

    public void setOnNextLitener(OnNextLitener mOnNextLitener) {
        this.mOnNextLitener = mOnNextLitener;
    }
}

使用方法:

package com.php.project.notificationsetutildemo;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

import com.php.project.notificationsetutildemo.utils.NotificationSetUtil;

public class MainActivity extends AppCompatActivity {

    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContext = this;


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //判断是否需要开启通知栏功能
            NotificationSetUtil.OpenNotificationSetting(mContext, new NotificationSetUtil.OnNextLitener() {
                @Override
                public void onNext() {
                    Toast.makeText(mContext,"已开启通知权限",Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

方法二:自定义消息通知

新建Toast.java

package com.php.utils.ui.toast;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationManagerCompat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import com.php.notification.R;



public class Toast {
    private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
    private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
    private static int checkNotification = 0;
    private static Object mToast;
    private static boolean flag = true;
    private Toast(Context context, String message, int duration) {
        if(context instanceof Application)
            checkNotification = 0;
        else
            checkNotification = isNotificationEnabled(context) ? 0 : 1;
        if (checkNotification == 1) {
            try {
                mToast = EToast2.makeText(context, message, duration);
            } catch (Exception e) {
                e.printStackTrace();
                synchronized (CHECK_OP_NO_THROW) {
                    if(flag){
                        flag = false;
                        View toastRoot = LayoutInflater.from(context).inflate(R.layout.toast, null);
                        TextView tv = (TextView) toastRoot.findViewById(R.id.toast_notice);
                        tv.setText(message);
                        mToast = android.widget.Toast.makeText(context,"",duration);
                        ((android.widget.Toast) mToast).setView(toastRoot);
                        ((android.widget.Toast) mToast).setGravity(Gravity.BOTTOM, 0, 200);
                    }
                }
                ((TextView)((android.widget.Toast) mToast).getView().findViewById(R.id.toast_notice)).setText(message);
            }
        } else {
//            mToast = android.widget.Toast.makeText(context, message, duration);
            synchronized (CHECK_OP_NO_THROW) {
                if(flag){
                    flag = false;
                    View toastRoot = LayoutInflater.from(context).inflate(R.layout.toast, null);
                    TextView tv = (TextView) toastRoot.findViewById(R.id.toast_notice);
                    tv.setText(message);
                    mToast = android.widget.Toast.makeText(context,"",duration);
                    ((android.widget.Toast) mToast).setView(toastRoot);
                    ((android.widget.Toast) mToast).setGravity(Gravity.BOTTOM, 0, 200);
                }
            }
            ((TextView)((android.widget.Toast) mToast).getView().findViewById(R.id.toast_notice)).setText(message);
        }
    }
    private Toast(Context context, int resId, int duration) {
        if(context instanceof Application)
            checkNotification = 0;
        else
            checkNotification = isNotificationEnabled(context) ? 0 : 1;
        if (checkNotification == 1 && context instanceof Activity) {
            mToast = EToast2.makeText(context, resId, duration);
        } else {
            mToast = android.widget.Toast.makeText(context, resId, duration);
        }
    }

    public static Toast makeText(Context context, String message, int duration) {
        return new Toast(context,message,duration);
    }
    public static Toast makeText(Context context, int resId, int duration) {
        return new Toast(context,resId,duration);
    }

    public void show() {
        if(mToast instanceof EToast2){
            ((EToast2) mToast).show();
        }else if(mToast instanceof android.widget.Toast){
            ((android.widget.Toast) mToast).show();
        }
    }
    public void cancel(){
        if(mToast instanceof EToast2){
            ((EToast2) mToast).cancel();
        }else if(mToast instanceof android.widget.Toast){
            ((android.widget.Toast) mToast).cancel();
        }
    }
    //判断该app是否打开了通知
    /**
     * 可以通过NotificationManagerCompat 中的 areNotificationsEnabled()来判断是否开启通知权限。NotificationManagerCompat 在 android.support.v4.app包中,是API 22.1.0 中加入的。而 areNotificationsEnabled()则是在 API 24.1.0之后加入的。
     * areNotificationsEnabled 只对 API 19 及以上版本有效,低于API 19 会一直返回true
     * */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @SuppressLint("NewApi")
    private static boolean isNotificationEnabled(Context context){
        if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT){
            NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
            boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
            return areNotificationsEnabled;
        }
        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        ApplicationInfo appInfo = context.getApplicationInfo();

        String pkg = context.getApplicationContext().getPackageName();

        int uid = appInfo.uid;

        Class appOpsClass = null; //* Context.APP_OPS_MANAGER *//*

        try {
            appOpsClass = Class.forName(AppOpsManager.class.getName());
            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, 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;
    }
}

新建EToast2.java文件:

package com.php.utils.ui.toast;

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Timer;
import java.util.TimerTask;

import com.php.notification.R;



public class EToast2 {

    private WindowManager manger;
    private Long time = 2000L;
    private View contentView;
    private WindowManager.LayoutParams params;
    private static Timer timer;
    private Toast toast;
    private static Toast oldToast;
    private static Context context;
    public static final int LENGTH_SHORT = 0;
    public static final int LENGTH_LONG = 1;
    private static Handler handler;
    private CharSequence text;

    private View toastRoot;

    private EToast2(Context context, CharSequence text, int HIDE_DELAY){
        this.text = text;

        if(HIDE_DELAY == EToast2.LENGTH_SHORT)
            this.time = 2000L;
        else if(HIDE_DELAY == EToast2.LENGTH_LONG)
            this.time = 3500L;

        if(oldToast != null && EToast2.context != null && EToast2.context != context){
            EToast2.context = context;
            oldToast.cancel();
            oldToast = null;
        }
        if(oldToast == null){
            LayoutInflater inflate = (LayoutInflater)
                    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            toastRoot = inflate.inflate(R.layout.toast, null);
            TextView tv = (TextView) toastRoot.findViewById(R.id.toast_notice);
            tv.setText(text);
            toast = Toast.makeText(context,"",HIDE_DELAY);
            toast.setView(toastRoot);
            toast.setGravity(Gravity.BOTTOM, 0, 200);
            contentView = toastRoot;

            params = new WindowManager.LayoutParams();
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            params.width = WindowManager.LayoutParams.WRAP_CONTENT;
            params.format = PixelFormat.TRANSLUCENT;
            params.windowAnimations = context.getResources().getIdentifier("android:style/Animation.Toast", null, null);
            params.type = WindowManager.LayoutParams.TYPE_TOAST;
            params.setTitle("EToast2");
            params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
            params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
            params.y = 200;
        }
        if(handler == null){
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    EToast2.this.cancel();
                }
            };
        }
    }

    public static EToast2 makeText(Context context, String text, int HIDE_DELAY){
        EToast2 toast = new EToast2(context, text, HIDE_DELAY);
        return toast;
    }

    public static EToast2 makeText(Context context, int resId, int HIDE_DELAY) {
        return makeText(context,context.getText(resId).toString(),HIDE_DELAY);
    }

    public void show(){
        if(oldToast == null){
            oldToast = toast;
            Context context = contentView.getContext().getApplicationContext();
            if (context == null) {
                context = contentView.getContext();
            }
            manger = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
            manger.addView(contentView, params);
        }else{
            if(timer != null){
                timer.cancel();
            }
            ((TextView)(oldToast).getView().findViewById(R.id.toast_notice)).setText(text);
        }
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                handler.sendEmptyMessage(1);
            }
        }, time);
    }


    public void cancel(){
        try {
            manger.removeView(contentView);
        } catch (IllegalArgumentException e) {
            //这边由于上下文被销毁后removeView可能会抛出IllegalArgumentException
            //暂时这么处理,因为EToast2是轻量级的,不想和Context上下文的生命周期绑定在一块儿
            //其实如果真的想这么做,可以参考博文2的第一种实现方式,添加一个空的fragment来做生命周期绑定
        }
        timer.cancel();
        oldToast.cancel();
        timer = null;
        toast = null;
        oldToast = null;
        contentView = null;
        handler = null;
    }
}

toast.xml文件:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"  
    android:background="@drawable/toast_bg">  
    
    <TextView android:id="@+id/toast_notice"  
          android:layout_width="wrap_content"  
          android:layout_height="wrap_content"  
          android:layout_gravity="center_vertical"  
          android:gravity="center_vertical"  
          android:background="@color/transparent"
          android:textSize="18sp"
          android:padding="7dp"
          android:textColor="@color/white">  
    </TextView>  
</LinearLayout>

使用方法:

/**
	 * 提示窗
	 *
	 * @param context
	 * @param mes
	 */
	public static void promptMes(Context context, String mes) {
		com.php.utils.ui.toast.Toast.makeText(context, mes,
				Toast.LENGTH_SHORT).show();
	}

欢迎大家关注本人公众号,一起学习进步,谢谢!

公众号

猜你喜欢

转载自blog.csdn.net/P876643136/article/details/88086425