Desarrollo de Android, sobre la pantalla de notificación del emulador normal, prueba de máquina real Notificación de máquina real problema no válido

Recientemente, Xiaobai recibió una notificación. La pantalla de notificación en el simulador sigue siendo normal, pero la prueba de la máquina real muestra el problema de que la notificación no se muestra y no informa un error. Oye, está roto.

Baidu no resolvió el problema durante mucho tiempo, y luego descubrió en la configuración de permisos de la aplicación de la máquina real que el permiso de notificación estaba desactivado de forma predeterminada. Después de abrirlo, por desgracia, bueno, se puede recibir la notificación.

Pero el problema volvió a aparecer. El usuario no sabía que debía activar el permiso de notificación, por lo que al principio quería tener el "permiso peligroso" relevante y permitir que el usuario lo autorizara directamente cuando el usuario abre la aplicación con el permiso de tiempo de ejecución. . tal como:

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

Por supuesto, revisé la tabla de permisos durante mucho tiempo, pero no la encontré (si algún amigo la encuentra, recuerde decírmelo, espero que no sea mi deslumbrante).

Por lo tanto, decidí escribir manualmente una clase que detecte si el permiso de notificación está habilitado, NotificationUtil.class, esta clase tiene un método estático, el valor de retorno booleano es si el permiso de notificación está habilitado y el nombre de la clase donde el permiso debe Adquisición de método:
ver código detallado Blog de un gran dios:
Enlace: Android obtiene el permiso de la barra de notificaciones de la aplicación y salta a la página de configuración de notificaciones (adaptado a todas las versiones) .

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

Cuando se obtiene el permiso, se cierra y se crea un cuadro de diálogo AlertDialog para guiar al usuario a abrirlo.

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

Cómo abrir la interfaz de la autoridad de notificación del sistema:

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

De esta forma se resuelve perfectamente el problema de la notificación. Oh, sí, Android 8.0 ha hecho algunas modificaciones menores a la notificación, agregando una clase NotificationChannel para clasificar y administrar algunas de las propiedades de la notificación. La implementación específica es la siguiente:


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

Supongo que te gusta

Origin blog.csdn.net/qq_41904106/article/details/108986054
Recomendado
Clasificación