Android에서 반복 작업 예약
앱이 포 그라운드에있는 한 전용 서버에 현재 상태를 보내는 반복 작업이있는 앱을 설계하고 있습니다.
웹을 통한 검색에서 나는 몇 가지 다른 접근 방식을 보았으며 이것을 수행하는 가장 좋은 방법이 무엇인지 알고 싶었습니다.
서버 호출을 예약하는 가장 좋은 방법은 무엇입니까?
내가 본 옵션은 다음과 같습니다.
타이머 .
서비스 .
AlarmManager를 사용한 BroadcastReciever .
당신의 의견은 무엇입니까?
편집 :
내가 필요한 이유는 모든 사용자 작업을 원격 서버로 보내는 채팅 기반 앱 때문입니다.
즉, 사용자가 메시지를 입력하고 있고, 사용자가 메시지를 읽고 있거나, 사용자가 온라인 상태이고, 사용자가 오프라인 상태입니다.
즉, 간격마다 한 번, 내가하고있는 일을 서버에 보내야합니다. 다른 사람들과 대화방을 열기 때문에 내가하는 일을 알아야합니다.
whatsapp 메시지 피드백 메커니즘과 유사합니다.
편집 # 2 : Android 교육 의 필수 섹션 에서 읽을 수있는 배터리 소모 문제를 방지하기 위해 API (또는 하위 API)를
통해 거의 항상 반복 작업을 예약해야합니다.JobScheduler
FirebaseJobDispatcher
나는 확실하지 않지만 내 지식에 따라 내 견해를 공유합니다. 내가 틀렸다면 항상 최선의 대답을 받아들입니다.
경보 관리자
알람 리시버의 onReceive()
메소드가 실행 되는 동안 알람 관리자는 CPU 웨이크 잠금을 유지합니다 . 이렇게하면 브로드 캐스트 처리가 완료 될 때까지 전화기가 절전 모드로 전환되지 않습니다. 일단 onReceive()
반환, 알람 Manager는이 웨이크 잠금을 해제합니다. 즉, onReceive()
분석법이 완료 되는 즉시 전화기가 절전 모드로 전환 됩니다. 알람 리시버 Context.startService()
가로 전화를 걸면 요청 된 서비스가 시작되기 전에 전화기가 잠자기 상태 일 수 있습니다. 이를 방지하려면 BroadcastReceiver
및 Service
서비스를 사용할 수있을 때까지 전화가 계속 실행되도록하기 위해 별도의 웨이크 잠금 정책을 구현해야합니다.
참고 : 알람 관리자는 애플리케이션이 현재 실행되고 있지 않더라도 특정 시간에 애플리케이션 코드를 실행하려는 경우를위한 것입니다. 일반적인 타이밍 작업 (틱, 시간 초과 등)의 경우 처리기를 사용하는 것이 더 쉽고 훨씬 효율적입니다.
시간제 노동자
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
'development' 카테고리의 다른 글
프로그래밍 방식으로보기를 숨기는 방법? (0) | 2020.07.23 |
---|---|
제출시 Xcode 8 "앱 환경에서 aps-environment 인 타이틀먼트가 누락되었습니다" (0) | 2020.07.23 |
스칼라 목록을 만드는 기본 방법 (0) | 2020.07.22 |
소켓 : Java를 사용하여 포트 가용성 발견 (0) | 2020.07.22 |
String switch 문이 null을 지원하지 않는 이유는 무엇입니까? (0) | 2020.07.22 |