안드로이드에서 타이머를 설정하는 방법


172

작업을 시작하기 위해 안드로이드에서 타이머를 설정하는 올바른 방법은 무엇입니까 (UI를 변경하지 않는 만든 기능)? 이것을 Java 방식으로 사용하십시오 : http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html

아니면 안드로이드 (안드로이드의 핸들러)에 더 좋은 방법이 있습니까?

답변:


143

java.util.Timerjava.util.TimerTask 를 통해 타이머를 사용하는 표준 Java 방법 은 Android에서 제대로 작동하지만이 메소드는 새 스레드를 작성합니다.

당신은 매우 편리한 사용을 고려할 수 처리기 클래스 (android.os.Handler)를 거쳐서 핸들러에 메시지를 보내 sendMessageAtTime(android.os.Message, long)거나 sendMessageDelayed(android.os.Message, long). 메시지를 받으면 원하는 작업을 실행할 수 있습니다. 두 번째 옵션은 생성하는 것입니다 의 Runnable 객체를 그리고 처리기의 기능을 통해 예약 postAtTime(java.lang.Runnable, long)또는 postDelayed(java.lang.Runnable, long).


10
이것은 안드로이드에서 일을하는 잘못된 방법입니다. 안드로이드에서는 미래의 작업을 실행하기 위해 알람 관리자 (developer.android.com/reference/android/app/AlarmManager.html)를 사용하려고합니다.
Kurtis Nusbaum

9
@Kurtis Nusbaum이 과제는 미래에 얼마나 멀리 있는지 말하지 않습니다.
크리스토퍼 페리

67
@KurtisNusbaum 반드시 사실은 아니지만 상황에 따라 다릅니다. AlarmManager의 문서는 "참고 : Alarm Manager는 현재 응용 프로그램이 실행되고 있지 않은 경우에도 특정 시간에 응용 프로그램 코드를 실행하려는 경우를위한 것입니다. 정상적인 타이밍 작업 (틱, 시간 초과 등) Handler를 사용하는 것이 더 쉽고 훨씬 효율적입니다. "
크리스토퍼 페리

5
@Scienceprodigy 아, 알겠습니다. 그럴 수 있지.
Kurtis Nusbaum

10
작업을 예약하는 처리기 방법을 사용하는 것은 응용 프로그램이 wakeLock을 획득 한 경우에만 신뢰할 수 있으므로 전화기가 절전 상태가되지 않아야합니다. 전화가 절전 상태가되면 sendMessageAlayTime 및 sendMessageDelayed가 작동하지 않습니다. 따라서이 시나리오에서 AlarmManager는 신뢰할 수있는 선택입니다.
crazyaboutliv

159

예 java의 타이머를 사용할 수 있지만 질문에 따라 더 나은 방법을 요청합니다 (모바일). 어떤 설명여기있습니다.


StackOverflow를 위해 :

이후 Timer 는 새 스레드를 생성무거운 것으로 간주 될 수 있습니다.

당신이 필요로하는 모든 활동이 실행되는 동안 다시 전화하는 것입니다 만하면 핸들러 와 함께 핸들러를 사용할 수 있습니다.

실행 가능 :

private final int interval = 1000; // 1 Second
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
    public void run() {
        Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
    }
};
...
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);

또는 메시지

private final int EVENT1 = 1; 
private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {         
        case Event1:
            Toast.makeText(MyActivity.this, "Event 1", Toast.LENGTH_SHORT).show();
            break;

        default:
            Toast.makeText(MyActivity.this, "Unhandled", Toast.LENGTH_SHORT).show();
            break;
        }
    }
};

...

Message msg = handler.obtainMessage(EVENT1);
handler.sendMessageAtTime(msg, System.currentTimeMillis()+interval);
handler.sendMessageDelayed(msg, interval);

참고로 다른 스레드에서 UI 스레드로 코드 조각을 실행하려는 경우이 방법을 사용할 수 있습니다.

