2017-11-24 18 views
1

우리는 안드로이드에서 네이티브 코드 용 타이머를 구현하려고합니다. 타이머는 깨우기 및 슬립 모드에서 정확하게 작동해야합니다. 타이머가 만료되면 우리 고유 코드가 DPD (Dead peer detection) 메시지 네트워크에 우리는 다음과 같은 접근 방법을 시도했다.안드로이드에서 슬립 상태에서 타이머가 정확하게 만료되지 않습니다.

  • 이도 2 초, 3 초, 5 초 같은 작은 타이머에 대한 웨이크 상태에서 정확한 결과를 제공하지 않습니다

    1. 사용자 공간 코드에 알람 관리자에 대한 안드로이드 프레임 워크 API의의를 사용하고 아래는 결과입니다 .

    2. 슬립 모드에서도 정확하게 작동하지 않습니다.
  • 우리는 커널 공간 코드에서 커널 타이머를 사용하려고 아래의 결과입니다

    • 웨이크 상태로 완벽하게 작품.
    • 그러나 수면 상태 타이머는 전혀 만료되지 않습니다. 장치를 수동으로 깨우면 타이머가 만료됩니다. 따라서 커널 타이머는 절전 모드에서는 작동하지 않습니다.

    3.Using 우리가 상당한 성능의 원인이 될 수 웨이크 잠금 장치의 사용을 방지하기 위해 노력하고있다 * 웨이크 잠금 는

    PS 발행 - 심지어 오픈 소스의 IPsec 구현 strongswan는 DPD 메시지를 보내는 정확한 시간을 strongswan은 잠자기 모드를 사용하지 않으므로 잠자기 모드에서 작동하는 방식을 파악하려고합니다.이 질문에 대한 답변을 검색하는 사람은 누구나 해당 코드를 살펴볼 수 있습니다.

    누구든지이 문제를 해결하기 위해 제안 할 수 있습니까?

    +0

    보이는 부분 웨이크 잠금을 획득하기 위해 아래의 코드를 사용합니다. 내가 생각하는 다른 방법은 없다. –

    +0

    안드로이드에서 잠자기 상태 란 무엇입니까? –

    +0

    @ Vlad Matvienko 예, 이것이 마지막 옵션입니다. 그러나 우리는 전력 사용량에 미치는 영향을 알지 못합니다. 이에 대해 알고 있습니까? – somil

    답변

    -1

    타이머를 시작하고 앱이 백그라운드로 전환되면 alarmManager를 시작합니다. 다시 앱이 포 그라운드로오고 타이머가 만료되지 않으면 타이머가 다시 트리거되어 알람 관리자가 제거됩니다.

    private int timeToStart; 
    private TimerState timerState; 
    
    private static final int MAX_TIME = 60; //Time length is 60 seconds 
    
    private enum TimerState { 
        STOPPED, 
        RUNNING 
    
    } 
    
    
    private void initTimer() { 
        Log.e(TAG,"initTimer called"); 
    
        long startTime = mPrefs.getStartedTime(); //here mprefs is your shared preference manager 
        if (startTime > 0) { 
         timeToStart = (int) (MAX_TIME - (getNow() - startTime)); 
         if (timeToStart <= 0) { 
          // TIMER EXPIRED 
          onTimerFinish(); 
         } else { 
          startTimer(); 
          timerState = TimerState.RUNNING; 
         } 
        } else { 
         timeToStart = MAX_TIME; 
         timerState = TimerState.STOPPED; 
        } 
    } 
    
        private long getNow() { 
        Calendar rightNow = Calendar.getInstance(); 
        return rightNow.getTimeInMillis()/1000; 
    } 
    
        private void onTimerFinish() { 
        Log.e(TAG,"onTimerFinish() called"); 
    
        timerState = TimerState.STOPPED; 
        mPrefs.setStartedTime(0); 
        timeToStart = MAX_TIME; 
    
    } 
    
    private void startTimer() { 
        Log.e(TAG,"startTimer() called"); 
    
        countDownTimer = new CountDownTimer(timeToStart * 1000, 1000) { 
    
         @Override 
         public void onTick(long millisUntilFinished) { 
          timeToStart -= 1; 
         } 
    
         @Override 
         public void onFinish() { 
          onTimerFinish(); 
         } 
        }.start(); 
    } 
    
        public void setAlarmManager() { 
        int wakeUpTime = (mPrefs.getStartedTime() + MAX_TIME) * 1000; 
        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
        Intent intent = new Intent(this, TimeReceiver.class); 
        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
         am.setAlarmClock(new AlarmManager.AlarmClockInfo(wakeUpTime, sender), sender); 
        } else { 
         am.set(AlarmManager.RTC_WAKEUP, wakeUpTime, sender); 
        } 
    } 
    
        public void removeAlarmManager() { 
        Intent intent = new Intent(this, TimeReceiver.class); 
        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 
        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
        am.cancel(sender); 
    } 
    
        @Override 
        protected void onResume() { 
        super.onResume(); 
         initTimer(); 
         removeAlarmManager(); 
    
    } 
    
    0

    Android가 잠자기 상태가되면 여러 상태가 발생하며 마지막 단계는 모든 프로세스를 고정시키고 CPU를 끄는 것입니다. 그런 경우에 당신의 시간은 터지지 않을 것입니다. 커널을 깨우고 CPU가 다시 꺼지지 않도록 잠자기를 설정하는 이벤트를 만들어야합니다. 이것은 안드로이드 알람을 사용하여 수행 할 수 있습니다.

    0

    타이머를 절전 모드에서 정확하게 작동시키는 유일한 방법은 Wakelock을 사용하여 장치를 부분적으로 활성화하는 것입니다. 문서에 따르면 항상 타이머가 작동해야 응용 프로그램이 작동하는지 확인하십시오.

    장치 배터리 수명은이 API를 사용하면 큰 영향을받습니다.. PowerManager.WakeLock을 필요로하지 않는 한 획득하지 마십시오. 가능한 한 최소 수준을 사용하고 최대한 빨리 해제하십시오.당신이 가동 잠금을 사용하여 부분적으로 깨어 장치를 유지해야 할 것 같은 PowerManager 클래스를 통해

    이동,

    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); 
        wl.acquire(); 
        ..cpu will stay on during this section.. 
        wl.release();