development

Android에서 반복 작업 예약

big-blog 2020. 7. 22. 07:37
반응형

Android에서 반복 작업 예약


앱이 포 그라운드에있는 한 전용 서버에 현재 상태를 보내는 반복 작업이있는 앱을 설계하고 있습니다.

웹을 통한 검색에서 나는 몇 가지 다른 접근 방식을 보았으며 이것을 수행하는 가장 좋은 방법이 무엇인지 알고 싶었습니다.

서버 호출을 예약하는 가장 좋은 방법은 무엇입니까?

내가 본 옵션은 다음과 같습니다.

  1. 타이머 .

  2. ScheduledThreadPoolExecutor .

  3. 서비스 .

  4. AlarmManager를 사용한 BroadcastReciever .

당신의 의견은 무엇입니까?

편집 :
내가 필요한 이유는 모든 사용자 작업을 원격 서버로 보내는 채팅 기반 앱 때문입니다.
즉, 사용자가 메시지를 입력하고 있고, 사용자가 메시지를 읽고 있거나, 사용자가 온라인 상태이고, 사용자가 오프라인 상태입니다.

즉, 간격마다 한 번, 내가하고있는 일을 서버에 보내야합니다. 다른 사람들과 대화방을 열기 때문에 내가하는 일을 알아야합니다.

whatsapp 메시지 피드백 메커니즘과 유사합니다. 메시지가 전달 된 것 같습니다

편집 # 2 : Android 교육 필수 섹션 에서 읽을 수있는 배터리 소모 문제를 방지하기 위해 API (또는 하위 API)를
통해 거의 항상 반복 작업을 예약해야합니다.JobSchedulerFirebaseJobDispatcher


나는 확실하지 않지만 내 지식에 따라 내 견해를 공유합니다. 내가 틀렸다면 항상 최선의 대답을 받아들입니다.

경보 관리자

알람 리시버의 onReceive()메소드가 실행 되는 동안 알람 관리자는 CPU 웨이크 잠금을 유지합니다 . 이렇게하면 브로드 캐스트 처리가 완료 될 때까지 전화기가 절전 모드로 전환되지 않습니다. 일단 onReceive()반환, 알람 Manager는이 웨이크 잠금을 해제합니다. 즉, onReceive()분석법이 완료 되는 즉시 전화기가 절전 모드로 전환 됩니다. 알람 리시버 Context.startService()가로 전화를 걸면 요청 된 서비스가 시작되기 전에 전화기가 잠자기 상태 일 수 있습니다. 이를 방지하려면 BroadcastReceiverService서비스를 사용할 수있을 때까지 전화가 계속 실행되도록하기 위해 별도의 웨이크 잠금 정책을 구현해야합니다.

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

시간제 노동자

timer = new Timer();

    timer.scheduleAtFixedRate(new TimerTask() {

        synchronized public void run() {

            \\ here your todo;
            }

        }}, TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1));

Timer에 의해 해결되는 몇 가지 단점이 있습니다 ScheduledThreadPoolExecutor. 그래서 최선의 선택이 아닙니다

ScheduledThreadPoolExecutor .

java.util.Timer또는 ScheduledThreadPoolExecutor(선호)를 사용 하여 백그라운드 스레드에서 규칙적인 간격으로 작업이 발생하도록 예약 할 수 있습니다.

다음은 후자를 사용하는 샘플입니다.

ScheduledExecutorService scheduler =
    Executors.newSingleThreadScheduledExecutor();

scheduler.scheduleAtFixedRate
      (new Runnable() {
         public void run() {
            // call service
         }
      }, 0, 10, TimeUnit.MINUTES);

그래서 나는 선호했다 ScheduledExecutorService

그러나 응용 프로그램이 실행되는 동안 업데이트가 발생하면 Timer다른 답변에서 제안 된대로 또는 최신 버전을 사용할 수 있습니다 ScheduledThreadPoolExecutor. 응용 프로그램이 실행 중이 아니더라도 업데이트되는 경우 AlarmManager.

알람 관리자는 응용 프로그램이 현재 실행되고 있지 않더라도 특정 시간에 응용 프로그램 코드를 실행하려는 경우를위한 것입니다.

응용 프로그램을 끌 때 업데이트를 계획하는 경우 10 분마다 한 번씩 매우 자주 발생하므로 약간의 전력 소비가 발생할 수 있습니다.


시간제 노동자

javadocs 에서 언급했듯이 ScheduledThreadPoolExecutor를 사용하는 것이 좋습니다.

ScheduledThreadPoolExecutor

유스 케이스에 여러 작업자 스레드가 필요하고 휴면 간격이 작은 경우이 클래스를 사용하십시오. 얼마나 작습니까? 글쎄, 나는 약 15 분 정도 말할 것입니다. 현재 AlarmManager시작 일정 간격이며 더 작은 수면 간격의 경우이 클래스를 사용할 수 있다고 제안합니다. 마지막 진술을 뒷받침 할 데이터가 없습니다. 직감입니다.

서비스