활동이 실행 중이 아니더라도 전화를 다시 받아야하는 경우 AlarmManager를 사용할 수 있습니다.


1
오 예, 나는이 대답을 정확하게 봤습니다. 유용한 링크에 대한 의견을 보내십시오.
ulidtko

1
링크를 업데이트하고 링크를 유지 관리하는 데 문제가있는 Google에 대해 이야기합니다.
사무엘

1
2007 년의이 기사-그것이 틀렸다고 말하지는 않지만, 3 년이 지난 모바일 기사는 항상 의심 스럽다. 상황이 아주 빨리 바뀝니다.
StackOverflowed

1
답변에서 링크의 주요 요점을 인용 할 수 있다면 StackOverflow와 비슷합니다.
n611x007

1
@ naxa, 내 2 센트는이 답변을 StackOverflow와 유사하게 만듭니다.
사무엘

131

내가 본 것처럼 java.util.Timer 는 타이머 구현에 가장 많이 사용됩니다.

반복되는 작업의 경우 :

new Timer().scheduleAtFixedRate(task, after, interval);

한 번의 작업 실행 :

new Timer().schedule(task, after);


태스크 는 초기 실행 시간
이후 에 실행될 방법입니다
( 실행 반복 시간 간격 ).


9
시간을 밀리 초 단위로 추가하겠습니다
Uri


1
taskjava.util.TimerTask 에서 상속 하고 재정의 하는 클래스의 인스턴스 일 수 있습니다 void run().
n611x007

2
너무 많은 공감대. 당신은 이것을 할 수 있습니다. 그러나 @Samuel은 더 나은 방법을 설명합니다. 왜 "여기에 설명되어 있는지"링크를 참조하십시오. 또한 타이머 스레드에서 UI를 업데이트 할 수 없습니다! 다른 스레드의 다른 처리기 기반 답변을 참조하십시오 (단순) stackoverflow.com/a/6702767/199364 또는 (다양한 대안 표시) stackoverflow.com/a/4598737/199364
ToolmakerSteve

@quemeful은 항상 편의성에 관한 것이 아니라 코드 품질과 효율성에 관한 것입니다. 이렇게하는 방법은 Handler를 사용하는 것보다 더 많은 리소스를 사용합니다
inDepth

33

이 기능이 도움이 되었기를 바랍니다 . Android CountDownTimer 클래스

예 :

 new CountDownTimer(30000, 1000) {
      public void onTick(long millisUntilFinished) {
          mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
      }

      public void onFinish() {
          mTextField.setText("done!");
      }  
}.start();

1
이것은 가장 쉽고 비디오 재생 시작 시간처럼 간단한 카운트 다운을 위해 머리에 맞습니다
Vijay Kumar Kanta

17

아마 Timerconcept

new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval

 public void onTick(long millisUntilFinished) {
  }
  public void onFinish() {
 }
}.start();

또는

방법 2 ::

타이머 프로그래밍

time이라는 이름의 int의 새 변수를 추가하십시오. 0으로 설정하십시오. MainActivity.java의 onCreate 함수에 다음 코드를 추가하십시오.

//Declare the timer
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {

    @Override
    public void run() {
        //Called each time when 1000 milliseconds (1 second) (the period parameter)
    }

},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);

run 메소드로 이동하여 다음 코드를 추가하십시오.

//We must use this function in order to change the text view text
runOnUiThread(new Runnable() {

    @Override
    public void run() {
        TextView tv = (TextView) findViewById(R.id.main_timer_text);
        tv.setText(String.valueOf(time));
        time += 1;
    }

});

11

상황에 따라 다릅니다.

Android 설명서에서는 AlarmManager 를 사용 하여 응용 프로그램이 실행되고 있지 않을 경우 지정된 시간에 시작되는 인 텐트를 등록 해야한다고 제안합니다 .

그렇지 않으면 Handler를 사용해야합니다.

