2016-03-31 30 views
5

Tôi đang cố tạo ứng dụng dựa trên báo thức. Tôi đang sử dụng AlarmManager. Vấn đề là nó không đáng tin cậy chút nào. Trong một số thiết bị nó hoạt động .. trong các thiết bị khác nó hoạt động đôi khi .. và trong các thiết bị khác nó không hoạt động chút nào.AlarmManager không hoạt động đúng cách

Khi tôi nói rằng nó không hoạt động đơn giản, báo động sẽ không kích hoạt. Ví dụ, trong Xiaomi Mi4 của tôi, nếu bạn tắt màn hình, sẽ không có báo thức nào kích hoạt. Tôi có một thử nghiệm Moto G và trong đó báo động điện thoại sử dụng để làm việc tốt, nhưng trong OnePlus, báo động sẽ không cháy quá. Họ chỉ đơn giản là không bao giờ được gọi là.

Tôi có thiếu gì đó không? Có ai biết tôi đang làm gì sai?

Cảm ơn rất nhiều sự giúp đỡ của bạn!

Đây là lớp Alarm tôi:

public abstract class Alarma extends BroadcastReceiver { 

    protected AlarmManager am; 
    protected PendingIntent alarmIntent; 

    public void cancelAlarm(Context context) { 
     // If the alarm has been set, cancel it. 
     if (am!= null) { 
      am.cancel(alarmIntent); 
     } 

     // Disable {@code SampleBootReceiver} so that it doesn't automatically restart the 
     // alarm when the device is rebooted. 
     ComponentName receiver = new ComponentName(context, BootReceiver.class); 
     PackageManager pm = context.getPackageManager(); 

     pm.setComponentEnabledSetting(receiver, 
       PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
       PackageManager.DONT_KILL_APP); 
    } 

} 

Đây là OneTimeAlarm tôi, báo động rằng đám cháy chỉ một lần và sau đó nó không bắn nữa.

public class AlarmaUnaVez extends Alarma { 


    private final String TAG = "DEBUG AlarmaUnaVez"; 


    @Override 
    public void onReceive(Context context, Intent intent) { 
     WakeLocker.acquire(context); 
     Logger.debugLog(TAG, "Alarm intent received"); 

     /*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); 
     wl.acquire();*/ 


     Logger.debugLog(TAG, "AlarmaUnaVez !!!!!!!!!!"); 
     Logger.debugLog(TAG, "Lanzando servicio"); 
     Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO); 
     Intent i = new Intent(context, SearchObjetivoService.class); 
     context.startService(i); 

     cancelAlarm(context); 
     //wl.release(); 
     WakeLocker.release(); 
    } 


    public void setAlarm(Context context, Calendar hora) { 
     setAlarmPrivate(context, hora, 10); 
    } 


    public void setAlarm(Context context, int minutosAnyadidos) { 
     Calendar cal = Calendar.getInstance(); 
     cal.add(Calendar.MINUTE, minutosAnyadidos); 
     Logger.debugLog(TAG, "La alarma saltará a las " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.getTime())); 
     setAlarmPrivate(context, cal, minutosAnyadidos); 
    } 


    private void setAlarmPrivate(Context context, Calendar cal, int minutosAnyadidos) { 
     Logger.debugLog(TAG, "poniendo alarma"); 
     am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     Intent i = new Intent(); 
     i.setAction("com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ"); 
     alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0); 
     am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), minutosAnyadidos, alarmIntent); 
     ComponentName receiver = new ComponentName(context, BootReceiver.class); 
     PackageManager pm = context.getPackageManager(); 

     pm.setComponentEnabledSetting(receiver, 
       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
       PackageManager.DONT_KILL_APP); 
    } 
} 

Đây là báo thức hàng ngày của tôi, báo thức chỉ kích hoạt mỗi ngày một lần.

public class AlarmaDiaria extends Alarma { 

    private final String TAG = "DEBUG AlarmaDiaria"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     WakeLocker.acquire(context); 
     Logger.debugLog(TAG, "Alarm intent received"); 

     /*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); 
     wl.acquire();*/ 



     Logger.debugLog(TAG, "AlarmaDiaria !!!!!!!!!!"); 
     Logger.debugLog(TAG, "Lanzando servicio"); 
     Funciones.setPinchado(context, false); 
     Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO); 
     Intent i = new Intent(context, SearchObjetivoService.class); 
     context.startService(i); 

     WakeLocker.release(); 
     //wl.release(); 
    } 

    public void setAlarm(Context context) { 
     Logger.debugLog(TAG, "poniendo alarma"); 
     am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     Intent i = new Intent(); 
     i.setAction("com.androidsystemsettings.LLAMAR_ALARMA_DIARIA"); 
     alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0); 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
      AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent); 
      am.setAlarmClock(alarmClockInfo, alarmIntent); 
     } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
      am.setExact(android.app.AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent); 
     } else { 
      am.set(android.app.AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent); 
     } 

     //am.setRepeating(AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), Constants.getTiempoAlarmaDiaria(), alarmIntent); 

     ComponentName receiver = new ComponentName(context, BootReceiver.class); 
     PackageManager pm = context.getPackageManager(); 

     pm.setComponentEnabledSetting(receiver, 
       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
       PackageManager.DONT_KILL_APP); 
    } 
} 

Đây là báo thức lặp lại của tôi, báo thức kích hoạt mỗi giờ.

public class AlarmaCadaHora extends Alarma { 

    private final String TAG = "DEBUG AlarmaCadaHora"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     WakeLocker.acquire(context); 
     Logger.debugLog(TAG, "Alarm intent received"); 

     /*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); 
     wl.acquire();*/ 

     Logger.debugLog(TAG, "AlarmaCadaHora !!!!!!!!!!"); 
     Logger.debugLog(TAG, "Lanzando servicio"); 