VM에서 언제든지 서비스를 닫을 수 있습니다. 반복 작업에 서비스를 사용하지 마십시오. 되풀이 작업은 서비스를 시작할있으며 이는 전적으로 또 다른 문제입니다.

AlarmManager를 통한 BroadcastReciever

더 긴 수면 간격 (> 15 분)의 경우이 방법을 사용하십시오. AlarmManager이미 일정 ( AlarmManager.INTERVAL_DAY)이 있으므로 처음 예약 된 후 며칠 동안 작업을 트리거 할 수 있습니다. 또한 코드를 실행하기 위해 CPU를 깨울 수 있습니다.

타이밍 및 작업자 스레드 요구 사항에 따라 이러한 솔루션 중 하나를 사용해야합니다.


나는 이것이 오래된 질문이며 답을 얻었지만 누군가를 도울 수 있음을 알고 있습니다. 당신의activity

private ScheduledExecutorService scheduleTaskExecutor;

onCreate

  scheduleTaskExecutor = Executors.newScheduledThreadPool(5);

    //Schedule a task to run every 5 seconds (or however long you want)
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            // Do stuff here!

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // Do stuff to update UI here!
                    Toast.makeText(MainActivity.this, "Its been 5 seconds", Toast.LENGTH_SHORT).show();
                }
            });

        }
    }, 0, 5, TimeUnit.SECONDS); // or .MINUTES, .HOURS etc.

예약 반복 알람 인용 -트레이드 오프 문서 이해 :

앱 수명 이외의 작업을 트리거하는 일반적인 시나리오는 서버와 데이터를 동기화하는 것입니다. 반복되는 알람을 사용하고 싶을 수도 있습니다. 그러나 앱 데이터를 호스팅하는 서버를 소유하고 있다면 동기화 어댑터와 함께 Google 클라우드 메시징 (GCM)을 사용하는 것이 AlarmManager보다 더 나은 솔루션입니다. 동기화 어댑터는 AlarmManager와 동일한 일정 옵션을 제공하지만 훨씬 더 융통성을 제공합니다.

따라서이를 바탕으로 서버 호출을 예약하는 가장 좋은 방법은 동기화 어댑터 와 함께 Google 클라우드 메시징 (GCM)사용하는 것 입니다.


사용자가 반복하려는 작업을 사용자 정의 TimeTask run () 메서드에 추가하는 정시 작업을 만들었습니다. 성공적으로 재발합니다.

 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Timer;
 import java.util.TimerTask;

 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.CheckBox;
 import android.widget.TextView;
 import android.app.Activity;
 import android.content.Intent;

 public class MainActivity extends Activity {

     CheckBox optSingleShot;
     Button btnStart, btnCancel;
     TextView textCounter;

     Timer timer;
     MyTimerTask myTimerTask;

     int tobeShown = 0  ;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    optSingleShot = (CheckBox)findViewById(R.id.singleshot);
    btnStart = (Button)findViewById(R.id.start);
    btnCancel = (Button)findViewById(R.id.cancel);
    textCounter = (TextView)findViewById(R.id.counter);
    tobeShown = 1;

    if(timer != null){
        timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
        //singleshot delay 1000 ms
        timer.schedule(myTimerTask, 1000);
    }else{
        //delay 1000ms, repeat in 5000ms
        timer.schedule(myTimerTask, 1000, 1000);
    }

    btnStart.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View arg0) {


            Intent i = new Intent(MainActivity.this, ActivityB.class);
            startActivity(i);

            /*if(timer != null){
                timer.cancel();
            }

            //re-schedule timer here
            //otherwise, IllegalStateException of
            //"TimerTask is scheduled already" 
            //will be thrown
            timer = new Timer();
            myTimerTask = new MyTimerTask();

            if(optSingleShot.isChecked()){
                //singleshot delay 1000 ms
                timer.schedule(myTimerTask, 1000);
            }else{
                //delay 1000ms, repeat in 5000ms
                timer.schedule(myTimerTask, 1000, 1000);
            }*/
        }});

    btnCancel.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            if (timer!=null){
                timer.cancel();
                timer = null;
            }
        }
    });

}

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

    if(timer != null){
        timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
        //singleshot delay 1000 ms
        timer.schedule(myTimerTask, 1000);
    }else{
        //delay 1000ms, repeat in 5000ms
        timer.schedule(myTimerTask, 1000, 1000);
    }
}


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

    if (timer!=null){
        timer.cancel();
        timer = null;
    }

}

@Override
protected void onStop() {
    super.onStop();

    if (timer!=null){
        timer.cancel();
        timer = null;
    }

}

class MyTimerTask extends TimerTask {

    @Override
    public void run() {

        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = 
                new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
        final String strDate = simpleDateFormat.format(calendar.getTime());

        runOnUiThread(new Runnable(){

            @Override
            public void run() {
                textCounter.setText(strDate);
            }});
    }
}

}

참고 URL : https://stackoverflow.com/questions/14376470/scheduling-recurring-task-in-android

반응형