在观看最新的 Google I/O 2016 音频演示时,我终于找到了这个问题的原因和(丑陋的)解决方案。
只需观看大约一分钟的这个 you Tube 剪辑(从 8 分 56 秒开始): https ://youtu.be/F2ZDp-eNrh4?t= 8m56s
它解释了为什么会发生这种情况以及如何摆脱它。
事实上,Android 会在几秒钟的触摸不活动后减慢 CPU 的速度,以减少电池使用量。视频中的那个人承诺很快就会为此提供适当的解决方案,但目前摆脱它的唯一方法是发送虚假触摸(这是官方建议)。
Instrumentation instr = new Instrumentation();
instr.sendKeyDownUpSync(KeyEvent.KEYCODE_BACKSLASH); // or whatever event you prefer
每 1.5 秒用计时器重复一次,问题就会消失。
我知道,这是一个丑陋的 hack,它可能会产生丑陋的副作用,必须加以处理。但就目前而言,它只是唯一的解决方案。
更新:关于您的最新评论……这是我的解决方案。我在屏幕边界之外的位置使用常规 MotionEvent.ACTION_DOWN。其他一切都以不受欢迎的方式干扰了 UI。为避免 SecurityException,请在主活动的 onStart() 处理程序中初始化计时器并在 onStop() 处理程序中终止它。当应用程序进入后台(取决于 CPU 负载)时,仍然存在可能遇到 SecurityException 的情况,因此您必须使用 try catch 块包围假触摸调用。
请注意,我使用的是我自己的计时器框架,因此您必须转换代码以使用您想要使用的任何计时器。
此外,我还不能确保代码是 100% 防弹的。我的应用程序应用了该 hack,但目前处于 beta 状态,因此我无法保证它是否在所有设备和 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();
.....
}