참고 : 알람 관리자는 현재 응용 프로그램이 실행되고 있지 않더라도 특정 시간에 응용 프로그램 코드를 실행하려는 경우를위한 것입니다. 일반적인 타이밍 작업 (틱, 시간 초과 등)의 경우 처리기를 사용하는 것이 더 쉽고 훨씬 효율적입니다.


11

우리는 간다. 우리는 두 개의 수업이 필요하다. 5 초 (5000 밀리 초)마다 모바일 오디오 프로파일을 변경하는 코드를 게시하고 있습니다 ...

우리의 1 등석

public class ChangeProfileActivityMain extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        Timer timer = new Timer();
        TimerTask updateProfile = new CustomTimerTask(ChangeProfileActivityMain.this);
        timer.scheduleAtFixedRate(updateProfile, 0, 5000);
    }

}

우리의 2 등석

public class CustomTimerTask extends TimerTask {

    private AudioManager audioManager;
    private Context context;
    private Handler mHandler = new Handler();

    // Write Custom Constructor to pass Context
    public CustomTimerTask(Context con) {
        this.context = con;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        // your code starts here.
        // I have used Thread and Handler as we can not show Toast without starting new thread when we are inside a thread.
        // As TimePicker has run() thread running., So We must show Toast through Handler.post in a new Thread. Thats how it works in Android..
        new Thread(new Runnable() {
            @Override
            public void run() {
                audioManager = (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
                            audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
                            Toast.makeText(context, "Ringer Mode set to Normal", Toast.LENGTH_SHORT).show();
                        } else {
                            audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                            Toast.makeText(context, "Ringer Mode set to Silent", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        }).start();

    }

}

5

나는 안드로이드 초보자이지만 위의 답변을 기반으로 만든 타이머 클래스가 있습니다. 내 앱에서 작동하지만 제안을 환영합니다.

사용 예 :

...{
public Handler uiHandler = new Handler();

  private Runnable runMethod = new Runnable()
    {
        public void run()
        {
              // do something
        }
    };

    timer = new UITimer(handler, runMethod, timeoutSeconds*1000);       
        timer.start();
}...

public class UITimer
{
    private Handler handler;
    private Runnable runMethod;
    private int intervalMs;
    private boolean enabled = false;
    private boolean oneTime = false;

    public UITimer(Handler handler, Runnable runMethod, int intervalMs)
    {
        this.handler = handler;
        this.runMethod = runMethod;
        this.intervalMs = intervalMs;
    }

    public UITimer(Handler handler, Runnable runMethod, int intervalMs, boolean oneTime)
    {
        this(handler, runMethod, intervalMs);
        this.oneTime = oneTime;
    }

    public void start()
    {
        if (enabled)
            return;

        if (intervalMs < 1)
        {
            Log.e("timer start", "Invalid interval:" + intervalMs);
            return;
        }

        enabled = true;
        handler.postDelayed(timer_tick, intervalMs);        
    }

    public void stop()
    {
        if (!enabled)
            return;

        enabled = false;
        handler.removeCallbacks(runMethod);
        handler.removeCallbacks(timer_tick);
    }

    public boolean isEnabled()
    {
        return enabled;
    }

    private Runnable timer_tick = new Runnable()
    {
        public void run()
        {
            if (!enabled)
                return;

            handler.post(runMethod);

            if (oneTime)
            {
                enabled = false;
                return;
            }

            handler.postDelayed(timer_tick, intervalMs);
        }
    }; 
}

3

처리기를 사용하고 타이머를 만들 수 있습니다. 나는 이것을 추상 클래스로 포장했다. 그냥 파생시키고 구현하면 좋습니다.

 public static abstract class SimpleTimer {
    abstract void onTimer();

    private Runnable runnableCode = null;
    private Handler handler = new Handler();

    void startDelayed(final int intervalMS, int delayMS) {
        runnableCode = new Runnable() {
            @Override
            public void run() {
                handler.postDelayed(runnableCode, intervalMS);
                onTimer();
            }
        };
        handler.postDelayed(runnableCode, delayMS);
    }

    void start(final int intervalMS) {
        startDelayed(intervalMS, 0);
    }

    void stop() {
        handler.removeCallbacks(runnableCode);
    }
}

handler.postDelayed코드가 실행되기 전에가 호출 된다는 점에 유의하십시오. 이렇게하면 타이머가 "예상 된"시간보다 더 닫힙니다. 그러나 타이머가 자주 실행되고 작업 ( onTimer())이 긴 경우 겹치는 부분이있을 수 있습니다. intervalMS작업이 완료된 후 계산을 시작 하려면 onTimer()전화를 한 줄 위로 이동하십시오 .


2

안드로이드 에서이 작업을 수행하는 방법은 백그라운드 서비스가 실행되어야한다는 것입니다. 해당 백그라운드 애플리케이션에서 타이머를 작성하십시오. 타이머가 "틱"할 때 (대기 시간 간격 설정) 시작할 활동을 시작하십시오.

http://developer.android.com/guide/topics/fundamentals.html (<-이 기사는 활동, 서비스, 의도 및 Android 개발의 다른 핵심 기본 요소 간의 관계를 설명합니다)


1

나는 ( Timer, TimerTask) 을 사용하고 Handler주기적으로 작업을 시작 (시간이 많이 걸리는)하는 데 사용했습니다. 이제 전체를 RxJava로 전환했습니다. RxJava Observable.timer는보다 간단하고 오류가 적으며 번거 로움없이 사용할 수있는 기능을 제공합니다.

public class BetterTimerFragment extends Fragment {
  public static final String TAG = "BetterTimer";
  private TextView timeView;
  private Subscription timerSubscription;

  @Override
  public View onCreateView(LayoutInflater inflater,
                           @Nullable ViewGroup container,
                           @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_timer, container, false);
  }

  @Override
  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    timeView = (TextView) view.findViewById(R.id.timeView);
  }

  @Override
  public void onResume() {
    super.onResume();

    // Right after the app is visible to users, delay 2 seconds
    // then kick off a (heavy) task every 10 seconds.
    timerSubscription = Observable.timer(2, 10, TimeUnit.SECONDS)
        .map(new Func1<Long, String>() {
          @Override
          public String call(Long unused) {
            // TODO: Probably do time-consuming work here.
            // This runs on a different thread than the main thread.
            return "Time: " + System.currentTimeMillis();
          }
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<String>() {
          @Override
          public void call(String timeText) {
            // The result will then be propagated back to the main thread.
            timeView.setText(timeText);
          }
        }, new Action1<Throwable>() {
          @Override
          public void call(Throwable throwable) {
            Log.e(TAG, throwable.getMessage(), throwable);
          }
        });
  }

  @Override
  public void onPause() {
    super.onPause();

    // Don't kick off tasks when the app gets invisible.
    timerSubscription.unsubscribe();
  }
}

1

타이밍 작업에는 Handler 를 사용해야합니다 .

백그라운드 서비스를 실행해야하는 경우 AlarmManager를 사용하는 것이 좋습니다.


0

이 예제는 Kotlin에서 파괴 된 타이머 unitl을 시작합니다.

private lateinit var timerTask: TimerTask

 timerTask = object : TimerTask() {
        override fun run() {
            Log.d("KTZ", "$minutes:$seconds");
            timeRecordingLiveData.postValue("$minutes:$seconds")
            seconds += 1;
            if (seconds == 60) {
                Log.d("KTZ", "$minutes:$seconds");
                timeRecordingLiveData.postValue("$minutes:$seconds")
                seconds = 0;
                minutes += 1;
            }
        }

    }

onDestroy ()에서 타이머 작업 취소

timerTask.cancel()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.