53 8. 인텐트와 필터 (intent and filter)
안드로이드에서의 인텐트는 어떤 작업이 수행되어야 하는 지를 추성적으로 명기하는 데 사용된다. Activity 를 화면에 띄우기 위한 startActivity()에 사용되기도 하고 브로드캐스팅하는 목적으로 사용되기도 하고, 백그라운드 서비스를 시작하는 데 사용되기도 한다.
예를 들면 이메일을 보내는 서비스를 생각해보면, 이메일 보내는 서비스를 수행하라는 인텐트를 시스템에 보냄에 의해 이메일 서비스를 시작할 수 있다. 아래는 이메일 서비스에 대한 인텐트 사용 예이다.
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
email.putExtra(Intent.EXTRA_EMAIL, recipients);
email.putExtra(Intent.EXTRA_SUBJECT, subject.getText().toString());
email.putExtra(Intent.EXTRA_TEXT, body.getText().toString());
startActivity(Intent.createChooser(email, "Choose an email client from..."));
위와 같은 명령어를 실행하게 되면 다음의 화면이 띄워진다.
이메일 앱이 스마트폰에 지정되지 않은 경우에는 다음과 같은 내용이 뜬다.
다음은 웹 검색에 대한 인텐트 사용예이다.
String q = "Android App Programming";
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, q);
startActivity(intent);
위와 같은 명령어를 실행하게 되면 다음의 화면이 나타날 것이다.
54
인텐트는 새로운 화면을 띄우거나 또는 백그라운드 작업 명령, 또는 브로드캐스트 메시지 발송에 사용되며 이를 수행하기 위한 메소드는 아래와 같다.
메소드 설명
startActivity() 새로운 액티비티 화면을 띄움 startService() 서비스를 실행시킴
sendBroadcast() 브로드캐스트 메시지 생성 및 발송
인텐트의 구성
인텐트는 Action 과 Data 로 구성된다.
Action: 인텐트를 통해 시작할 작업을 지정한다.
Data: 작업의 매개변수를 의미한다. 매개변수는 자료형, URI 등의 작업에 필요한 매개변수들이 포함된다.
55
다음은 안드로이드에서 필요한 Action 의 목록이다.
Intent 설명
ACTION_ALL_APPS 기기에 있는 모든 앱들을 보여준다.
ACTION_ANSWER 수신 통화를 다룬다.
ACTION_ATTACH_DATA 첨부 파일을 다룬다.
ACTION_BATTERY_CHANGED 배터리 잔여 용량이 변화했을 때 브로드캐스트 메시지를 보낸다.
ACTION_BATTERY_LOW 배터리 잔여 용량이 얼마 남지 않았을 때 브로드캐스트 메시지를 보낸다..
ACTION_BATTERY_OKAY 배터리 잔여 용량이 정상수준으로 회복되었을 때 브로드캐스트 메시지를 보낸다.
ACTION_BOOT_COMPLETED 시스템이 부팅을 완료 했을 때 브로드캐스트 메시지를 보낸다.
ACTION_BUG_REPORT 버그 리포트 화면을 띄운다.
ACTION_CALL Data 에 지정된 사람에게 전화를 한다.
ACTION_CALL_BUTTON 통화 버튼을 누르는 것과 같은 작업을 한다.
ACTION_CAMERA_BUTTON 카메라 버튼을 누르는 것과 같은 작업을 한다.
ACTION_CHOOSER 선택화면을 보여준다.
ACTION_CONFIGURATION_CHANGED 기기의 설정 (위치, 방향)이 바뀌었음을 알리도록 한다.
ACTION_DATE_CHANGED 날짜가 바뀜을 알려준다.
ACTION_DEFAULT 주어진 Data 에 대해 디폴트 작업을 한다.
ACTION_DELETE 주어진 Data 를 삭제한다.
ACTION_DEVICE_STORAGE_LOW 메모리 용량이 얼마 남지 않았음을 알린다.
56
ACTION_DEVICE_STORAGE_OK 메모리 용량이 회복되었음을 알린다.
ACTION_DIAL Data 에 지정된 번호로 전화를 건다.
ACTION_DOCK_EVENT 도킹 상태의 변화를 알린다.
ACTION_DREAMING_STARTED 시스템이 잠자기 상태임을 알린다.
ACTION_DREAMING_STOPPED 시스템이 잠자기 상태를 멈추었음을 알린다.
ACTION_EDIT 주어진 Data 를 편집하는 작업을 제공한다.
ACTION_FACTORY_TEST 공장 테스팅 화면에 진입한다.
ACTION_GET_CONTENT 사용자가 특정 항목의 데이터에 접근하도록 한다.
ACTION_GTALK_SERVICE_CONNECTED GTalk 연결이 되었음을 알린다.
ACTION_GTALK_SERVICE_DISCONNECTED A GTalk 연결이 해지되었음을 알린다.
ACTION_HEADSET_PLUG 유선 헤드셋이 연결/연결해지 되었음을 알린다.
ACTION_INPUT_METHOD_CHANGED 입력 방식이 변했음을 알린다.
ACTION_INSERT 아이템을 저장소에 삽입한다.
ACTION_INSERT_OR_EDIT 아이템을 새로 작성하거나 기존 아이템을 편집한다.
ACTION_INSTALL_PACKAGE 인스톨러를 띄운다.
ACTION_LOCALE_CHANGED 현 기기의 로케일이 바뀐다.
ACTION_MAIN 메인 화면으로 진입한다.
ACTION_MEDIA_BUTTON 미디어 버튼을 누른 효과를 만든다.
ACTION_MEDIA_CHECKING 외부 미디어가 연결되어 있으며 이를 체크하고 있음.
ACTION_MEDIA_EJECT 연결된 외부 저장장치를 제가하기를 원함.
ACTION_MEDIA_REMOVED 외부 미디어가 제거됨.
57
ACTION_NEW_OUTGOING_CALL 새로운 통화를 요청함.
ACTION_PASTE 새로운 아이템을 생성하는 데 그 데이터는 클립보드에서 가져옴.
ACTION_POWER_CONNECTED 전원이 연결됨.
ACTION_REBOOT 기기가 재부팅됨.
ACTION_RUN 데이터를 실행함.
ACTION_SCREEN_OFF 화면이 꺼짐
ACTION_SCREEN_ON 화면이 켜짐
ACTION_SEARCH 검색 작업을 수행함.
ACTION_SEND 데이터를 어딘가로 보냄.
ACTION_SENDTO 메시지를 지정된 사람에게 보냄.
ACTION_SEND_MULTIPLE 복수의 데이터를 보냄.
ACTION_SET_WALLPAPER 배경화면을 선택하는 행동을 함.
ACTION_SHUTDOWN 기기가 종료됨.
ACTION_SYNC 데이터 동기화 실행됨.
ACTION_TIMEZONE_CHANGED 타임존이 바뀜.
ACTION_TIME_CHANGED 시스템 시간이 바뀜
ACTION_VIEW 데이터를 사용자에게 보여줌.
ACTION_VOICE_COMMAND 음성으로 명령어를 실행함.
ACTION_WALLPAPER_CHANGED 배경화면이 바뀜.
ACTION_WEB_SEARCH 웹 검색을 수행함.
58
데이터인텐트는 Action 과 data 로 구성된다. Data 는 자료형, URI 등이 있으며 action 과 같이 인텐트를 구성한다. 다음 표는 action 과 data 의 쌍으로 표현된 intent 의 예를 나타낸다.
Action Data 설명
ACTION_VIEW
content://contacts/people/1 연락처의 1 번 사람의 정보를 나타내라.
ACTION_DIAL
content://contacts/people/1 연락처의 1 번 사람에게 전화를 걸어라 ACTION_VIEW tel:123 전화걸기 화면을 나타내는데 전화번호는
123 으로 채워라.
ACTION_EDIT
content://contacts/people/1 연락처 1 번의 편집화면을 나타내어라.
ACTION_VIEW
content://contacts/people 연락처 리스트를 화면에 나타내어라
인텐트의 종류
인텐트는 명시적/암묵적인 인텐트의 두 가지 종류가 있다. 명시적 인텐트는 어떤 서비스 또는 액티비티가 인텐트로 실행되어야 하는 지를 지정하는 인텐트이다.
Intent intent = new Intent(MyActivity.this, NewActivity.class);
startActivity(intent);
위의 예에서 보이듯이 Intent 객체의 인스턴스 intent 는 NewActivity 클래스를 호출하는 것을 알 수 있다.
암묵적 인텐트의 경우 특정 서비스 또는 액티비티를 직접 지정하지는 않으며 대신에 인텐트에 의해 실행될 작업들의 특성을 지정하여 시스템이 그 특성에 맞는 액티비티 또는 서비스를 실행하도록 한다. 다음은 암묵적 인텐트의 예이다.
Intent intent = new Intent();
Intent.setAction(android.content.Intent.ACTION_VIEW);
Intent.setData(ContactsContact.contacts.CONTENT_URI);
startActivity(intent);
위의 예에서 보이듯이 이 인텐트는 직접 어떤 클래스가 실행되어야 하는 지를 지정하지 않는다. 대신 ACTION 과 DATA 를 지정하여 시스템이 이에 맞는 요소들을 찾아 실행하도록 되어 있다. 이 방법은 주로 다른 앱의 요소들을 실행시킬 때 사용된다. 같은 앱의 다른 액티비티나 서비스를 실행시킬 때에는 해당 액티비티나 서비스를 수행하는 클래스를 호출하는 명시적 방법을 사용한다.
59
추가 데이터인텐트를 구성할 때에는 ACTION 과 DATA 외에도 별도의 추가 정보들이 필요한 경우가 있다.
이런 경우에는 Intent 객체의 putExtras() 메소드를 사용하며 추가 정보들을 읽으려고 할 경우에는 getExtras() 메소드를 사용한다.
인텐트 필터
인텐트는 다른 액티비티를 띄우기 위해서 또는 다른 서비스 클래스를 실행시키기 위해서 사용한다. 안드로이드 OS 는 인텐트를 어떤 액티비티에서 발생시켰을 경우 이 인텐트에 적합한 액티비티나 또는 서비스를 실행시키게 된다. 만약 직접 작성한 액티비티가 특정 인텐트에 반응하여 실행되도록 하며면 <intent-fileter> 를 통해 그 인텐트를 정하도록 한다. 다음은 intent-filter 의 예이다.
<activity android:name=".Main2Activity">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<action android:name="com.course.thirdapp.Main2Activity" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
위는 매니패스트 파일의 일부로서 Main2Activity 클래스는 android.intent.action.View 또는 com.course.thirdapp.Main2Activity 라는 인텐트에 의해 실행된다고 정의한 부분을 보여준다. <data>는 액티비티가 호출되기 위해 필요한 자료형을 정의하는 것으로 위의 예에서는 http:// 로 시작하는 자료가 액티비티의 호출에 필요하다는 것을 보여준다.
<intent-filter>에는 최소 하나 이상의 <action>이 정의되어 있어야 하며 그렇지 않다면 어떤 인텐트에도 앱이 반응하지 않을 것이다. <category>는 없어도 상관없으나 없을 경우 인텐트의 <category>에 상관없이 반응할 것이며 여러 개의 <category>가 정의되어 있을 경우 정의된 모든 <category>가 일치하는 경우에만 액티비티가 반응할 것이다. <data>는 URI 나 자료형 (예를 들면 MIMI 미디어 형)과 같은 내용을 정의할 수 있다. <data>에 무언가가 정의되어 있다면 여기에 정의된 자료형이 일치하는 intent 만이 액티비티를 호출할 수 있다.
예제) 인텐트 실행 앱
1) 새 프로젝트를 생성한다. 세팅은 늘 하던대로 한다. 단 이번 예제는 가능하다면 직접 스마트 폰을 연결하여 진행하도록 한다.
60
2) MainActivity.java 파일을 변경하여 새 개의 버튼을 추가하며 각 버튼에 대하여 event listener 를 다음과 같이 추가한다. 버튼 하나의 이름은 ‘웹서치’ 다른 하나는
‘전화연결’, 나머지는 ‘다른 화면 이동’로 한다. 이를 위해 string.xml, activity_main.xml 도 같이 변경한다.
String.xml 파일을 변경한다. 다음은 string.xml 파일의 내용이다.
<resources>
<string name="app_name">ThirdApp</string>
<string name='button1'>웹 검색</string>
<string name='button2'>전화연결</string>
<string name='button3'>화면 전환</string>
</resources>
레이아웃 디자이너를 통해 화면 UI 를 구성한다. 화면에는 3 개의 버튼을 놓고 차례로
‘웹검색’, ‘전화연결’, ‘화면 전환’으로 버튼의 텍스트를 선택한다. 다음은 레이아웃 디자이너를 통해 만들어진 activity_main.xml 파일이다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="108dp"
android:text="Hello World!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="70dp"
android:text="@string/button1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
61
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="67dp"
android:text="@string/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java 에 새로 만들어진 버튼의 클릭을 처리할 수 있는 루틴을 만들어준다. 루틴은 onCreate() 안에 만들어 준다. 해당 코드는 다음과 같다.
public class MainActivity extends AppCompatActivity { Button b1, b2, b3;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1 = (Button)findViewById(R.id.button);
b2 = (Button)findViewById(R.id.button2);
b3 = (Button)findViewById(R.id.button3);
b1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(intent);
} });
b2.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:01022603833"));
startActivity(intent);
} });
62
b3.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent("com.course.thirdapp.LAUNCH", Uri.parse("http://www.dongguk.edu"));
startActivity(intent);
} });
} }
3) 새로운 액티비티 파일을 생성한다. 새로운 액티비티는 첫번째와 세번째 버튼을 클릭했을 때 화면에 나타나는 역할을 한다.
다음은 새 액티비티 코드이다.
public class Main2Activity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TextView myText = (TextView)findViewById(R.id.textView2);
Uri uri = getIntent().getData();
myText.setText(uri.toString() + " is accepted.");
} }
다음은 새 액티비티의 activity xml 파일이다. 이 액티비티는 인텐트를 받아 인텐트를 받았다는 메시지를 화면에 보여주는 역할을 한다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Main2Activity">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="147dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
63
4) 새로운 액티비티 파일에 맞추어 매니페스트 파일을 수정한다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.course.thirdapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.course.thirdapp.Main2Activity">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<action android:name="com.course.thirdapp.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
5) 앱을 실행한다.