본문 바로가기

IT_Story/안드로이드

Android Components-1(Activity, Service, Intent & IntentFilter, Manifest)

Android App Components -1

1. Activity

1.1 소개

  • Android 4개의 컴포넌트 중의 하나.
  • 사용자 인터페이스 화면을 의미한다.
  • UI 컴포넌트를 화면에 표시하고 시스템이나 사용자의 반응을 처리한다.
  • 하나의 어플리케션은 여러 Activity를 가질 수 있고, 어플리케이션이 실행되었을 때 가장 먼저 실행되는 Activity를 'Main Activity'라고 한다.
  • Activity의 전환으로 생기는 사항은 'Back Stack'이라는 "last in, fist out" stack mechanism이라고 한다.

    사용자가 안드로이드 어플리케이션을 끄기 위해서는 back button을 눌러 뒤로가기를 통해 activity를 종료를 한다.
  • AndroidManifest에 등록해야된다.
    <activity android:name=".view.activities.IntroActivity" android:screenOrientation="portrait"/>

1.2 Creating an Activity

  • Activity를 생성하기 위해서는 Activity클래스를 상속받아야 한다.
  • Activity LifeCycle에 따라 다양한 상태전환이 이루어지기 때문에 각 상태에 해당되는 콝백 메소드를 재정이 해줘야 한다.
  • onCreate() : UI에 관한 layout을 정의하는 setContentView()를 이 부분에서 사용해야 한다.
public class MyActivity extends Activity{
     @Override
     public void onCreate(Bundel savedInstanceState){
       super.onCreate(savedInstanceState);
       setContentViewe(R.layout.main); // main.xml 파일의 레이아웃을 이 activity에 적용
 
       //여기에 자신이 작업할 추가적인 내용을 구성한다.
    }
}

1.3 Starting an Activity

  • Activity에서 다른 Activity를 생성하려면 Intnet를 생성하고 startActivity() 메소드를 사용한다.
  • 생성될 Intent에 실행시키고자 하는 Activity의 정보를 명시해야 한다.
    • Explicit Intent
      • 동일한 어플리케이션 내에 존재하는 Activity를 호출하거나 반드시 해당 Activity를 호출해야 할 경우 Activity Class명을 사용하여 Activity를 시작한다.
      • Intent 클래스의 생성자 중에서 첫번째 인자에 Intent 객체를 생성하여 사용하는 Context를 명시, 두 번째 인자에는 사용하고자하는 Component 클래스를 명시한다.
        Intent intent = new Intent(this, NextActivity.calss);
        startActivity(intent);
    • Implicit Intent
      • 어떤 Activity가 실행될지 직접적으로 결정할 수 없을 경우(예, 이메일, Text 메시지 보내기)
      • 자신이 원하는 action을 명시하여 Activity를 실행한다.
        Intent intent = new Intent(Intent.ACTION_SEND); // Email을 보내는 행동
        intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
        startActivity(intent);

1.4 Starting an Activity for a result

  • Activity를 수행한 뒤 결과를 반환 받아야할 경우 사용한다. (예, 카메라 어플)
  • startActivity() 메소드 대신, startActivityForResult() 메소드를 사용하고 onActivityResult() 콜백 메소드를 재정의한다.
  • onCactivityResult()메소드에 전달되는 3가지 인자.
    • resultCode : startActivityForResult()의 두번째 인자와 동일하다. 여러 개의 Activity를 수행시킨 경우 이 값으로 어떤 Activity의 결과값인지 구별할 수 있다.
    • resultCode : 실행결과값이 성공으로 받았는지의 여부를 확인한다.
    • data : Activity의 구체적 실행 값이다.
      private void pickContact(){
         // Create an intent to "pick" a contact, as defined by the content provider URI
         Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
         startActivityForResult(intent, PICK_CONTACT_REQUEST);
      }
       
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data){
         // if the request went well (OK) and the request was PICK_CONTACT_REQUEST
         if(resultCode ==Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST){
             // Perform a query to the contact's content provider for the contact's name
             Cursor cursor = getContentResolver().query(data.getData(), new String[] {Contacts.DISPLAY_NAME}, null, null, null};
             if(cursor.moveToFirst()){ // Ture if the cursor is not empty
                int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
                String name = cursor.getString9columnIndex);
                // Do something with the selected contact's name...
             }
         }
      }