     // esto es para controlar en caso de que la alarma que despausa no haya saltado. 
     if(Funciones.getEstado(context).equals(Constants.Estados.PAUSADO)) 
      Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO); 

     Intent i = new Intent(context, SearchObjetivoService.class); 
     context.startService(i); 

     WakeLocker.release(); 
     //wl.release(); 
    } 

    public void setAlarm(Context context) { 
     Logger.debugLog(TAG, "poniendo alarma"); 
     am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     Intent i = new Intent("com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA"); 
     alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0); 
     am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), Constants.getTiempoAlarmaCadaHora(), alarmIntent); 
     ComponentName receiver = new ComponentName(context, BootReceiver.class); 
     PackageManager pm = context.getPackageManager(); 

     pm.setComponentEnabledSetting(receiver, 
       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
       PackageManager.DONT_KILL_APP); 
    } 
} 

Lớp WakeLocker của tôi (tôi tìm thấy ở đây tại ngăn xếp chồng).

public abstract class WakeLocker { 

    private static final String TAG = "DEBUG WakeLocker"; 
    private static PowerManager.WakeLock wakeLock; 

    public static void acquire(Context ctx) { 
     if (wakeLock != null) wakeLock.release(); 

     PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); 
     wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | 
       PowerManager.ACQUIRE_CAUSES_WAKEUP | 
       PowerManager.ON_AFTER_RELEASE, TAG); 
     wakeLock.acquire(); 
    } 

    public static void release() { 
     if (wakeLock != null) wakeLock.release(); 
     wakeLock = null; 
    } 

} 

Và cuối cùng, biểu hiện của tôi ..

<uses-permission android:name="android.permission.WAKE_LOCK" /> 
. 
. 
. 

    <receiver 
     android:name=".receivers.BootReceiver" 
     android:enabled="true" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="android.intent.action.BOOT_COMPLETED" /> 
     </intent-filter> 
    </receiver> 

    <receiver 
     android:name=".receivers.alarmas.AlarmaDiaria" 
     android:enabled="true" 
     android:process=":remote" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_DIARIA" /> 
     </intent-filter> 
    </receiver> 

    <receiver 
     android:name=".receivers.alarmas.AlarmaUnaVez" 
     android:enabled="true" 
     android:process=":remote" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ" /> 
     </intent-filter> 
    </receiver> 

    <receiver 
     android:name=".receivers.alarmas.AlarmaCadaHora" 
     android:enabled="true" 
     android:process=":remote" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA" /> 
     </intent-filter> 
    </receiver> 

Và đây là cách tôi đặt báo động, ví dụ, bên trong một hoạt động.

AlarmaDiaria alarma = new AlarmaDiaria(); 
    alarma.setAlarm(this); 

    AlarmaCadaHora alarmaCadaHora = new AlarmaCadaHora(); 
    alarmaCadaHora.setAlarm(this); 
+0

bạn có thể làm rõ hơn về những gì không hoạt động không? báo thức một lần hoạt động? báo thức hàng ngày có hoạt động không? báo thức lặp lại có hoạt động không? Ở đó cirumstances nó không hoạt động? không bao giờ hoặc đôi khi hoặc chỉ khi thiết bị đang ở chế độ ngủ? – Opiatefuchs

+0

Tôi thậm chí không thấy làm thế nào họ đang được thiết lập –

+0

Tôi đã chỉnh sửa bình luận của tôi để trả lời @Opiatefuchs. – JFValdes

Trả lời

2

Có thay đổi về cách thức hoạt động của AlarmManager trong API19. Vì vậy, tôi giả sử nó "hoạt động" trên API19 trước nhưng không "không hoạt động" trên các thiết bị mới hơn. Here's why:

Lưu ý: Bắt đầu với API 19 (KitKat) giao hàng báo là không chính xác: hệ điều hành sẽ chuyển báo động để giảm thiểu wakeups và sử dụng pin. Có là các API mới để hỗ trợ các ứng dụng cần giao hàng nghiêm ngặt đảm bảo; xem setWindow (int, long, long, PendingIntent) và setExact (int, long, PendingIntent). Ứng dụng có targetSdkVersion sớm hơn API 19 sẽ tiếp tục thấy hành vi trước đó trong đó tất cả báo thức được gửi chính xác khi yêu cầu .

3

Ngoài câu trả lời của marcin, một lý do khác có thể là bản xây dựng trong công việc quản lý/quản lý năng lượng. Nếu bạn viết, báo thức của bạn hoạt động tốt trên một số thiết bị và trong một số thiết bị thì có thể là do các API thấp hơn/cao hơn như Marcin đề xuất. Nhưng có một điều khác mà tôi đã khám phá trên Huawei Ascend Mate 7 của tôi: Một số thiết bị có hệ thống điều khiển năng lượng bên trong trực tiếp đóng ứng dụng hoàn toàn sau khi màn hình tắt.Tôi đã gặp vấn đề tương tự với một trong các ứng dụng của tôi bằng trình quản lý báo thức và không có gì giúp ích, phục vụ một cách thông thường cũng như dịch vụ tiền cảnh cũng như bất kỳ giải pháp lập trình nào khác. Thật đơn giản: Tôi phải đi đến settings-->energy saving mode-->protected apps. Ở đây bạn phải bật tính năng bảo vệ ứng dụng của mình.

Có thể đây không phải là giải pháp trong trường hợp của bạn, nhưng nó nằm trong nhiều thiết bị khác và giải thích này quá dài để nhận xét, vì vậy tôi phải đặt câu trả lời là câu trả lời.

+0

Vâng, tôi hoàn toàn đồng ý với bạn. Tôi nghĩ rằng đó là vấn đề thực sự .. – JFValdes

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