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