1.5 Activity LifeCycle

  • onCreate()
    • Activity가 생성될 때 호출되는 메소드
    • 화면 Layout을 구성하고 각정 object들을 초기화하는 단계
  • onStart()
    • Activity가 사용자에게 보여줄 준비가 되었을 때 호출됨
  • onResume()
    • Activity가 사용자에게 보여지고 사용자 입력을 처리할 수 있는 단계
  • onPause()
    • Focus를 잃고 이전의 Activity가 resume 되기 전, 데이터를 저장하고 cpu 소비하는 작업을 중단함
  • onDestory()
    • 안드로이드 시스템 내의 Activity가 존재하지 않는 단계

2. Service

2.1 소개

  • 사용자 인터페이스 화면이 아니라 Background로 실행되는 component(예, mp3)
  • startService() : service를 시작할 때 사용하는 메소드
  • bindServicee() : 어플리케이션 컴포넌트와 연결을 할 때 사용하는 메소드
  • 두가지의 Service
    • 백그라운드 작업(local Service)
      • 사용 메서드 : onStartCommend (Intent intent, int flags, int startId)
        onStartCommand() 리턴값
        startService로 service를 실행하면 Service에 onCreate(), onStart() 메소드가 호출된다.
        시스템에 의해서 재실행되는 경우 onCreate() 메소드가 호출되고 onStart()는 호출되지 않기 때문에
        Android 2.0 이후부터는 onStartCommmand()를 통해 service가 어떻게 되는지 리턴을 통해 확인한다.
        • START_STICKY : 메모리 부족이나 기타 상황에서 시스템이 강제로 service를 종료시켰을 경우, 시스템이 다시 service를 재시작해주지면 intent값이 null로 초기화시켜서 재시작한다.
        • START_NOT_STICKY : 재시작하지 않고 종료된 상태로 남게 된다. 예를 들어 매 15분마다 네트워크를 체크하는 service가 강제로 종료되었을 경우 15분 후에 자동적으로 다시 service가 실행되기에 따로 재시작을 해 줄 필요가 없다.
        • START_REDELIVER_INTENT : Intent가 다시 전달되어 재시작한다. 반드시 실행되어야하는 service일 때 해당한다.
      • 호출 메서드 : CompornetName stratService (Intent service)
      • 중지 메서드 : stopService (Intent service) 
    • 원격 호출 인터페이스
      • 사용 메서드 : onBind (Intent intent)
      • 호출 메서드 : bindService (Intent service, ServiceConnection conn, int flags)
      • 중지 메서드 : unbindService (ServiceConnection conn)
  • AndroidManifest에 등록해야된다.
    <service android:name=".controller.MusicDownloadController" android:label="@string/download_service_name"/>

2.2 Service LifeCycle

startService()를 시작하면 음악을 background 형태로 running하는 것이다.
사용자가 음악을 들으며 이전곡, 다음곡 등으로 제어를 할 때
bindService()가 호출이 되고 onUnbind()가 되면 다시 Service running 형대가 된다.

2.3 AIDL(Android Interface Definition Language)

  • Service가 실행하고 있는 process가 아닌 별개의 process에서 API를 호출하고자 할 때는 IBinder와 AIDL을 사용해야한다.
  • AIDL을 통해 IPC(InterProcess Communication)가 가능하다.
  • AIDL을 사용해서 bind 하는 방법
    • .aidl 파일 생성
    • 인터페이스 구현
    • 인터페이스에서 client 제시 : service 구현 및 onBind() 재정의
.aidl 파일 생성
// IRemoteService.adil
package com.example.android:
 
//Declare any non-default types here with import statements
 
