2015-05-10 12 views
7

Tôi đang phát triển một ứng dụng sẽ thực hiện một tác vụ nhất định sau mỗi 60 giây. Vì có một số vấn đề về độ chính xác với báo thức trong Android 4.4 trở lên, trong đó tất cả báo thức không chính xác, tôi đã chọn kiểu chuỗi: A BroadcastReceiver kích hoạt báo thức đầu tiên và mỗi lần báo thức sẽ đặt báo thức tiếp theo.Android set() và setExact() báo động kích hoạt vào khoảng thời gian không chính xác

Vấn đề là, mặc dù tôi đang đặt báo thức trong khoảng thời gian 60 giây (60000 mili giây), báo thức kích hoạt ở khoảng thời gian 5 giây và đôi khi thậm chí còn ít hơn. Tôi đã thử nghiệm mã trên Nexus 5 (Android 5.1.1) và trên trình giả lập Android 5.0.1, cả hai đều cho kết quả tương tự. Tôi nên chỉ ra rằng cả hai người nhận đều được đăng ký trên AndroidManifest và ứng dụng của tôi có quyền RECEIVE_BOOT_COMPLETED.

EDIT: setExact() gây ra chính xác cùng một vấn đề

StartupReceiver.java (BroadcastReceiver cho BOOT_COMPLETED):

public class StartupReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     Log.d(TAG, "Got the BOOT_COMPLETED signal"); 
     // Get the first alarm to be invoked immediately 
     AlarmReceiver.setNextScanAlarm(context, 0); 
    } 
} 

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     // Start the service 
     Intent startServiceIntent = new Intent(context, BackgroundService.class); 
     startServiceIntent.putExtra("interval", 60000); 
     startServiceIntent.putExtra("action", "scan"); 
     context.startService(startServiceIntent); 

     // Schedule the next alarm 
     setNextScanAlarm(context, 60000); 
    } 

    public static void setNextScanAlarm(Context context, int interval) { 
     Intent scanIntent = new Intent(context, AlarmReceiver.class); 
     scanIntent.putExtra("interval", interval); 
     scanIntent.putExtra("action", "scan"); 
     PendingIntent pendingIntent = PendingIntent.getBroadcast(
       context, 
       0, 
       scanIntent, 
       PendingIntent.FLAG_ONE_SHOT); 


     AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     alarmManager.set(
       AlarmManager.ELAPSED_REALTIME_WAKEUP, 
       interval, 
       pendingIntent); 
    } 
} 

gì có thể là vấn đề?

+0

Chỉ cần một câu hỏi nhanh là bạn thực sự làm bất cứ điều gì với báo động hoặc chỉ cố gắng chạy một số mã trong nền hoặc giao diện người dùng chính mỗi 60 giây? – napkinsterror

Trả lời

0

Tôi tin rằng bởi vì đây là một chiếc đồng hồ báo thức khi gọi

alarmManager.set(
       AlarmManager.ELAPSED_REALTIME_WAKEUP, 
       interval, 
       pendingIntent); 

Biến bạn đang gọi interval được số lượng thời gian bạn muốn trôi qua cho đến khi báo động tiếp theo, nhưng khi bạn nghĩ về điều này khi nào nó biết bắt đầu? Hơn thế nữa, khi nào thì thời gian thực sự bằng 0?

Khi bạn tạo nó? Số
Khi bạn gọi .set()? Số

Nó thực sự là số không khi BOOT. Vì vậy, bạn đang yêu cầu nó khởi động 60 giây sau khi khởi động, và yêu cầu của bạn cho mọi thời gian này, thời gian này sẽ đã trôi qua.

Đây là nơi có sự nhầm lẫn và nơi bạn có thể chỉ cần sử dụng cuộc gọi như new Handler.postDelayed(Runnnable r, 60000) thay vì Trình quản lý báo thức. Nó sẽ chính xác hơn nhiều và sẽ không phải chịu một số vấn đề với sự hiểu biết về Hệ điều hành Android và các báo động/đồng hồ/etc/etc của nó.

Nhưng đối với trường hợp cụ thể của bạn, tôi tin rằng bạn có thể giải quyết nó bằng cách truy cập System các cuộc gọi/biến chức năng. Vì vậy, bên trong hàm của bạn setNextScanAlarm() tôi tin rằng nó sẽ trông như thế này:

public static void setNextScanAlarm(Context context, int interval) { 
     //create the intent the same way as before 
     Intent scanIntent = new Intent(context, AlarmReceiver.class); 
     scanIntent.putExtra("interval", interval); 
     scanIntent.putExtra("action", "scan"); 
     PendingIntent pendingIntent = PendingIntent.getBroadcast(
       context, 
       0, 
       scanIntent, 
       PendingIntent.FLAG_ONE_SHOT); 

     //create new variables to calculate the correct time for this to go off 
     long timeRightNow = System.elapsedRealTime() //use something else if you change AlarmManager type 
     long timeWhenIShouldGoOff = timeRightNow + interval; 

     //use the new timeWhenIShouldGoOff variable instead of interval 
     AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     alarmManager.set(
       AlarmManager.ELAPSED_REALTIME_WAKEUP, 
       timeWhenIShouldGoOff, 
       pendingIntent); 
    } 
0

Xem my answer cho một câu hỏi tương tự. Tôi sử dụng postDelayed() thay vì AlarmManager trong khoảng thời gian ngắn (dưới 1 phút) và AlarmManager để có thời gian dài.

Các vấn đề liên quan