- 인플레이션
- XML 레이아웃에 정의된 내용이 메모리에 객체화되는 과정
- setContentView() 함수가 내부적으로 인플레이션 작업 실행
- 인플레이션 작업 하기 전에 xml 파일에 접근하면 널 포인트 에러 발생
- 전체 화면 중 일부분만 차지하는 화면 구성요소들을 XML레이아웃에서 로딩
- getSystemService(Context.LAYOUT_INFLATER_SERVICE)
- LayoutInflater라는 클래스 제공하며, 이 클래스는 시스템 서비스로 제공된다.
- LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.sub1, container, true);
- 액티비티 생명주기
- 실행(Running): 화면 상에 액티비타가 보이면서 실행되어 있는 상태, 액티비티 스택의 최상위에 있으며 포커스를 가지고 있음
- 일시 중지(Paused): 사용자에게 보이기는 하지만 다른 액티비티가 위에 있어 포커스를 받지 못하는 상태, 대화상자가 위에 있어 일부가 가려져 있는 경우에 해당
- 중지(Stopped): 다른 액티비티에 의해 완전히 가려져 보이지 않는 상태
- 생명주기를 활용한 데이터 저장
- onCreate -> onStart -> onResume -> onPuase -> onStop -> onDestroy
- onPause 에서 데이터 저장 후 onResume에서 데이터 복구
- onPuase
- SharedPreferences pref = getSharedPreference("pref", Activity.MODE_PRIVATE);
- SharedPreferences.Editor editor = pref.edit();
- editor.putString("name", "davidyoon");
- editor.commit();
- onResumse
- SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
- if ( pref != null) { String name = pref.getString("name"); }
- 서비스
서비스는 화면이 없는 상태에서 백그라운드로 실행됨
서비스는 프로세스가 종료되어도 시스템에서 자동으로 재시작함
서비스 생명주기
- onCreate -> onDestroy
- startService()
액티비티에서 서비스로 데이터 전달
- Intent intent = new Intent(getApplicationContext(), MyService.class);
- intent.putExtra("command", "show");
- startService(intent);
onCreate 는 한 번 만들어 지고 새로 만들어지지 않는다.
- 결국 데이터 처리는 onCreate가 아닌 onStartComamnd(Intent intent, int flags, int startId) 에서 처리
- if ( intent == null) { return Service.START_STICKY }
- START_STICKY : 서비스가 종료되었을 떄에도 다시 시작해 달라는 의미
Service 에서 Activity로 데이터 전달
- Intent showIntent = new Intent(getApplicationContext(), MainActivity.class);
- showIntent.addFlags(Intent.FlAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP);
- showIntent.putExtra("command", "show");
- showIntent.putExtra("name", name + " from service.");
- startActivity(showIntent);
Activity 에서 데이터 받기
- onNewIntent(Intent intent) 사용
- processComamnd(intent);
- onCreate()에서도 처리
- Intent passedIntent = getIntent()
- processCommand(passedIntent);
- processCommand(Intent intent)
- if(intent != null) { String command = intent.getStringExtra("command"); String name = intent.getStringExtra("name"); }
- onNewIntent(Intent intent) 사용
- BroadCast Receiver
- 어플리케이션이 글로벌 이벤트(Global Event)를 받아서 처리하려면 브로드캐스트 수신자로 등록
- 글로벌 이벤트란 전화, 문자 메시지 와 같이 안드로이드 시스템 전체에 보내지는 메시지다
- 브로드 캐스트 수신자는 인텐트필터를 포함하며, 매니페스트 파일에 등록함으로써 인텐트를 받을 준비를 한다
- 수신자가 매니페스트 파일에 등록되었다면 따로 시작시키지 않아도 된다
- 어플리케이션 컨텍스트 클래스의 registerReceiver 메소드를 이용하면 런터임 시에도 수신자를 등록할 수 있다
- 서비스처럼 브로드캐스트 수신자도 UI가 없다
- 인텐트와 브로드캐스트
- 인텐트를 이용하여 액티비트를 실행하며 포그라운드(foreground)로 실행되어 사용자에게 보여지지만
- 브로드캐스트를 이용해서 처리하면 백그라운드(background)로 동작하므로 사용자가 모름
- 인텐트를 받으면 onReceive() 메소드가 자동으로 호출된다
- 브로드캐스트의 구분
- 브로드캐스트는 크게 두 가지 클래스로 구분된다
- 일반 브로드캐스트(sendBroadcase() 메소드로 호출): 비동기적으로 실행되며 모든 수신자는 순서없이 실행된다 (때로는 동시에 실행됨) 효율적이나, 한 수신자의 처리 결과를 다른 수신자가 이용할 수 없고 중간에 취소가 불가능
- 순차 브로드캐스트(sendOrderedBroadcase() 메소드로 호출): 한 번에 하나의 수신자에만 전달되므로 순서대로 실행됨. 중간에 취소하면 그 다음 수신자는 받지 못함. 수신자가 실행되는 순서는 인텐트필터의 속성으로 정할 수 있음. 순서가 같으면 임의로 실행된다
- 브로드캐스트는 크게 두 가지 클래스로 구분된다
- SMS Receiver
- BroadcastReceiver 상속 받는 Receiver 생성
- onReceive() 메소드에서 intent 처리
- Bundle bundle = intent.getExtras();
- Object[] objs = (Object[]) bundle.get("pdus"); // SMS 표준 프로토콜 puds로 번들에서 object형태로 꺼내 사용
- SmsMessage[] messages = new SmsMessage[objs.length]; //SmsMessage 객체에 object 넣어서 메시지 파싱
- 마시멜로 이상 버전은 format 설정
- String format = bundle.getString("format");
- message[i] = SmsMessage.createFromPdu((byte[])objs[i], format);
- 액티비티에 intent 전송 (화면이 없는 Receiver에서 화면으로)
- sendToActivity(context, sender, contents, date)
- Intent intent = new Intent(context, SmsActivity.class);
- 데이터 put
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP ); // 화면없는 곳에서 activity로 데이터 보낼때 셋팅
- intent.putExtra("sender", sender);
- Date to String foramt
- private static SimpleDateForamt format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
- intent.putExtra("receivedDate", format.format(date));
- context.startActivity(intent);
- SmsActivity
- onCreate()
- Intent passedIntent = getIntent(); //getIntent로 받아서 처리
- processCommand(passedIntent);
- private void processCommand(Intent intent){ if (intent != null) { String sender = intent.getStringExtra("sender); } }
- 실행한 Activity가 foreground 상태에서 Intent에 Extra 값을 추가하고 StartActivity를 호출하면 onCreate() 대신 onNewIntent(Intent intent)가 시랳ㅇ 되고 그 다음 onResume()이 호출된다.
- 따라서 SmsActivity에서도 onNewIntent() 오버라이딩 해주어야 한다.
- onNewIntent(Intent intent){ processCommand(intent); }
- Activity Flags
- 안드로이드 Activity는 Stack 형태로 쌓이게 된다.
- startActiviy로 activity를 호출할 때 FLAG 셋팅으로 Activity 스택을 제어할 필요하 있다.
- FlAG 종류
- Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT: 시스템에 의해 스택 관리되며 가장 기본 값이다.
- Intent.FLAG_ACTIVITY_NEW_TASK: 새로운 테스크 생성, 기존에 열어놓은게 없으면 새로운 테스크 생성, 기존에 열어놓은게 있으면 그 테스트로 들어감.
- Intent.FLAG_ACTIVITY_CLEAR_TOP: 상위 스택 제거, 실행하는 액티비티가 존재하면 새로 시작하지 않고 상위에 액티비티 모두 제거
- Intent.FLAG_ACTIVITY_SINGLE_TOP: 액티비티가 이미 최상단에 있으면 다시 시작하지 않고 재사용, [ABCDE]가 있고, E에서 다시 E를 열면 onPuase() -> onNewIntent() -> onResume()
- Intent.FLAG_ACTIVITY_CLEAR_TASK // 실행 액티비티 외 모두 제거
- Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS // 최근 목록에서 제외.
- Intent.FLAG_ACTIVITY_FORWARD_RESULT // result를 상위로 보냄. startActivityForResult()에서 사용.
- Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP // onActivityResult()로 결과를 전달할 때 이전 액티비티로 돌아가도록 하기 위해 추가.
- Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT // 멀티 윈도우 시 사용.
- Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY // 시스템에 의해 설정됨. 최근 목록에서 실행되면 자동으로 붙음.
- Intent.FLAG_ACTIVITY_MULTIPLE_TASK // FLAG_ACTIVITY_NEW_TASK와 함께 사용시 새 태스크 생성
- Intent.FLAG_ACTIVITY_NEW_DOCUMENT // concurrent document 동시 문서에서 사용
- Intent.FLAG_ACTIVITY_NO_ANIMATION // 액티비티 전환시 애니메이션 무시
- Intent.FLAG_ACTIVITY_NO_HISTORY // 액티비티를 스택에 존재X (로딩화면 등)
- Intent.FLAG_ACTIVITY_NO_USER_ACTION // onUserLeaveHint() 실행을 차단
- Intent.FLAG_ACTIVITY_REORDER_TO_FRONT // 실행하는 액티비티를 최상위로 올려줌
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED // 정리할 액티비티가 있으면 태스크를 리셋
- Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET // 리셋하면 상위 태스크 모두 삭제
- Intent.FLAG_ACTIVITY_TASK_ON_HOME // FLAG_ACTIVITY_NEW_TASK와 함께 사용. 현재 홈 태스크 위에 위치.
- Intent.FLAG_ACTIVITY_MATCH_EXTERNAL // 전체 앱이 intent를 처리할 수 없을 때
- Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS // 최근 목록에서 재실행할 수 있도록 유지.
- Intent.FLAG_DEBUG_LOG_RESOLUTION // 디버깅 정보를 로그로 출력.
- Intent.FLAG_INCLUDE_STOPPED_PACKAGES // stopped된 application도 target이 됨.
- Intent.FLAG_EXCLUDE_STOPPED_PACKAGES // stopped된 application은 target이 되지 않음.
- Intent.FLAG_FROM_BACKGROUND // 백그라운드 동작중을 알려줌.
- Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION // URI 지속 권한
- Intent.FLAG_GRANT_PREFIX_URI_PERMISSION // URI prefix match 권한.
- Intent.FLAG_GRANT_READ_URI_PERMISSION // URI 읽기 권한.
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION // URI 쓰기 권한.
- Intent.FLAG_RECEIVER_FOREGROUND // 포그라운드로 변경
- Intent.FLAG_RECEIVER_NO_ABORT // 리시버가 브로드캐스트를 중지 못함.
- Intent.FLAG_RECEIVER_REGISTERED_ONLY // 동적 리시버만 브로드캐스트 받음.
- Intent.FLAG_RECEIVER_REPLACE_PENDING // 중복된 브로드캐스트를 제거.
- Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS // 브로드캐스트가 instant app의 수신자에게 표시.
- 일반 권한과 위험 권한 (마시멜로 API 23 부터)
- 설치시 권한 설정 했는데 유저들이 모두 OK 누르는 형태에서 문제 발생하여 23이상부터 변경
- 위험 권한은 실행 시 권한 부여
- 위험 권한
- 위치
- 카메라
- 마이크
- 연락처
- 전화
- 문자
- 일정
- 센서
- 퍼미션 체크
- int permissionCheck = ContextCompact.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS);
- if (permissionCheck == PackageManger.PERMISSION_GRADNTED)
- 퍼미션 거절
- if (ActivityCompat.shouldShowRequestPermisionRationale(this, Manifest.permission.RECEIVE_SMS))
- 퍼미션 요청 창 띄우기
- ActivityCompact.requestPermssions(this, new String[] {Manifest.permission.RECEIVE_SMS}, 1);
- 퍼미션 요청 결과 콜백 함수
- onRequestPermissionResult(requestCode, permissions, gratResults)
- switch (requestCode) { case 1: if (grantResults.length > 0) { if ( grantResults[0] == PackageManager.PERMISSION_GRANTED) { //토스트 메시지 승인 } } }
- 다양한 위젯과 이벤트 활용
- 대표적 이벤트
- 터치: 화면을 손가락으로 누를 떄 발생
- 키: 키패드나 하드웨어 버튼을 누를 떄 발생
- 제스처: 터치 이벤트 중에서 일정 패턴을 만들어 내는 이벤트
- 포커스: 뷰마다 순서대로 주어지는 포커스
- 화면 방향 변경: 화면의 방향이 가로/세로로 바뀜에 따라 발생하는 이벤트
- 제스처를 통해 처리할 수 있는 이벤트
- onDown(): 화면이 눌렸을 경우
- onShowPress(): 화면이 눌렸다 뗴어지는 경우
- onSingleTapUp(): 화면이 한 손가락으로 눌렸다 뗴어지는 경우
- onSingleTapConfirmed(): 화면이 한 손가락으로 눌려지는 경우
- onDoubleTap(): 화면이 두 손가락으로 눌려지는 경우
- onDoubleTapEvent(): 화면이 두 손가락으로 눌려진 상태에서 뗴거나 이동하는 등 세부적인 액션을 취하는 경우
- onScroll(): 화면이 눌린 채 일정힌 속도와 방향으로 움직였다 떼는 경우
- onFling(): 화면이 눌린 채 가속도를 붙여 손가락을 움직였다 떼는 경우
- onLongPress(): 화면을 손가락으로 오래 누르는 경우
- 가로 세로 전환
- res/layout-land 폴더 생성 후 activity_main.xml 복사 해서 붙여넣기
- 2 개의 액티비티를 가로 세로에 따라서 새로 띄우고 꺼지고 반복 된다.
- onSaveInstanceState() 함수 오버라이딩 해서 저장된 값을 불러와서 사용 가능.
- 동일한 PlainText(EditView)에는 자동으로 값 저장되게 최신버전의 안드로이드는 변경 되었다.
- 한 액티비티에서 가로 세로 전환
- onConfigurationChanged() 함수 오버라이드
- 상태가 변할 때 마다 호출되는 함수
- newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE 등으로 조건문 붙여서 처리 가능.