Android development, about the emulator notification display normal, real machine test real machine notification invalid problem

Recently, Xiaobai got a notification. The notification display on the emulator is still normal, but the real machine test has the problem that the notification is not displayed, and it does not report an error. Hey, it can be broken.

Baidu didn't solve the problem for a long time, and then found in the application permission settings of the real machine that the notification permission was turned off by default. After opening it, alas, well, the notification can be received.

But the problem came again. The user didn't know to turn on the notification permission, so I initially hoped that there is no relevant "dangerous permission". With the help of runtime permission, when the user opens the application, the user can directly authorize it. such as:

//检测权限
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){
    
    
      //请求成功
      
      }
 }
}

Of course, I checked the permission table for a long time, but I didn't find it. (If any friends find it, remember to tell me, I hope it's not my dazzling).

Therefore, I decided to manually write a class that detects whether the notification permission is enabled, NotificationUtil.class, this class has a static method, the return value Boolean is whether the notification permission is enabled, and the class name where the permission needs to be detected. Method acquisition:
see detailed code A great god’s blog:
Link: Android gets the app notification bar permission and jumps to the notification setting page (adapted to all versions) .

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

When the permission is obtained, it is closed, and a dialog box AlertDialog is created to guide the user to open it.

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

How to open the system notification authority interface:

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

In this way, the notification problem is perfectly solved. Oh, yes, Android 8.0 has made some minor modifications to the notification, adding a NotificationChannel class to classify and manage some of the properties of the notification. The specific implementation is as follows:


//建立通知部分格式 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);

Guess you like

Origin blog.csdn.net/qq_41904106/article/details/108986054