Inteface IRemoteService{
   /**Request the process ID of this service, to do evil things with it. */
   int getPid();
    
   /** Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
   void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);
}
Interface 구현
private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
   public int getPid(){
      return Process.myPid();
   }
   public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString){
   // Does nothing
   }
}
Interface에서 client제시
public class RemoteService extends Service{
   @Override
   public void onCreate(){
      super.onCreate();
   }
    
   @Override
   public IBinder onBinder(Intent intent){
     // Return the interface
     return mBinder;
   }
 
   private final IRemoteService.Stub mBinder= new IRemoteService.Stub(){
      public int getPid(){
        return Process.myPid();
      }
      public void basicTypes(int anInt, long aLong, boolean, aBoolean, float aFloat, double aDouble, String aString){
         // Does nothing
      }
   };
}
 
 
IRemoateService mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection(){
   // Called when the connection with the service is estabilished
   public void onServiceConnected(ComponentName className, IBinder service){
      // this gets an instance of the IRemoteInterface, which we can use to call on the service
      mIRemoteService = IRemoteService.Stub.asInerface(service);
   }
 
  // Called when the connection with the service disconnects unexpectedly
  public void onServiceDisconnected(ComponentName className){
    Log.e(TAG, "Services has unexpectedly disconnected");
     mIRemoteService = null;
  }
};

2.4 Messaenger

  • AIDL 없이 IPC를 할 수 있도록 Android에서 제공해주는 MEssenger 클래스이다.
  • Messanger는 Handler 클래스를 상속받아 구현하며 Handler의 인스턴스를 가지고 있다.
    Message를 수신할 Service 쪽의 onBind()메소드
    public class MessengerService extends Service{
        Messenger mMessenger = new Messenger(new Handler(){
              @Override
              public void handleMessange(Message msg){
                    super.handleMessage(msg);
              }
       });
     
       @Override
       public IBinder onBind(Intent intent){
                return mMessenger.getBinder();
       }
    }
Service와 연결할 Client 코드
public static class MessengerClient extends Activity{
    Messenger mService = null;
    private ServiceConnection mConnection = new ServiceConnection(){
           public void onServiceConnected(ComponentName className, IBinder service){
                    mService = new Messenger(service);
           }
           public void onServiceDisconnected(ComponentName className){
                   mService = null;
           }
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
             
            bindService(new Intent(MessengerClient.this, MessengerService.class), mConenction, Context.BIND_AUTO_CREATE);
   
}

3. Intent & IntentFilter

3.1 Intent 소개

  • 어플리케이션 컴포넌트에서 다른 어플리케이션 컴포넌트를 실행시킬 때 필요한 객체
  • 어플리케이션 컴포넌트에 action, data를 전달하는 메시지 객체
  • Intent 객체가 가지고 있는 정보
    • Component name, Action, Data, Category, Extras, Flags
  • 두 가지의 Intent
    • Explicit
      • 실행할 어플리케이션 컴포넌트의 이름이 명시된 Intent
    • Implicit
      • 다른 어플리케이션의 컴포넌트를 실행할 때 사용
      • 클래스 이름 대신에 action 이름으로 명시된 Intent

3.2 Intent 객체가 가지고 있는 정보

  • Component name : 호출할 Activity, Service나 BR(Broadcast Receiver) 등의 이름을 나타낸다.
  • Action : Intent를 통해 수행할 동작을 지정하거나 특정상태를 의미한다. Intent는 *하나의 action*만 가진다.
    ConstantTarget ComponentAction
    android.intent.action.ACTION_CALLActivity전화를 건다
    android.intent.action.ACTION_EDITActivity데이터를 편집한다
    android.intent.action.ACTION_MAINActivitytask의 첫 Activity로 시작한다
    android.intent.action.ACTION_BATTERY_LOWBR베터리 수준이 낮음을 뜻한다
    android.intent.action.ACTION_SCREEN_ONBR단말기 화면이 켜졌음을 의미한다
  • Data : Intent는 대상 Component에서 처리할 Action 뿐 아니라 Data도 전달 할 수 있다. Data형태는 URI형태로 구성되며 종류에 따라 type이 다르다.
    종류형태타입의미
    URLhttp://naver.comX사이트 주소
    사진, JPEGContent://media/external/images/media/1image/jpeg이미지
    음악Content://media/external/images/audio/1audio/mp3오디오
    전화번호Tel:01028749769X전화번호
    좌표geo::37.111111-222.333333333X특정 지역 좌표
  • Category : Action과 함께 component의 특징을 나타내는 항목. Action과 다르게 Intent에 *여러개의 category*를 가질 수 있다.
    ConstantCategory
    android.intent.category.HOME홈화면을 표시한다
    android.intent.category.LAUNCHERActivity가 어플리케이션의 런처에 표시된다.
    android.intent.category.PREFERENCE환경설정을 표시한다
  • Extras : Intent를 통해 component를 호출하거나 메시지를 보내면서 URI형태가 아닌 data를 전달할 때 사용한다.
    Extras는 Bundle Object에 +Key-value pair+를 통해 저장된다.

3.3 Intent Filter 소개

  • 어플리케이션 component가 받고자 하는 Intent가 무엇인지 확인하는 수단
  • Intent Filter의 구성요소
    • action
    • data(URI, data type)
    • category
  • AndroidManifest에 등록한다.
    <activity android:name=".view.activities.HomeActivity"
              android:launchMode="standard"
              android:screenOrientataion="portrait">
       <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
    </activity>

4. AndroidManifest

4.1 소개

  • XML문서 형식의 어플리케이션 명세서
  • 안드로이드 어플리케이션의 이름, 버전, 구성요소, 권한 등을 설정할 수 있다.
    • 어플리케이션의 java package 이름을 지정
    • 어플리케이션의 components 지정
    • 어떤 프로세스가 어플리케이션의 작동을 하는지 결정
    • Permission 선언 및 정의, 어플리케이션에 요구되는 최소 API레벨 및 연결되어야하는 라이브러리 지정
      permission 
      ACCESS_FINE_LOCATIONGPS 위치 추적기능이 필요한 권한
      BLUETOOTH블루투스를 연결할 수 있는 권한
      CALL_PHONE다이얼로 전화를 걸 수 있또록 허락하는 권한
      CAMERA내장 카메라 접근 권한
      INTERNET인터넷 접속 권한
      RECEIVE_SMS문자메시지 수신 기능을 허락하는 권한
      SEND_SMS문자메시지 전송 기능을 허락하는 권한
      VIBRATE진동 기능을 허락하는 권한
AndroidManifest 예제
<?xml version="1.0" encoding="utf-8"?>
      package="com.example.helloworld" // 응용프로그램의 패키지 이름
      android:versionCode="1" // 응용프로그램의 버전 부호, 업데이트 할 때마다 버전 부호를 증가시켜야 함
      android:versionName="1.0">
 
   <uses-permission android:name="android.permission.INTERNET"/> //권한 설정요소
 
   <application android:icon="@drawable/icon"
                android:label="@string/app_name">
      <activity android:name=".HelloWorldActivity"
                android:label="@string/app_name">
           <intent-filter>
               <action android:name="android.intent.action.MAIN"/>
               <category android:name="android.intent.category.LAUNCHER"/>
           </intent-filter>
     </activity>
   </application>
 
   <uses-sdk android:minSdkVersion="7"/>
 
</manifest>
AndroidManfiest.xml 속성
<?xml version=“1.0” encoding=“utf-8”?>
<manifest> => 응용 프로그램의 패키지 이름 및 버전 정보를 설정
      <uses-permission /> // 응용프로그램에 필요한 권한 등록
      <permission /> // 응용 프로그램이 다른 응용 프로그램에게 허락하는 권한들을 등록
      <instrumentation /> // 응용 프로그램과 시스템 리소스와의 상호 작용을 모니터링하는 유효
      <uses-sdk /> //  응용 프로그램을 어느 버전의 안드로이드 환경에서 사용할 수 있는지 설정
      <uses-configuration /> // 응용 프로그램에 필요한 하드웨어/소프트웨어 입력 구성을 정의
      <uses-feature /> // 응용 프로그램에서 사용되는 특정 feature를 설정
      <supports-screen /> // 응용 프로그램에서 지원하는 화면 크기를 설정
      <application> // 응용 프로그램의 이름과 아이콘을 설정
           <activity> // 응용 프로그램의 모든 activity를 각각 하나의 <activity> 요소로 등록
               <intent-filter>
               <action />
                   <category />
                   <data />
               </intent-filter>
           </activity>
          <service> </service> // service 등록
          <receiver> </receiver> // broadcast receiver 등록
      <provider> </provider> // content provider 등록
    <uses-library /> // 지도 서비스처럼 추가로 연동되는 다른 패키지들을 링크
</manifest>