Android开发,关于模拟器通知显示正常,真机测试真机通知无效问题
程序员文章站
2022-04-02 20:13:31
最近,小白弄一个通知,模拟器上通知显示还是正常的,但真机测试就出现通知不显示的问题,并且也不报错,嘿,可给它牛坏了。百度半天也没解决问题,然后就在真机的应用权限设置里发现,原来通知权限是默认关闭的,打开后,唉,好了,通知可以接收了。但问题又来了,用户又不知道要开启通知权限,所以我一开始是希望有没有相关的“危险权限”,借助运行时权限让用户打开应用时,直接让用户授权。比如://检测权限if(Context.checkSelfPermission(this,Manifest.permission.权限名)...
最近,小白弄一个通知,模拟器上通知显示还是正常的,但真机测试就出现通知不显示的问题,并且也不报错,嘿,可给它牛坏了。
百度半天也没解决问题,然后就在真机的应用权限设置里发现,原来通知权限是默认关闭的,打开后,唉,好了,通知可以接收了。
但问题又来了,用户又不知道要开启通知权限,所以我一开始是希望有没有相关的“危险权限”,借助运行时权限让用户打开应用时,直接让用户授权。比如:
//检测权限
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);
本文地址:https://blog.csdn.net/qq_41904106/article/details/108986054