Androidでタイマーを設定する方法


172

タスクを開始するためにAndroidでタイマーを設定する適切な方法は何ですか(UIを変更しない、私が作成した関数)。これをJavaの方法で使用します。http//docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html

それともアンドロイド(アンドロイドのハンドラ)にもっと良い方法がありますか?

回答:


143

java.util.Timerおよびjava.util.TimerTaskを介してタイマーを使用する標準的なJavaの方法は、Androidでは正常に機能しますが、このメソッドは新しいスレッドを作成することに注意してください。

非常に便利なHandlerクラス(android.os.Handler)の使用を検討し、sendMessageAtTime(android.os.Message, long)またはを介してハンドラーにメッセージを送信できますsendMessageDelayed(android.os.Message, long)。メッセージを受信したら、必要なタスクを実行できます。2番目のオプションは、Runnableオブジェクトを作成し、ハンドラーの関数postAtTime(java.lang.Runnable, long)またはを介してそれをスケジュールすることpostDelayed(java.lang.Runnable, long)です。


10
これはアンドロイドで物事を行うには間違った方法です。Androidでは、将来的にタスクを実行するために、アラームマネージャー(developer.android.com/reference/android/app/AlarmManager.html)を使用します。
Kurtis Nusbaum、2011年

9
@Kurtis Nusbaum質問は、タスクがどれだけ遠い将来のことであるかを述べていません。
クリストファーペリー

67
@KurtisNusbaum必ずしもそうとは限りません。状況によって異なります。AlarmManagerのドキュメントには、「注:アラームマネージャーは、アプリケーションが現在実行されていない場合でも、特定の時間にアプリケーションコードを実行したい場合を対象としています。通常のタイミング操作(ティック、タイムアウトなど)の場合ハンドラーを使用する方が簡単ではるかに効率的です。」
クリストファーペリー

5
@Scienceprodigyああ、なるほど。けっこうだ。
Kurtis Nusbaum

10
タスクをスケジュールするハンドラーメソッドの使用は、アプリケーションがwakeLockを取得していて、電話がスリープ状態にならないことが確実な場合にのみ信頼できます。電話がスリープ状態になった場合、sendMessageDelayedとsendMessageAtTimeは機能しません。したがって、そのシナリオでは、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がリンクを維持できない問題について話しました。
Samuel

1
2007年のこの記事-間違いではありませんが、モバイル記事が3年以上前のものであるかどうかは常に疑わしいものです。物事はかなり急速に変化します。
StackOverflowed 2012

1
ここで回答のリンクの主要なポイントを引用できれば、StackOverflowのようになります。
n611x007 2013

1
@naxa、この応答をStackOverflowのようにするための2セント。
Samuel

131

私が見たように、タイマーの実装にはjava.util.Timerが最も使用されています。

繰り返しタスクの場合:

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

タスクを1回実行する場合:

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


タスクは、最初の実行の時間の
に実行されるメソッドです
間隔は実行を繰り返す時間です)


9
ミリ秒単位の時間であることを追加します
Uri

2
アンドロイドのためのdevのドキュメントscheduleAtFixedRate
n611x007

1
taskjava.util.TimerTaskから継承してオーバーライドするクラスのインスタンスである場合がありますvoid run()
n611x007 2013

2
非常に多くの賛成票。あなたはこれをすることができます。しかし、@サミュエルはより良い方法を説明しています。理由については、「ここで説明されている項目」リンクを参照してください。また、タイマースレッドからUIを更新できません!そして、他のスレッドでこれらの他のハンドラーベースの回答を見てください:(単純)stackoverflow.com/a/6702767/199364、または(さまざまな代替案を示しています)stackoverflow.com/a/4598737/199364
ToolmakerSteve

@quemefulは、常に利便性についてではなく、コードの品質と効率についてです。この方法では、ハンドラーを使用するよりも多くのリソースを使用します
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 2018年

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を使用することを推奨していますをして、アプリケーションが実行されていない場合に指定された時間に起動するインテントを登録するしています。

それ以外の場合は、ハンドラを使用する必要があります。

注:アラームマネージャーは、アプリケーションが現在実行されていなくても、特定の時間にアプリケーションコードを実行させたい場合を対象としています。通常のタイミング操作(ティック、タイムアウトなど)では、ハンドラーを使用する方が簡単で効率的です。


11

では、2つのクラスが必要になります。5秒(5000ミリ秒)ごとにモバイルオーディオプロファイルを変更するコードを投稿しています...

ファーストクラス

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

私はAndroidの初心者ですが、上記の回答に基づいて作成したタイマークラスを以下に示します。それは私のアプリで動作しますが、どんな提案も歓迎します。

使用例:

...{
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

Androidでこれを行う方法は、バックグラウンドサービスを実行する必要があるということです。そのバックグラウンドアプリケーションで、タイマーを作成します。タイマーが「ティック」(待機する間隔を設定)したら、開始したいアクティビティを起動します。

http://developer.android.com/guide/topics/fundamentals.html(<-この記事では、アクティビティ、サービス、インテント、およびその他のAndroid開発の基本的なコアとの関係について説明しています)


1

TimerTimerTask)を使用したり、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.