1. 스마트폰은 기본적으로 일정 시간동안 아무런 반응이 없으면 자동으로 화면이 꺼지게 됩니다.
원할 경우 실행되는 동안 화면을 안꺼지 게 할수 있습니다.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
을 추가하게 되면 실행되는 동안 화면이 꺼지지 않습니다.
2. Dialog 타이틀바 없애기.
3. EditText에 이벤트 주기
EditText 이벤트는 addTextChangedListener() 를 사용하면 보다 쉽게 다룰수가 있었다.( setOnClickListener() 보다 좋음.)
et.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
});
4. intent : https://yoo-hyeok.tistory.com/15?category=708422 putExtra를 단일 String, ArrayList 모두 가능.
5. 서비스 등록하기
Service는 background에서 처리를 계속할 수 있는 클래스이다.
Service는 기본적으로 activity를 가지지 않는다.
서비스를 구현하기 위한 3가지 절차
-- Service 클래스를 확장한 새로운 클래스 정의
-- Manifest file에 Service 선언 추가
-- App에서 Service 실행
1. 서비스를 실행하는 클래스 - 타이머를 이용한 반복 처리.
public class MyService extends Service implements Runnable {
// 시작 ID
private int mStartId;
// 서비스에 대한 스레드에 연결된 Handler. 타이머 이용한 반복 처리시 사용.
private Handler mHandler;
// 서비스 동작여부 flag
private boolean mRunning;
// 타이머 설정 (2초)
private static final int TIMER_PERIOD = 2 * 1000;
private static final int COUNT = 10;
private int mCounter;
// 서비스를 생성할 때 호출
public void onCreate() {
Log.e("MyService", "Service Created.");
super.onCreate();
mHandler = new Handler();
mRunning = false;
}
// 서비스 시작할 때 호출. background에서의 처리가 시작됨.
// startId : 서비스 시작요구 id. stopSelf에서 종료할 때 사용.
//onStart는 여러번 호출될 수 있기 때문에 식별자로 사용.
public void onStart(Intent intent, int startId) {
Log.e("MyService", "Service startId = " + startId);
super.onStart(intent, startId);
mStartId = startId;
mCounter = COUNT;
// 동작중이 아니면 run 메소드를 일정 시간 후에 시작
if (!mRunning) {
// this : 서비스 처리의 본체인 run 메소드. Runnable 인터페이스를 구현 필요.
// postDelayed : 일정시간마다 메소드 호출
mHandler.postDelayed(this, TIMER_PERIOD);
mRunning = true;
}
}
// 서비스의 종료시 호출
public void onDestroy() {
// onDestroy가 호출되어 서비스가 종료되어도
// postDelayed는 바로 정지되지 않고 다음 번 run 메소드를 호출.
mRunning = false;
super.onDestroy();
}
// 서비스 처리
public void run() {
if (!mRunning) {
// 서비스 종료 요청이 들어온 경우 그냥 종료
Log.e("MyService", "run after destory");
return;
} else if (--mCounter <= 0) {
// 지정한 횟수 실행하면 스스로 종료
Log.e("MyService", "stop Service id = "+mStartId);
stopSelf(mStartId);
} else {
// 다음 작업을 다시 요구
Log.e("MyService", "mCounter : " + mCounter);
mHandler.postDelayed(this, TIMER_PERIOD);
}
}
// 원격 메소드 호출을 위해 사용
// 메서드 호출을 제공하지 않으면 null을 반환
public IBinder onBind(Intent intent) {
return null;
}
}
2. 서비스 실행, 종료를 사용자가 요청하는 클래스
// 서비스 시작과 종료를 요구하는 Activity
public class MyServiceActivity extends Activity {
ComponentName mService; // 시작 서비스의 이름
TextView mTextView; // 서비스 상태 표시
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView)findViewById(R.id.text_view);
Button start = (Button)findViewById(R.id.start_button);
start.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
startHelloService();
}});
Button stop = (Button)findViewById(R.id.stop_button);
stop.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
stopHelloService();
}});
}
// 서비스 시작 요청
private void startHelloService() {
mService = startService(new Intent(this, MyService.class));
mTextView.append(mService.toShortString()+" started.\n");
}
// 실행한 서비스 중지 요청
private void stopHelloService() {
if (mService == null) {
mTextView.append("No requested service.\n");
return;
}
Intent i = new Intent();
i.setComponent(mService);
if (stopService(i))
mTextView.append(mService.toShortString()+" is stopped.\n");
else
mTextView.append(mService.toShortString()+" is alrady stopped.\n");
}
}
3. 사용자가 서비스 실행, 종료하는 화면 구성
<!-- 시작 -->
<Button android:id="@+id/start_button" android:text="Start"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<!-- 종료 -->
<Button android:id="@+id/stop_button" android:text="Stop"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<!-- 상태표시 -->
<TextView android:id="@+id/text_view_id"
android:editable="true"
android:layout_width="fill_parent" android:layout_height="fill_parent" />
6. 컴포넌트의 생명주기
컴포넌트의 생명주기는 컴포넌트를 인스턴스화 할 때 시작해서, 인스턴스가 사라질 때 종료됩니다.
액티비티의 경우 그 사이에 활성화, 비활성화가 될 수 있기 때문에 사용자에게 보이거나 , 또는 보이지 않을 수도 있습니다.
1. 액티비티 생명주기
액티비티는 필수적으로 세 가지의 상태를 가지고 있습니다.
▣ 활성화(activity) 또는 실행 (running) 상태
액티비티가 포그라운드 화면으로 사용자에게 보이는 상태입니다 ( 즉, 현재 태스크에서 스택의 최상위에 위치하는 것).
이 상태는 사용자 액션을 받을 수 있게 됩니다.
▣ 멈춤(paused) 상태
사용자 액션을 받진 못하지만 여전히 보여지고 있는 상태입니다. 즉 다른 액티비티가 그 위에 위치하지만 해당 액티비티가 화면을 전부 채우지 않거나 투명해서 멈춤 상태의 액티비티를 볼 수 있는 상태입니다.
이 상태의 액티비티는 살아있습니다 ( 모든 상태정보와 멤버를 유지 중 )
하지만 , 메모리 부족시엔 시스템에 의해 강제종료 될 수 있습니다.
▣ 정지 (stopped) 상태
완전히 다른 액티비티에 의해 가려진 상태입니다.더 이상 사용자에게 보이진 않지만 여전히 살아서(정보와 멤버유지) 있는 상태이죠.
여전히 보여지진 않기 때문에 메모리 부족시엔 강제종료 될 수 있습니다.
액티비티가 멈춤 또는 정지 상태라면, 시스템은 finish() 메소드를 호출하거나 프로세스를 강제종료 시킴으로서 메모리에서 제거할 수 있습니다.
종료된 액티비티가 다시 실행된다면, 다시 시작되어야 하고 이전 상태로 복구되어야 할 것입니다.
액티비티 상태변화
액티비티의 상태가 변하면 아래의 메소드가 호출됨으로써 변화가 통보되는데요.
이 메소들은 모두 프로텍티드(protected) 메소드 입니다.
여기의 7가지 메소드들은 오버라이드 할 수 있습니다.
단, 모든 액티비티는 최초 인스턴스 초기화를 위해 onCreate() 메소드는 무조건 구현해야 합니다.
또한, 액티비티 종료직전.... 마지막 기회가 될 수도 있는 시점에선 적절한 데이터 저장을 위해 onPause() 메소드도 구현해주면 좋겠네요.
액티비티 생명주기 메소드를 구현할 땐 항상 슈퍼클래스 버전을 호출하여야 합니다.
protected void onPause() {
super.onPause() ;
}
네스티드 루프(nested loop)
액티비티 생명주기 메소드를 구현하여 볼 수 있는 것은 아래와 같습니다.
▣ 액티비티 인타이어 라이프타임 ( entire lifetime )
onCreate() 와 onDestroy() 메소드 사이에서 발생합니다.
액티비티는 onCreate() 메소드에서 모든 초기 설정을 하고 onDestroy()에서 모든 리소스를 해제하죠.
▣ 액티비티 비지블 라이프타임 ( visible lifetime )
onStart() 메소드에서 onStop() 메소드 사이에서 발생합니다.
onStart() 메소드에서는 사용자 인터페이스의 변화 모니터를 위해 브로드캐스트 리시버를 등록할 수 있고 사용자가 보고있는 화면이 없을때엔 onStop() 메소드에서 제거할 수 있습니다. onStart() 와 onStop()은 액티비티가 사용자에게 보여지고 숨겨지는 상태이므로 여러번 호출 될 수 있습니다.
▣ 액티비티 포그라운드 라이프타임 ( foreground lifetime )
onResume() 메소드와 onPause() 메소드 사이에서 발생합니다.
이 기간동안 액티비티는 화면에서 다른 모든 액티비티보다 앞에 놓이며 사용자에게 보여집니다. onPause()는 기계가 꺼지거나 새로운 액티비티가 시작될 때 호출되고, onResume() 은 액티비티가 다시 복귀되거나 새로운 인텐트가 도착했을때 호출됩니다.
따라서 이 두개의 메소드 내용은 빠르고 가벼울 수록 좋겠네요.
생명주기 메소드가 하는 일
▣ onCreate()
액티비티가 최초 생성시에 호출됩니다. 초기화 설정을 하는 곳이지요. 보관된 상태의 액티비티가 있다면, 그 상태를 저장중인 Bundle 객체를 받습니다.
onStart() 메소드가 이어집니다. 강제종료가 불가능 합니다.
▣ onRestart()
액티비티가 정지 후 다시 시작되기 바로 직전에 호출됩니다.
onStart() 메소드가 이어집니다. 강제종료가 불가능 합니다.
▣ onStart()
액티비티가 사용자에게 보여지기 직전에 호출됩니다.
액티비티가 보여지게되면 onResume() 메소드가, 안보이게 되면 onStop() 메소드가 이어집니다.
강제종료가 불가능 합니다.
▣ onResume()
액티비티가 사용자와 상호작용하기 직전에 호출됩니다 (스택의 최상위에 위치)
onPause() 메소드가 이어집니다. 강제종료가 불가능 합니다.
▣ onPause()
시스템이 다른 액티비티를 시작하려 할 때 호출됩니다.
일반적으로 데이터 저장을 하기에 좋은 곳입니다.
하지만 소스코드의 속도가 빨라야합니다.
왜냐하면 이 메소드가 끝나기 전까진 다음 액티비티가 실행되지 않기 때문인데요,
액티비티가 되돌아오면 onResume(), 보이지않게되면 onStop() 이 이어집니다.
강제종료가 가능 합니다.
▣ onStop()
액티비티가 사용자에게 보이지 않을때 호출 됩니다.
액티비티가 제거되거나 다른 액티비티가 실행되어 해당 액티비티를 덮어버렸을 때, 호출되죠. 액티비티가 되돌아오면 onRestart(), 액티비티가 사라지면 onDestroy() 가 이어집니다.
강제종료가 가능 합니다.
▣ onDestroy()
액티비티 삭제 직전에 호출됩니다. 액티비티가 받는 마지막 호출 메소드가 되죠. 시스템이 메모리 확보를 위해 액티비티 인스턴스를 없애버려고 하거나 , finish() 메소드가 호출되면 호출되는 메소드입니다.
isFinishing() 메소드로 두 가지를 분기할 수 있습니다.
onStart() 메소드가 이어집니다. 강제종료가 불가능 합니다.
☞ 여기에서 onPause() 는 프로세스가 강제종료 되기 전에 호출되는 것입니다. 즉, 프로세스가 강제종료 될 때 onPause() 는 무조건 호출되는 유일한 곳이 됩니다. ( onStop(), onDestroy() 는 호출되지 않을 수 있어요 ), 따라서 데이터 저장 등의 작업은 종료되기 직전에 호출되는 onPause() 에 구현해야 되겠네요.
액티비티 상태 저장하기
시스템이 액티비티를 강제종료 했을때, 사용자는 이전의 액티비티로 돌아가고 싶을 수 있습니다. 이럴 경우 액티비티가 강제종료 되기 전에 상태를 저장할 수 있는 onSaveInstanceState() 메소드를 구현하면 저장이 가능해 집니다.
즉, 액티비티가 파괴되기전에 호출되는 메소드 인데요. ( onPause() 호출 이전에 호출됩니다. )
이 메소드는 이름/값 쌍으로 이루어진 번들 객체(Bundle) 를 인수로 가집니다. 액티비티가 다시 시작되면 번들은 onSaveInstanceState() 와 onStart() 이후에 호출되는 onRestoreInstanceState() 에게 전달됩니다.
☞ onSaveInstanceState() , onRestoreInstanceState() 메소드는 생명주기 메소드는 아닙니다.
따라서 항상 호출되지는 않으며 특정 상황 ( 액티비티 강제종료전에 onSaveInstance() 호출처럼 ) 에서만 호출됩니다. 단, 사용자 액션에 의해 종료될 때는 ( 사용자가 직접종료 ) 호출되지 않습니다.
- 사용자가 되돌아가지 않을 생각으로 종료한 것으로 판단한 것이겠죠...
onSaveInstanceState() 는 액티비티의 일시적인 상태 저장을 위한 것이므로 , 데이터 등을 안전하게 저장하려면 onPause() 메소드에서 처리해야 합니다.
액티비티 생명주기 메소드의 순서
하나의 액티비티가 다른 액티비티를 시작할 때 하나는 멈추고 정지되며, 다른 하나는 시작되는 구조를 가집니다. 생명주기 메소드의 순서는 두 개의 액티비티가 동일 프로세스 안에 있을 때에 정의됩니다.
1. 현재 액티비티("A") 의 onPause() 가 호출됩니다.
2. 다음 시작되는 액티비티("B") 의 onCreate() -> onStart() -> onResume() 이 차례대로 호출됩니다
3. "B" 액티비티가 더 이상 사용되지 않으면 그것의 onStop() 이 호출됩니다.
7. PHP MySql 설치 등.. https://yoo-hyeok.tistory.com/16?category=708422
'개발자 넋두리 > 안드로이드앱' 카테고리의 다른 글
[될 때까지 안드로이드] 기초 다지기4(화면 변경, 인텐트 사용법) (0) | 2019.11.09 |
---|---|
[될 때까지 안드로이드] 기초 다지기2(View 정렬방법) (0) | 2019.11.09 |
[될 때까지 안드로이드] 기초 다지기1(주요 속성 TextView, layout_weight 등) (0) | 2019.11.09 |
앱개발 tip2. (0) | 2019.05.11 |