Android開発、エミュレータ通知表示正常、実機テスト実機通知無効問題について

最近、シャオバイに通知が届きました。シミュレーターの通知表示は正常ですが、実機テストでは通知が表示されず、エラーも報告されないという問題があり、壊れています。

Baiduは長い間問題を解決していませんでしたが、実際のマシンのアプリケーション権限設定で、通知権限がデフォルトでオフになっていることがわかりました。開いた後、残念ながら、通知を受信できます。

しかし、問題が再び発生しました。ユーザーは通知権限をオンにすることを知らなかったので、最初に関連する「危険な権限」を取得し、ユーザーが実行時権限でアプリケーションを開いたときにユーザーに直接承認させたいと思いました。 。といった:

//检测权限
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を手動で作成することにしました。このクラスには静的メソッドがあり、戻り値ブール値は通知権限が有効かどうか、および権限が必要なクラス名です。メソッドの取得:
詳細なコードを参照してください偉大な神のブログ:
リンク: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