admin管理员组文章数量:1586144
1.问题
最近负责的Android APP,用户反馈无法收到通知,尤其是息屏状态下无法收到通知。
这些APP,笔者以前都测试过,可以收到推送的。但测试以后,发现在新的Android上,确实收不到通知和推送。
根本原因在于:在最新的Android系统里,基于省电考虑,如果相关应用没有在系统白名单里,则会在锁屏之后,会被优化掉而不再运行;这样,APP将不再收到通知和推送。
用户还抱怨:微信能收到消息,为啥你们不能?笔者查阅资料后得知:在几乎所有Android系统里,微信、QQ、企业微信都被默认在系统白名单里,可以开机运行,锁屏后后台运行。
2.解决方案整体思路
但问题还得解决,解决思路为:
1)允许APP收到通知;
2)允许APP自启动;
3)打开APP的悬浮窗;
4)在电量管理里,允许APP在耗电状态下长期运行。
值得注意的是:这一系列操作,只能让使用者自己来完成;这样的APP才能才能被认为是合规的。
对于用户来说,可以做的,其实是提供引导程序,让用户来操作。
3.引导程序
提供的引导程序如下:
开启通知工具类:
/**
* Created by Administrator
* 开启通知
*/
public class NotificationUtil {
/**
* 跳转到app的设置界面--开启通知
* @param context
*/
public static void goToNotificationSetting(Context context) {
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= 26) {
// android 8.0引导
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
} else if (Build.VERSION.SDK_INT >= 21) {
// android 5.0-7.0
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", context.getPackageName());
intent.putExtra("app_uid", context.getApplicationInfo().uid);
} else {
// 其他
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 判断是否需要打开通知
* @param context
*/
public static boolean isNotificationEnabled(Context context) {
boolean isOpened = false;
try {
isOpened = NotificationManagerCompat.from(context).areNotificationsEnabled();
} catch (Exception e) {
e.printStackTrace();
isOpened = false;
}
return isOpened;
}
}
权限检查工具类:
/**
* Created by Administrator
* 权限检查
*/
public class PermissionCheckUtil {
//判断是否开启悬浮窗权限 context可以用你的Activity.或者tiis
public static boolean checkFloatPermission(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return true;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
try {
Class cls = Class.forName("android.content.Context");
Field declaredField = cls.getDeclaredField("APP_OPS_SERVICE");
declaredField.setAccessible(true);
Object obj = declaredField.get(cls);
if (!(obj instanceof String)) {
return false;
}
String str2 = (String) obj;
obj = cls.getMethod("getSystemService", String.class).invoke(context, str2);
cls = Class.forName("android.app.AppOpsManager");
Field declaredField2 = cls.getDeclaredField("MODE_ALLOWED");
declaredField2.setAccessible(true);
Method checkOp = cls.getMethod("checkOp", Integer.TYPE, Integer.TYPE, String.class);
int result = (Integer) checkOp.invoke(obj, 24, Binder.getCallingUid(), context.getPackageName());
return result == declaredField2.getInt(cls);
} catch (Exception e) {
return false;
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (null == appOpsMgr) {
return false;
}
int mode = appOpsMgr.checkOpNoThrow(
"android:system_alert_window",
android.os.Process.myUid(), context
.getPackageName()
);
return mode == AppOpsManager.MODE_ALLOWED || mode == AppOpsManager.MODE_IGNORED;
} else {
return Settings.canDrawOverlays(context);
}
}
}
//权限打开
public static void requestSettingCanDrawOverlays(Context context) {
int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt >= Build.VERSION_CODES.O) {
//8.0以上
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
// startActivityForResult(intent, REQUEST_DIALOG_PERMISSION);
context.startActivity(intent);
} else if (sdkInt >= Build.VERSION_CODES.M) {
//6.0-8.0
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + context.getPackageName()));
// startActivityForResult(intent, REQUEST_DIALOG_PERMISSION);
context.startActivity(intent);
} else {
//4.4-6.0以下
//无需处理了
}
}
}
自启动工具类
/**
* Created by Administrator
* 自启动设置
*/
public class AutoStartUtil {
/**
* 获取自启动管理页面的Intent
* @param context context
* @return 返回自启动管理页面的Intent
* */
public static void getAutostartSettingIntent(Context context) {
ComponentName componentName = null;
String brand = Build.MANUFACTURER;
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
switch (brand.toLowerCase()) {
case "samsung"://三星
componentName = new ComponentName("com.samsung.android.sm", "com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
break;
case "huawei"://华为
//荣耀V8,EMUI 8.0.0,Android 8.0上,以下两者效果一样
componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity");
// componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");//目前看是通用的
break;
case "xiaomi"://小米
componentName = new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity");
break;
case "vivo"://VIVO
// componentName = new ComponentName("com.iqoo.secure", "com.iqoo.secure.safaguard.PurviewTabActivity");
componentName = new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
break;
case "oppo"://OPPO
// componentName = new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity");
componentName = new ComponentName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
break;
case "yulong":
case "360"://360
componentName = new ComponentName("com.yulong.android.coolsafe", "com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
break;
case "meizu"://魅族
componentName = new ComponentName("com.meizu.safe", "com.meizu.safe.permission.SmartBGActivity");
break;
case "oneplus"://一加
componentName = new ComponentName("com.oneplus.security", "com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
break;
case "letv"://乐视
intent.setAction("com.letv.android.permissionautoboot");
default://其他
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
break;
}
intent.setComponent(componentName);
context.startActivity(intent);
} catch (Exception e){
Log.e("HLQ_Struggle", e.getLocalizedMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(context);
//设置标题
builder.setTitle("请用户设置自启动");
//设置对话框内容
builder.setMessage("请用户别忘记设置自启动!!!");
//设置图标
builder.setIcon(android.R.drawable.ic_dialog_alert);
//设置是否可以点击屏幕其他地方或者返回键取消显示
builder.setCancelable(false);
//确定按钮
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//该按钮的点击事件,这里设置按钮返回
dialog.dismiss();
}
});
//很多朋友都会忘了show
builder.show();
intent = new Intent(Settings.ACTION_SETTINGS);
context.startActivity(intent);
}
}
}
电池优化工具类:
/**
* Created by Administrator
* 对电池进行管理,使APP避免被电池优化
*/
public class BatteryManagementUtil {
/**
* 忽略电池优化
*/
public static void ignoreBatteryOptimization(Context context) {
PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
boolean hasIgnored = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
hasIgnored = powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
// 判断当前APP是否有加入电池优化的白名单,如果没有,弹出加入电池优化的白名单的设置对话框。
if (!hasIgnored) {
try {//先调用系统显示 电池优化权限
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
} catch (Exception e) {//如果失败了则引导用户到电池优化界面
try {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = ComponentName.unflattenFromString("com.android.settings/.Settings$HighPowerApplicationsActivity");
intent.setComponent(cn);
context.startActivity(intent);
}catch (Exception ex){//如果全部失败则说明没有电池优化功能
ex.printStackTrace();
Intent intent = new Intent(Settings.ACTION_SETTINGS);
context.startActivity(intent);
}
}
}
}
}
}
整个程序放在MainActivity的OnCreate()函数里:
NotificationUtil.goToNotificationSetting(MainActivity.this);
//打开悬浮窗
PermissionCheckUtil.requestSettingCanDrawOverlays(MainActivity.this);
//打开自启动窗口
AutoStartUtil.getAutostartSettingIntent(MainActivity.this);
//打开电池优化
BatteryManagementUtil.ignoreBatteryOptimization(MainActivity.this);
4.目前结果
引导之后,部分机型可以直接设置。当然,部分机型还有如下问题:
1)小米需要更改通知过滤规则,避免消息被过滤掉;
2)华为需要手动在电池管理里进行操作,才能进行自启动和后台运行。
没办法,提供操作说明和解决方案吧。提供解决方案以后,目前还正常。
版权声明:本文标题:Android APP息屏状态下收到通知解决方案 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1727975467a1140604.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论