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

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

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

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

//检测权限
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);

猜你喜欢

转载自blog.csdn.net/qq_41904106/article/details/108986054
今日推荐