[Component] - AndroidManifest.xml(목차)의 <application.> 태그안에 반드시 등록해야만 사용할 수 있는 주요 클래스들
화면 담당 클래스
디바이스의 특정 상태/ 시그널[문자수신, 배터리부족, 부팅완료, gps 상태정보 등등..]를 OS 에서 방송해주면 이를 수신할 때 사용
백그라운드(앱은 실행 중- 화면에서 안보이는)에서 코드를 동작하게 하고 싶을 때 사용. [ex. 뮤직플레이어 앱]
다른앱에게 나의 DB 정보를 제공할 때 사용 [ex. 사진앱 or 연락처앱 ]
기본적으로 앱은 샌드박싱기술로 되어있어서 다른 앱이 접근 불가능 근데 내 데이터베이스를 다른앱이 쓰게하고 싶을때(남이 접근하는게 아니고 내가 열어주는것!) Contents Provider 통해 열어줌
가져다 쓸때 Contents Resolver를 통해 가져옴
핸드폰은 하나의 스크린안에 하나의 창만 보여주도록 막아둠 한번에 하나의 화면만 보여주자고 약속
java폴더에 new java class 생성 & 호환성을 가진 AppCompatActivity 를 상속
액티비티가 보여줄 view를 설정하기 위해 자동으로 실행되는 콜백메소드 protected void onCreate()
secondActivity용 레이아웃(xml) 생성
Activity는 4대 컴포넌트중 하나이기 때문에 AndroidManifest에 등록해줘야함!!
💡 android:exported="true"
안쓰면 에러, 안드로이드(운영체제)는 화면 단위로 앱이라고 생각함 앱을 시작점을 거쳐가기 싫어해서 단위단위로 본다(화면끼리 서로 참조할 수 없다) -> 이것이 메인함수가 없는 이유
외부에서 직접 이 화면을 부를것인지 아닌건지 선택하는 부분
Main.java
package com.bsj0420.ex42activity;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button goBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
goBtn = findViewById(R.id.go_btn);
goBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//두번째 화면(SecondActivity)으로 이동
//SecondActivity를 실핼시켜줄 택배기사 객체 생성
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
//Intent(보내는 사람-context, 받는사람-설계도면 );
//택배기사를 통해 새로운 액티비티 실행
startActivity(intent);
//현재 액티비티를 종료
finish();
}
});
}
}
앱의 화면은 다른 화면이 열리면 알아서 꺼지는 것이 아니고 현재 화면을 덮고 그 위에 화면이 겹쳐져서 나온다
가려진 화면은 백스택(stack)으로 이동
때문에 현재화면을 다른 화면을 열때 현재 화면을 백스택으로 넣지 않으려면 finish(); 를 쓴다
💡 Stack & queue
stack : FILO
queue : FIFO ex) 키보드
익명 클래스의 축약표현
리스너 안의 메소드가 한개일때만 쓸 수 있음
🔨 람다식 표기법
thirdBtn.setOnClickListener( view -> {
할 행동
} );
(매개변수 -> {할 행동});
thirdBtn = findViewById(R.id.third_btn);
thirdBtn.setOnClickListener( view -> {
//서드액티비티를 실행시켜줄 택배기사 객체 생성
Intent intent = new Intent(this, ThirdActivity.class);
//람다식으로인해 익명클래스가 사라져서 그냥 this써도 됨!!
startActivity(intent);
} ); //리스너 안의 메소드가 한개일때만 쓸 수 있음
package com.bsj0420.ex42activity;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button goBtn;
Button thirdBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//클릭 리스너 짧게 줄여보기
thirdBtn = findViewById(R.id.third_btn);
thirdBtn.setOnClickListener( view -> {
//서드액티비티를 실행시켜줄 택배기사 객체 생성
Intent intent = new Intent(this, ThirdActivity.class);
//람다식으로인해 익명클래스가 사라져서 그냥 this써도 됨!!
startActivity(intent);
} ); //리스너 안의 메소드가 한개일때만 쓸 수 있음
}
}
package com.bsj0420.ex42activity;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class ThirdActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
//나도 화면전환시 제목줄 글씨도 내거 보여주기
getSupportActionBar().setTitle("세번째 화면");
//1. 제목 왼쪽에 돌아가는 버튼(업버튼) 보이도록
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//2. 보이도록했지만 움직이지 않음 -> 움직이게 만들기
}
//3. [업버튼]이 클릭됐을 때 자동으로 발동하는 콜백메소드
@Override
public boolean onSupportNavigateUp() {
super.onBackPressed(); //4. 핸드폰 뒤로가기 버튼 능력 상속
return super.onSupportNavigateUp();
}
}
A화면에서 B화면로 데이터 가져다줘 할때 (A -> B)
package com.bsj0420.ex43activity2;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
EditText etName, etAge;
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etName = findViewById(R.id.et_name);
etAge = findViewById(R.id.et_age);
btn = findViewById(R.id.btn);
btn.setOnClickListener(view -> {
//세컨드 액티비티로 보낼 데이터
String name = etName.getText().toString();
int age = Integer.parseInt(etAge.getText().toString());
//새러운 액티비티를 실행 시켜줄 택배기사님 생성
Intent intent = new Intent(this, SecondActivity.class);
//새로운 액티비티에 보낼 데이터를 택배기사(intent)한테 넣기
intent.putExtra("name",name); // .putExtra("이름표/식별자",값 들어간 변수);
intent.putExtra("age",age); // .putExtra("이름표",값 들어간 변수);
startActivity(intent);
});
}
}
package com.bsj0420.ex43activity2;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
public class SecondActivity extends AppCompatActivity {
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//이 액티비티를 실행시켜준 Intent(택배기사) 소환
Intent intent = getIntent();
//택배기사를 통해 전달된 Extra 데이터 있으면 받기
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age",0); // defaltValue : 혹시 값으면 써라
//defaltValue 는 기본형 자료형을 없어올때 쓰라고 나옴 , 참조형은 null값으로 알아서 오기때문에 쓸 필요 없음
//받은 데이터 확인
//제목줄에 확인해보기
getSupportActionBar().setTitle(name);
//TextView에 확이해보기
tv = findViewById(R.id.tv);
tv.setText(age + "");
}
}
B화면에서 A화면의 데이터 갖다주세요 할때 (B ->A ->B)
(ex. 사진 등록)
.startActivityForResult() 였는데 변경됨 intent가 어디서 갔다왔는지 확인이 불편해서 바뀜
메인액티비티가 전부처리하기 싫어서 하청업체 만듦 : ActivityResultLauncher
두번째 화면 글자를 첫번째 화면으로 가져오기
1. 버튼 클릭 안에서 결과를 받기위한 secontActivity을 띄울 intent 객체 생성
2. 멤버변수로 ActivityResultLauncher<Intent'> 만들기
매개변수 2개
1. 어떤 계약 객체를 만들건지 (현재한 계약은ActivityResultContracts.StartActivityForResult( ))
2. 갔다가 돌아왔을 때 자동으로 실행되는 메소드
(new ActivityResultCallback<ActivityResult'>( ))
위 3번까지의 코드
package com.bsj0420.ex44activitystartactivityforresult;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
tv = findViewById(R.id.tv);
btn.setOnClickListener(view -> {
//1.결과를 받기위해 secontActivity실행
Intent intent = new Intent(this, SecondActivity.class);
//3.만든 대행사에게 intent 보내기
resultLauncher.launch(intent);
});
}
//2.
// 결과를 받기위한 액티비티를 대신 실행시켜 주기위한 대행사(하청업체) 객체 생성 및 등록
// 꼭 멤버변수로 만들어야함 (지역변수로 생성 x)
ActivityResultLauncher<Intent> resultLauncher
= registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
//혹시 실행시켰던 액티비티에서 [뒤로가기 버튼]으로 취소했을 수도 있어서 if문으로 예외상황 막아둠
if(result.getResultCode() == RESULT_OK) {
//4. 돌아온 인텐트 객체 소환
} else if (result.getResultCode() == RESULT_CANCELED) {
Toast.makeText(MainActivity.this, "취소 했습니다", Toast.LENGTH_SHORT).show();
}
}
});
}
1. EditText에 입력한 데이터들을 결과값으로 설정
2. 다시 돌아갈 택배기사(intent)에게 결과 데이터를 넣기위해
intent 소환 : getIntent()
3. 인텐트한테 값 줌
.putExtra() 를 통해
4. 값을 제대로 전달해서 간다는 뜻의 시그널을 줌
RESULT_OK 라고 말해줌! (if문에 쓴 시그널 맞추기)
5. 현재 화면을 꺼주기 : finish();
버튼을 눌렀다고 화면이 꺼지지 않으니 내가 꺼줘야함!
package com.bsj0420.ex44activitystartactivityforresult;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
public class SecondActivity extends AppCompatActivity {
EditText etName, etAge;
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
etName = findViewById(R.id.et_name);
etAge = findViewById(R.id.et_age);
btn = findViewById(R.id.btn);
btn.setOnClickListener(view -> {
//EditText에 입력한 데이터들을 결과로 설정
String name= etName.getText().toString();
int age = Integer.parseInt(etAge.getText().toString());
//위에 값을 결과값이라고 설정
//다시 돌아갈 택배기사(intent)에게 결과 데이터를 넣기
//즉,액티비티간의 데이터 전달은 Intent밖에 못한다!!!!!★★★★
Intent intent = getIntent();
//인텐트한테 값 줌
intent.putExtra("name", name);
intent.putExtra("age", age);
//버튼을 클릭하면 RESULT_OK 라고 말해줌! 시그널 맞추기
setResult(RESULT_OK, intent);
//버튼을 눌렀다고 화면이 꺼지지 않으니 내가 꺼줘야함!
finish();
});
}
}
RESULT_OK 일때 상황 설정을 위해 다시 main.java로 가자
if(result.getResultCode() == RESULT_OK) {}
안에서 second화면의 값 받아오기
package com.bsj0420.ex44activitystartactivityforresult;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
tv = findViewById(R.id.tv);
btn.setOnClickListener(view -> {
//1.결과를 받기위해 secontActivity실행
Intent intent = new Intent(this, SecondActivity.class);
//3.만든 대행사에게 intent 보내기
resultLauncher.launch(intent);
});
}
//2.
// 결과를 받기위한 액티비티를 대신 실행시켜 주기위한 대행사(하청업체) 객체 생성 및 등록
// 꼭 멤버변수로 만들어야함 (지역변수로 생성 x)
ActivityResultLauncher<Intent> resultLauncher
= registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
//혹시 실행시켰던 액티비티에서 [뒤로가기 버튼]으로 취소했을 수도 있어서 if문으로 예외상황 막아둠
if(result.getResultCode() == RESULT_OK) {
//4. 돌아온 인텐트 객체 소환
Intent intent = result.getData();
//intent에 넣었던 Extra 데이터 빼오기
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age",0);
//화면에 확인
tv.setText(name + " : " + age);
} else if (result.getResultCode() == RESULT_CANCELED) {
Toast.makeText(MainActivity.this, "취소 했습니다", Toast.LENGTH_SHORT).show();
}
}
});
}
인텐트를 실행시키려면 Intent intent = new Intent(this, SecondActivity.class); 매개변수에 class이름이 있어야한다
그러나 클래스이름을 모를 때 쓸수 있는 방법이 있다 이 방법을 쓰기 위해 매니페스트에 액티비티에 필터를 등록해야됨
(단, API 30버전 이상부터는 묵시적 Intent로 실행하는 엑티비티는 exported가 true여야됨)
쓰는 이유 : 앱이 다르면 명시적으로 실행하는 건 불가능
다른 앱을 쓰기 위해선 묵시적으로 불러야함
package com.bsj0420.ex45activityenumintent;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
btn.setOnClickListener(view -> {
//묵시적인텐트로 즉 SecondActivity.calss 명칭없이 실행해보기
//1. intent 생성 but 매개변수 없이
Intent intent = new Intent();
//2. 매니패스트에 등록한 액션 이름으로 찾아라
intent.setAction("aaaa");
startActivity(intent);
});
}
}
매니패스트에 필터로 액션 네임 등록 한 것은 아예 다른 앱화면에서 부를 수 있다
사용방법은 위랑 같음
package com.bsj0420.ex46activity5;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn).setOnClickListener(view -> {
Intent intent = new Intent();
intent.setAction("aaaa");
startActivity(intent);
});
}
}
공통인텐트
https://developer.android.com/guide/components/intents-common?hl=ko
package com.bsj0420.ex47activitysystemintent;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//전화걸기 화면 켜기
findViewById(R.id.btn_call).setOnClickListener(view -> {
//버튼 누르면 다이얼화면(전화앱) 실행
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
//미리 전화번호까지 전달하기
intent.setData(Uri.parse("tel:01011341245")); //tel: 키워드 꼭 써야됨
startActivity(intent);
});
findViewById(R.id.btn_sms).setOnClickListener(view -> {
//sms문자 화면(메세지 앱)
//Intent intent = new Intent();
//intent.setAction(Intent.ACTION_SENDTO);
Intent intent = new Intent(Intent.ACTION_SENDTO); //생성자로 액션 설정 가능
intent.setData(Uri.parse("smsto:01012341234,01084568456")); //번호 설정
//문자내용 프로그래밍
intent.putExtra("sms_body","안뇽~"); // sms_body 이 식별자는 정해져 있음
startActivity(intent);
});
findViewById(R.id.btn_iternet).setOnClickListener(view -> {
//웹페이지 보는 화면 - 크롬 브라우저
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.naver.com")); //액션과 데이터 한방에 쓸수 있음
startActivity(intent);
});
findViewById(R.id.btn_camera).setOnClickListener(view -> {
//카메라 앱
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="@color/black"/>
<solid android:color="@color/white"/>
<corners android:radius="4dp"/>
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="@color/black"/>
<solid android:color="#979797"/>
<corners android:radius="4dp"/>
</shape>
</item>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="@drawable/baseline_favorite_border_24"/>
<item android:state_checked="true" android:drawable="@drawable/baseline_favorite_24"/>
</selector>