Просматривая последнюю аудиопрезентацию Google I/O 2016, я наконец нашел причину и (уродливое) решение этой проблемы.
Просто посмотрите примерно одну минуту этого клипа на You Tube (начиная с 8:56): https://youtu.be/F2ZDp-eNrh4?t=8m56s
Объясняется, почему это происходит и как от этого избавиться.
На самом деле, Android замедляет работу процессора после нескольких секунд бездействия сенсорного экрана, чтобы уменьшить расход заряда батареи. Парень в видео обещает скорое решение этой проблемы, но на данный момент единственный способ избавиться от этого — отправить поддельные касания (это официальная рекомендация).
Instrumentation instr = new Instrumentation();
instr.sendKeyDownUpSync(KeyEvent.KEYCODE_BACKSLASH); // or whatever event you prefer
Повторяйте это с таймером каждые 1,5 секунды, и проблема исчезнет.
Я знаю, что это уродливый хак, и он может иметь уродливые побочные эффекты, с которыми нужно справиться. Но пока это просто единственное решение.
Обновление: что касается вашего последнего комментария... вот мое решение. Я использую обычный MotionEvent.ACTION_DOWN за пределами экрана. Все остальное нежелательным образом мешало пользовательскому интерфейсу. Чтобы избежать SecurityException, инициализируйте таймер в обработчике onStart() основного действия и завершите его в обработчике onStop(). По-прежнему бывают ситуации, когда приложение переходит в фоновый режим (в зависимости от загрузки ЦП), в которых вы можете столкнуться с SecurityException, поэтому вы должны окружить фальшивый сенсорный вызов блоком try catch.
Обратите внимание, что я использую свою собственную структуру таймера, поэтому вам нужно преобразовать код, чтобы использовать любой таймер, который вы хотите использовать.
Кроме того, я пока не могу гарантировать, что код на 100% пуленепробиваем. В моих приложениях применен этот хак, но в настоящее время они находятся в состоянии бета-тестирования, поэтому я не могу дать вам никаких гарантий, что это работает правильно на всех устройствах и версиях Android.
Timer fakeTouchTimer = null;
Instrumentation instr;
void initFakeTouchTimer()
{
if (this.fakeTouchTimer != null)
{
if (this.instr == null)
{
this.instr = new Instrumentation();
}
this.fakeTouchTimer.restart();
}
else
{
if (this.instr == null)
{
this.instr = new Instrumentation();
}
this.fakeTouchTimer = new Timer(1500, Thread.MIN_PRIORITY, new TimerTask()
{
@Override
public void execute()
{
if (instr != null && fakeTouchTimer != null && hasWindowFocus())
{
try
{
long downTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, -100, -100, 0);
instr.sendPointerSync(event);
event.recycle();
}
catch (Exception e)
{
}
}
}
}, true/*isInfinite*/);
}
}
void killFakeTouchTimer()
{
if (this.fakeTouchTimer != null)
{
this.fakeTouchTimer.interupt();
this.fakeTouchTimer = null;
this.instr = null;
}
}
@Override
protected void onStop()
{
killFakeTouchTimer();
super.onStop();
.....
}
@Override
protected void onStart()
{
initFakeTouchTimer();
super.onStart();
.....
}
person
gal
schedule
23.05.2016