1.判断是否有通知权限
2.没有的话,弹出一个对话框,提示用户是否去设置,用户点击确定后跳转到设置页面
3.手动设置权限成功后,结果会返回到
onActivityResult方法中,其中返回的请求码等于传入的码时,并且结果码等于2,编辑正确设置了,此时就可以调用发起通知。
4.正式开始:首先先写好一个工具类,用来判断是否有通知权限。
工具类名:NotificationPermissions
首先我们需要理解什么是appOps,这是一个android的原生权限管理,当手机系统启动时,就会自动启动这个相关的服务。
api:appopsmanager
整体的工作框架:
解释:当我们打开了设置页面的ui,并点击允许通知时,就会change permission
,改变app权限主要是通过appopsmanager这个类来实现。appopsmanager将会和appopsservice进行交互, 用户改变的权限将会存储在/data/system/appops.xml文件中。appopsservice也会被注入到其他各种服务中,进行权限的检测。
相关接口的api:
int checkop(String op,int uid,String packageName)判断应用是否含有某个权限
int noteop(string op,int uid,String packageName)和checkop使用一样,但是会在检测的时候记录一下
int checkopnothrow(string op,int uid,String packageName)和checkop类似,但是权限错误,不会报SecurityException错误,会返回appopsmanager.mode_error
int noteopnothrow(string op,int uid,String packageName)和checkopnothrow类似,但是不会返回appopsmanager.mode_error
void setMode(int code,int uid,String packageName,int mode)这个是我们最需要的方法,用来改变APP的权限。code代表具体的权限,mode表示(允许/禁止/提示)。
正式代码:
public class NotificationPermissions{
private final string checkopnothrow="CHECKOPNOTHROW";//将要获取的方法,
private final string op_post_notification="OP_POST_NOTIFICATION";将要获取的字段
public boolean isNotification(Context context){//需要将上下文传入进来
//1.获取appopsmanager
AppOpsManager appopsmanager=(AppOpsManager )context.getSystemtService(Context.APP_OPS_SERBIVE);
//2.获取applicationContextInfo信息
ApplicationInfo appInfo =context.getApplicationInfo();
//3.获取包名
String packageName=appInfo,packageName;//或者 packageName=context.getAppliacationContext().getPackageName();
int uid=appInfo.uid;用户身份
//4.实例化该packageName类
Class cla=class.forName(AppOpsManager.class.getName());
//5.通过反射获取要调用的appopsmanager中的方法
Method checkOpNoThrowMethod=appopsmanager.getMthod(checkopnothrow,Integer.TYPE,Integer.TYPE,String.class);
checkOpNoThrowMethod这个方法就是上面提到过的红色第三个方法。
Field opPostNotificationValue=appopsmanager.getDeclaredField(op_post_notification);
int value=(Integer)opPostNotificationValue.get(Integer.class);
return checkOpNoThrowMethod.invoke(appopsmanager,value,uid,packageName)==AppOpsManager.MODE_ALLOWED;//MODE_ALLOWED表示已经允许了
}
}
//6.以下代码是在mainactivity中,当权限检测没有时,执行的方法
//创建通知消息的方法 private void createNotification(){ NotificationCompat.Builder builder = new NotificationCompat.Builder(this);//使用NotificationCompat build通知消息 builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentTitle("新消息"); builder.setContentText("你有一条新的消息"); builder.setNumber(num++); builder.setAutoCancel(true);//设置点击通知跳转页面后,通知消失 Intent intent = new Intent(this,MainActivity.class);//点击后要跳转的页面 //PendingIntent ,不会立即跳转,是将要跳转到某个页面,正好用于点击通知后的操作 PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pi); Notification notification = builder.build(); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);//通知管理器 Log.e("xx","新消息"); mNotificationManager.notify(NO_1,notification);//发送 Log.e("xx","你有一条新的消息"); } //若是没有权限 ,跳转 private void gotoSet(){ if (!NotificationPermissions.isNotificationEnabled(this)) { final AlertDialog dialog = new AlertDialog.Builder(this).create(); dialog.show(); View view = View.inflate(this, R.layout.dialog, null); dialog.setContentView(view); TextView context = (TextView) view.findViewById(R.id.tv_dialog_context); context.setText("检测到您没有打开通知权限,是否去打开"); TextView confirm = (TextView) view.findViewById(R.id.btn_confirm); confirm.setText("确定"); confirm.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dialog.cancel(); Intent localIntent = new Intent(); localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= 9) {//系统8.0以上的 localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); localIntent.setData(Uri.fromParts("package", MainActivity.this.getPackageName(), null)); } else if (Build.VERSION.SDK_INT <= 8) {//系统8.0以下的 localIntent.setAction(Intent.ACTION_VIEW); localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails"); localIntent.putExtra("com.android.settings.ApplicationPkgName", MainActivity.this.getPackageName()); } startActivityForResult(localIntent,REQUESTCODE); } }); TextView cancel = (TextView) view.findViewById(R.id.btn_off); cancel.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dialog.cancel(); } }); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode==2){ if(requestCode==REQUESTCODE){ createNotification();//发送测试通知 } } }