Trong khi xem bản trình bày âm thanh Google I/O 2016 mới nhất, cuối cùng tôi đã tìm ra nguyên nhân và giải pháp (xấu xí) cho vấn đề này.
Chỉ cần xem xung quanh một phút này, bạn kẹp ống (bắt đầu từ 8m56s): https://youtu.be/F2ZDp-eNrh4?t=8m56s
Nó giải thích tại sao điều này đang xảy ra và làm thế nào bạn có thể thoát khỏi nó.
Trên thực tế, Android sẽ làm chậm CPU sau vài giây không hoạt động để giảm mức sử dụng pin. Anh chàng trong video hứa hẹn một giải pháp thích hợp cho việc này sớm, nhưng bây giờ cách duy nhất để loại bỏ nó là gửi những chạm giả (đó là đề nghị chính thức).
Instrumentation instr = new Instrumentation();
instr.sendKeyDownUpSync(KeyEvent.KEYCODE_BACKSLASH); // or whatever event you prefer
Lặp lại điều này với bộ hẹn giờ sau 1,5 giây và sự cố sẽ biến mất.
Tôi biết, đây là một hack xấu xí, và nó có thể có tác dụng phụ xấu xí phải được xử lý. Nhưng bây giờ, nó chỉ đơn giản là giải pháp duy nhất.
Cập nhật: Về nhận xét mới nhất của bạn ... đây là giải pháp của tôi. Tôi đang sử dụng MotionEvent.ACTION_DOWN thông thường tại một vị trí bên ngoài giới hạn màn hình. Mọi thứ khác can thiệp một cách không mong muốn với giao diện người dùng. Để tránh SecurityException, khởi tạo bộ đếm thời gian trong trình xử lý onStart() của hoạt động chính và chấm dứt nó trong trình xử lý onStop(). Vẫn có những tình huống khi ứng dụng chuyển sang nền (tùy thuộc vào tải CPU) mà bạn có thể chạy vào SecurityException, do đó bạn phải bao quanh cuộc gọi chạm giả với khối thử try.
Xin lưu ý rằng tôi đang sử dụng khung thời gian của riêng mình, vì vậy bạn phải chuyển đổi mã để sử dụng bất kỳ bộ hẹn giờ nào bạn muốn sử dụng.
Ngoài ra, tôi không thể đảm bảo rằng mã này là 100% chống đạn. Ứng dụng của tôi có ứng dụng hack, nhưng hiện đang ở trạng thái beta, do đó tôi không thể đảm bảo cho bạn nếu tính năng này hoạt động chính xác trên tất cả các thiết bị và phiên bản 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();
.....
}
Cũng không xảy ra trên Nexus 5 chạy Android 4.4.2. –
Ghi nhật ký ưu tiên luồng trong khi phát lại dường như cho thấy mức độ ưu tiên của luồng không thực sự thay đổi khi chạm vào màn hình. Có lẽ sự kiện cảm ứng đang kích hoạt một gián đoạn gây rối với những gì mà trình lên lịch có khả năng quay trở lại? –
Tôi gặp sự cố tương tự trong ứng dụng của mình. Miễn là tôi tương tác với màn hình, tất cả chạy trơn tru như nó phải. Ngay sau khi tôi ngừng chạm vào màn hình, nó bắt đầu với sự sụt giảm lớn sau một vài (khoảng 3-5 giây). Khi tôi bắt đầu tương tác lại với màn hình, nó trở lại hoạt động trơn tru. Nó không quan trọng nếu tương tác màn hình làm bất cứ điều gì thực sự, cũng không phải nếu ngón tay được kích hoạt với một điều khiển/nút cụ thể. Ngay khi ngón tay di chuyển trên màn hình, tất cả âm thanh đều chạy mượt mà. Nó không xảy ra trên Android 5.x, nó chỉ bắt đầu với 6.0, và nó cũng là trường hợp trên Android N. – gal