2013-03-25 4 views
0

나는 알람 응용 프로그램을 가지고 있으며 사용자가 연락을 취하여 그의 경보가 때때로 지연된다고보고했습니다. 나는 다른 접근법과 이론을 시도해 보았고 사용자에게 기본 Android 알람을 백업으로 사용할 것을 제안했습니다.WakeLock with PARTIAL_WAKE_LOCK이 작동하지 않습니다.

일반적으로 알람은 약 한 시간 지연되었지만 안드로이드가 한 가지 확실한 제안을 한 직후에 알람이 시작된 것은 그 장치가 잠자기 상태이고 안드로이드의 알람으로 깨어 났기 때문에 광산이 "계속 시작"할 수있게 해줍니다.

편집 : 일부 클래스를 수정했으며 새 버전에서 이미 로그를 수신 했으므로 클래스와 로그 정보를 변경하려고합니다.

다음은 CountedWakeLock 클래스입니다. 시작시 문제가 될 수 있는지 확인하기 위해 깨우기 잠금 해제 지연을 처리하기 위해 자체 HandlerThread를 만들었습니다. 문제는 해결되지 않았지만 로그 (아래)에서 흥미로운 정보가 생성되었습니다.

public class CountedWakeLock { 

private static long TIMEOUT_DEFAULT = DateUtils.MINUTE_IN_MILLIS * 3; 
private static WakeLock sWakeLock = null; 
private static int sLockCount; 

private static class TimeoutReleaseThread extends HandlerThread { 

    static TimeoutReleaseThread mInstance = null; 

    Handler mHandler; 
    private Runnable mReleaseRunnable; 

    public static TimeoutReleaseThread instance() { 
     if (mInstance == null) mInstance = new TimeoutReleaseThread(); 
     return mInstance; 
    } 

    public TimeoutReleaseThread() { 
     super("TimeoutReleaseThread HandlerThread"); 
     start(); 
     mHandler = createHandler(); 
     mReleaseRunnable = new Runnable() { 

      @Override 
      public void run() { 
       Utils.log("TimeoutReleaseThread release lock"); 
       releaseLock(); 
      } 
     }; 
    } 

    private synchronized Handler createHandler() { 
     return new Handler(getLooper()); 
    } 

    public synchronized void postRelease(long timeout) { 
     mHandler.removeCallbacks(mReleaseRunnable); 
     mHandler.postDelayed(mReleaseRunnable, timeout); 
    } 
} 

public synchronized static void acquireLock(Context context) { 
    acquireLock(context, TIMEOUT_DEFAULT); 
} 

public synchronized static void acquireLock(Context context, long timeout) { 
    if (sWakeLock == null) { 
     Utils.log("WakeLock creating"); 
     PowerManager pm = (PowerManager) context.getApplicationContext() 
       .getSystemService(Context.POWER_SERVICE); 
     sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 
       "AlarmReceiver lock"); 
     sWakeLock.setReferenceCounted(false); 
     sLockCount = 0; 
    } else if (sWakeLock.isHeld()) 
     Utils.log("WakeLock held already"); 
    else 
     Utils.log("WakeLock not held"); 

    Utils.log("WakeLock acquiring for " + timeout); 
    sLockCount++; 
    sWakeLock.acquire(); 
    TimeoutReleaseThread.instance().postRelease(timeout); 
} 

public synchronized static void releaseLock() { 
    Utils.log("WakeLock releasing"); 
    if (sWakeLock == null) { 
     Utils.log("WakeLock==null"); 
    } else if (!sWakeLock.isHeld()) { 
     Utils.log("WakeLock not held"); 
     sWakeLock = null; 
     sLockCount = 0; 
    } else { 
     sLockCount--; 
     if (sLockCount <= 0) { 
      Utils.log("WakeLock released"); 
      sWakeLock.release(); 
      sWakeLock = null; 
      if (sLockCount != 0) Utils.log("lockcount=" + sLockCount); 

     } 
    } 
} 
} 

AlarmReceiver 브로드 캐스트 리시버는 - 그것은 알람 관리기

public void onReceive(Context context, Intent intent) { 
    Logger.initialize(context, "AlarmReceiver"); 
    if (CALL_IS_ON) { 
     //set another alarm with AlarmManager to start after 5 seconds 
     //doesn't happen in this situation 
    } else { 
     Utils.log("sending START ALARM"); 
     CountedWakeLock.acquireLock(context); 
     Intent i = new Intent(); 
     i.setAction(StartAlarmReceiver.ACTION_START_ALARM); 
     i.putExtras(intent.getExtras()); 

     context.sendOrderedBroadcast(i, null); //it is ordered, so eventual previous Alarm Activities etc. can be stopped 
     Utils.log("START ALARM send"); 
    } 
} 

StartAlarmReceiver에서 의도를 받고있다. 실제로 알람 활동을 시작

public void onReceive(Context context, Intent intent) { 
    Logger.initialize(context, "StartAlarmReceiver"); 
    Intent i = new Intent(context, AlarmOnScreen.class); 
    Bundle extras = intent.getExtras(); 
    i.putExtras(extras); 
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    context.startActivity(i); 
    Utils.log("AlarmActivity started"); 
} 

업데이트 로그 : 로그에서

504. 27/3 5:0:0 - logger initialized again from AlarmReceiver 
505. 27/3 5:0:0 - sending START ALARM 
506. 27/3 5:0:0 - WakeLock creating 
507. 27/3 5:0:0 - WakeLock acquiring for 180000 
508. 27/3 5:0:0 - START ALARM send 
509. 27/3 5:0:0 - logger initialized again from StartAlarmReceiver 
510. 27/3 5:0:0 - AlarmActivity started 
511. 27/3 5:0:0 - Main start 
512. 27/3 5:0:1 - Main resume 
513. 27/3 5:0:1 - Main pause 
514. 27/3 5:0:5 - Main stop 
515. 27/3 5:3:0 - TimeoutReleaseThread release lock 
516. 27/3 5:3:0 - WakeLock releasing 
517. 27/3 5:3:0 - WakeLock released 
518. 27/3 6:46:18 - logger initialized again from AlarmOnScreen create //user said he unlocked phone then to check the time... 

가 지금은 가동 잠금이 실제로 작동하는지 생각 - TimeoutReleaseThread 완료 할 수 있다면 모든 CPU가 실행되어 있어야합니다 후 일.

질문은 AlarmOnScreen 활동이 시작되지 않은 이유입니까? 그리고 Main Activity (511-514 줄)가 시작된 이유는 무엇입니까? 최근에 AlarmOnScreen에 단일 태스크 모드가 설정되었습니다. 그것이 문제의 원인 일 수 있습니까? 하지만 왜? 다른 이유로이 싱글 태스크가 필요합니다 ...

디바이스는 2.3.6 Android의 GT-S5830i입니다.

답변

0

여전히 문제의 원인을 알 수는 없지만, 많은 테스트를 거친 후에도 비슷한 변화를 경험하게된다면 Intal.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED를 StartAlarmReceiver의 Intent에 추가하면됩니다.

는 그래서

i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 
    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 

가 작동합니까

처럼? 네, 그렇습니다. 그리고 지금까지 그것은 다른 휴대폰에 어떤 문제도 일으키지 않았습니다.

의미가 있습니까? 아니, 전혀.