Во-первых, если вы работаете в API> = 26, вам нужно использовать службы переднего плана, используйте следующий код для запуска службы
Intent intent = new Intent(getApplicationContext(), PieOptions.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
}else {
startService(intent);
}
Теперь внутри вас PieOptions
класс, сначала расширьтеJobIntentService
вместо Service
, в методе onCreate()
добавьте следующий код.Службы Foreground должны показывать пользователю уведомление об API> = 26, в противном случае служба будет уничтожена через 5 секунд.
@Override
public void onCreate() {
super.onCreate();
String CHANNEL_ID = "my_service";
String CHANNEL_NAME = "My Background Service";
if (Build.VERSION.SDK_INT >= 26) {
// in APIs 26+ we should show a notifications
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME, NotificationManager.IMPORTANCE_NONE);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setCategory(Notification.CATEGORY_SERVICE).setPriority(PRIORITY_MIN).build();
startForeground(NOTIFICATION_ID, notification);
}
}
Еще одна вещь, которую вам нужно сделать, это изменить тип, который вы используете при инициализации параметров макета, следующий код даст вам правильный тип в зависимости от вашей версии API
int type = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
И последнее: чтобы рисовать оверлеи, необходимо убедиться, что у вас есть разрешение на рисование оверлеев:
private boolean canDrawOnScreen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return canDrawOnScreenM();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return canDrawOverlaysUsingReflection(getApplicationContext());
} else
return true;
}
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean canDrawOnScreenM() {
return Settings.canDrawOverlays(getApplicationContext());
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static boolean canDrawOverlaysUsingReflection(Context context) {
try {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class clazz = AppOpsManager.class;
Method dispatchMethod = clazz.getMethod("checkOp", new Class[]{int.class, int.class, String.class});
//AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
int mode = (Integer) dispatchMethod.invoke(manager, new Object[]{24, Binder.getCallingUid(), context.getApplicationContext().getPackageName()});
return AppOpsManager.MODE_ALLOWED == mode;
} catch (Exception e) {
return false;
}
}
Теперь для надуваемой части и обработки представления переработчика, сначала вам нужна ссылка на представление переработчика,вы можете сделать следующее:
RecyclerView myRecyclerView = mView.findViewById(R.id.your_recycler_id);
, затем вы можете обработать RecyclerView в обычном режиме, настроив менеджер раскладки и адаптер.