欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发,关于模拟器通知显示正常,真机测试真机通知无效问题

程序员文章站 2022-04-02 20:13:31
最近,小白弄一个通知,模拟器上通知显示还是正常的,但真机测试就出现通知不显示的问题,并且也不报错,嘿,可给它牛坏了。百度半天也没解决问题,然后就在真机的应用权限设置里发现,原来通知权限是默认关闭的,打开后,唉,好了,通知可以接收了。但问题又来了,用户又不知道要开启通知权限,所以我一开始是希望有没有相关的“危险权限”,借助运行时权限让用户打开应用时,直接让用户授权。比如://检测权限if(Context.checkSelfPermission(this,Manifest.permission.权限名)...

最近,小白弄一个通知,模拟器上通知显示还是正常的,但真机测试就出现通知不显示的问题,并且也不报错,嘿,可给它牛坏了。

百度半天也没解决问题,然后就在真机的应用权限设置里发现,原来通知权限是默认关闭的,打开后,唉,好了,通知可以接收了。

但问题又来了,用户又不知道要开启通知权限,所以我一开始是希望有没有相关的“危险权限”,借助运行时权限让用户打开应用时,直接让用户授权。比如:

//检测权限
if(Context.checkSelfPermission(this,Manifest.permission.权限名) 
!= PackageMananger.PERMISSION_GRANTED){
   ActivityCompat.requestPermissions(this,new String[]{
   Manifest.Permission.权限名},1);
} 
//对请求结果处理
@Override
public void onRequsetPermissionsResult(int requestCode,
String[] permissions,int[] grantResults){
 switch (requestCode){
      case 1:
      if(grantResults.length>0&&grantResults[0]
      ==PackageManager.PERMISSION_GRANTED){
      //请求成功
      
      }
 }
}

当然,查了很久的权限表,没找到,(要是有小伙伴们找到了,记得告诉我哦,希望不是我眼花了)。

所以,我决定手动写一个检测通知权限是否开启的类,NotificationUtil.class, 这个类有一个静态方法,返回值Boolean为通知权限是否开启,在需要检测权限的地方 类名. 方法获取:
详细代码见一位大神的博客:
链接: Android获取应用通知栏权限,并跳转通知设置页面(全版本适配).

public class NotificationUtil {
    private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
    private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
    
    //调用该方法获取是否开启通知栏权限
    public static boolean isNotifyEnabled(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            return isEnableV26(context);
        } else {
            return isEnabledV19(context);
        }
    }

    /**
     * 8.0以下判断
     *
     * @param context api19  4.4及以上判断
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private static boolean isEnabledV19(Context context) {

        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;

        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;
    }


    /**
     * 8.0及以上通知权限判断
     *
     * @param context
     * @return
     */
    private static boolean isEnableV26(Context context) {
        ApplicationInfo appInfo = context.getApplicationInfo();
        String pkg = context.getApplicationContext().getPackageName();
        int uid = appInfo.uid;
        try {
            NotificationManager notificationManager = (NotificationManager)
                    context.getSystemService(Context.NOTIFICATION_SERVICE);
            Method sServiceField = notificationManager.getClass().getDeclaredMethod("getService");
            sServiceField.setAccessible(true);
            Object sService = sServiceField.invoke(notificationManager);

            Method method = sService.getClass().getDeclaredMethod("areNotificationsEnabledForPackage"
                    , String.class, Integer.TYPE);
            method.setAccessible(true);
            return (boolean) method.invoke(sService, pkg, uid);
        } catch (Exception e) {
            return true;
        }
    }
}

当获取到权限是关闭状态,建立一个对话框AlertDialog引导用户开启,

 public void produceAlertDialog(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("通知权限开启");
        builder.setMessage("检测到系统禁止了应用通知权限,我们希望您能开启通知权限,以便接收应用重要通知");
        builder.setCancelable(false);
        builder.setPositiveButton("允许", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
               intenttoOpen();//跳转到打开权限通知界面
            }
        });
        builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                finish();
            }
        });
        builder.show();
    }

打开系统通知权限界面的方法:

public void intenttoOpen(){
   Intent localIntent = new Intent();
        //直接跳转到应用通知设置的代码:
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0及以上
            localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
            localIntent.setData(Uri.fromParts("package", getPackageName(), null));
        } else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0以上到8.0以下
            localIntent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
            localIntent.putExtra("app_package", getPackageName());
            localIntent.putExtra("app_uid", getApplicationInfo().uid);
        } else if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {//4.4
            localIntent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            localIntent.addCategory(Intent.CATEGORY_DEFAULT);
            localIntent.setData(Uri.parse("package:" + getPackageName()));
        } else {
            //4.4以下没有从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,
            localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (Build.VERSION.SDK_INT >= 9) {
                localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
                localIntent.setData(Uri.fromParts("package", getPackageName(), null));
            } else if (Build.VERSION.SDK_INT <= 8) {
                localIntent.setAction(Intent.ACTION_VIEW);
                localIntent.setClassName("com.android.settings", "com.android.setting.InstalledAppDetails");
                localIntent.putExtra("com.android.settings.ApplicationPkgName", getPackageName());
            }
        }
        startActivity(localIntent);
}

这样,通知问题就完美解决了,哦,对了, Android 8.0对于通知进行了一些小的修改,加入了一个 NotificationChannel类,对通知的部分属性进行了分类管理。具体实现如下:


//建立通知部分格式 NotificationChannel, 参数Channelid, Channel名, 优先级(1,2,3,4,5)
    public void createNotificationChanneler(String c_channelid,String c_channelname,int c_importance){
        NotificationManager manager  = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        //检测 Channel是否已经被创建了,避免重复创建
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//检测Android版本
            if (manager.getNotificationChannel(c_channelid)!=null){
                return; }//要是没被创建那么
            NotificationChannel notificationChannel = new NotificationChannel(c_channelid,c_channelname,c_importance);
            notificationChannel.enableLights(true);//开启提示灯
            notificationChannel.enableVibration(true);//开启震动
            notificationChannel.setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg")),null);
            notificationChannel.setBypassDnd(true);//可绕过免打扰模式
            notificationChannel.setImportance(c_importance);//设置优先级
            notificationChannel.setLightColor(Color.RED);//设置提示灯颜色
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);//设置锁屏界面图标可见
            notificationChannel.setShowBadge(true);//有图标
            notificationChannel.setVibrationPattern(new long[]{0,1000,1000,1000});
            manager.createNotificationChannel(notificationChannel);
        }else {
            return;
        }
    }


//创建Notification
    //创建 notificationChannel
        createNotificationChanneler("channelone","channelonename", ConstantString.IMPORTANCE_DEFAULT);
        Intent intent = new Intent();
        intent.setClass(this,TenthtoActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
        Notification notification = new NotificationCompat.Builder(this,"channelone")
                .setContentTitle("一分钱抽Iphone~")//设置标题
                .setContentText("你参与的一分钱抽奖活动开始啦!机不可失失不再来!")//设置内容
                .setWhen(System.currentTimeMillis())//设置通知发出的时间
                .setSmallIcon(R.mipmap.orange)//设置左上方小图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.orange))//设置右边大图标
                .setContentIntent(pi)//设置跳转对象
                .setAutoCancel(true)//设置点击后自动取消标题栏图标提示
                .build();
        manager.notify(1,notification);

本文地址:https://blog.csdn.net/qq_41904106/article/details/108986054