Tag Archives: 안드로이드

안드로이드(Android) Dialog의 cancel()과 dismiss()의 차이

안드로이드(Android)에서 다이얼로그(Dialog)는 앱이 자주 사용하는 UI 컴포넌트이다. 다이얼로그를 보여주는 데는 show() 세드를 사용하고, 종료하는데는 cancel(), dismiss() 메서드를 사용할 수 있다. 종료하는 이 두 메서드에 대해서 API 문서에서는 아래와 같이 설명하고 있다. UI 경험이 별로 없다보니 잘 감이 안 온다. 화면에서 다이얼로그가 종료되는 동작은 같기에 차이가 없어 보인다.

종료하는데 사용하는 두 메서드의 API 문서를 살펴보면 다음과 같다.

void cancel()

Cancel the dialog.
void dismiss()

Dismiss this dialog, removing it from the screen.

이 두 메서드의 차이에 대해서 살펴보자. API 문서만으로 차이점을 알기가 쉽지 않으니, 다이얼로그 API 소스에서 차이를 확인해보자.

1. cancel() 메서드 소스

    /**
     * Cancel the dialog.  This is essentially the same as calling {@link #dismiss()}, but it will
     * also call your {@link DialogInterface.OnCancelListener} (if registered).
     */
    public void cancel() {
        if (!mCanceled && mCancelMessage != null) {
            mCanceled = true;
            // Obtain a new message so this dialog can be re-used
            Message.obtain(mCancelMessage).sendToTarget();
        }
        dismiss();
    }

위 canel() 메서드는 다음의 단계를 거치게 된다. 그리고 이 메서드는 OnCancelListener로 등록한 객체가 있으면 호출해 준다.

  • mCancelMessage가 있으면 메시지를 전달한다.
  • dismiss()를 호출한다.

2. dismiss() 메서드

 
    /**
     * Dismiss this dialog, removing it from the screen. This method can be
     * invoked safely from any thread.  Note that you should not override this
     * method to do cleanup when the dialog is dismissed, instead implement
     * that in {@link #onStop}.
     */
    public void dismiss() {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(mDismissAction);
        } else {
            mHandler.removeCallbacks(mDismissAction);
            mDismissAction.run();
        }
    }

위 dismiss() 메서드는 화면에서 다이얼로그를 종료하는 역할을 하고 스레드 세이프 하다. 스레드 세이프 하다는 것으로 UI 스레드만이 다이얼로그를 종료시킨다는 것도 알 수 있다. 다이얼로그는 mDismissAction.run() 메서드가 종료시킨다. 이 메서드는 dismissDialog() 메서드를 호출하고, 이 메서드에서는 윈도 매니저를 사용해서 다이얼로그를 윈도에서 제거한다.

그리고 다이얼로그가 화면에 보이는 상황에서 백 키를 누르면 아래의 소스와 같이 동작한다. 즉 cancel() 메서드를 호출해서 다이얼로그를 종료시킨다. 따라서 백키의 이벤트로 다이얼로그가 종료하는 상황은 DialogInterface.OnCancelListener 인터페이스를 구현하면 되겠다.

    /**
     * Called when the dialog has detected the user's press of the back
     * key.  The default implementation simply cancels the dialog (only if
     * it is cancelable), but you can override this to do whatever you want.
     */
    public void onBackPressed() {
        if (mCancelable) {
            cancel();
        }
    }

위에서 살펴본 cancel()과 dismiss()와 같이 API 문서를 봐도 차이점이 잘 이해가 되지 않는 경우에는 API 소스를 보면서 확인하는게 매우 도움이 된다.

안드로이드(Android) 기기의 다양한 화면 지원하기

안드로이드(Android) OS는 다양한 기기에 포팅될 수 있다. 그리고 다양한 기기는 자신만의 화면 크기를 가지는 경우가 많다. 이렇다 보니 애플리케이션을 개발하다 보면 기기의 고유 해상도로 인해서 문제가 생길 수 있다.

안드로이드는 허니콤 버전부터 태블릿을 지원하기 시작해서, 아이스크림부터는 모바일과 태블릿을 같이 지원하기 시작했다. 이런 상황이다 보니, 구글에서는 해상도에 어울리게 UI를 구성(XML 파일로 구성)하도록 가이드(Supporting Multiple Screens) 하고 있다. 이 가이드를 보면 다양한 해상도를 지원하려면 /res/layout-sw600dp/layout.xml 과 같은 파일을 화면에 적합하게 여러 개 만들어서 개발하라는 것이다.

화면에 적당한 UI로 앱의 퀄리티를 유지하는 방향으로는 좋겠지만, 그만큼 개발비용(iOS에 비해)을 증가시킬 게 분명하다. 물론, 이 방법으로 한 바이너리로 모바일/태블릿/TV를 지원할 수 있어서 좋긴 하다. 하지만 가이드 대로 개발해 보니, 이렇게 분리해서 개별 UI(모바일/태블릿/TV)의 장점을 살릴 수 있을까? 라는 질문에는 잘 만들면(?) 된다는 생각이다. 한 바이너리로 여러 화면에 적합한 UI를 서비스 할 수 있다는 것은 역시나 매력적이고 앞으로도 이 방향으로 서비스를 개발하는 것이 좋겠다.

앱을 개발하면서 화면별(모바일, 태블릿 그리고 TV) UI 구성은 어떻게 할 수 있을까? 에 대한 대답은 layout_weight 속성으로 해결한다는 것이다.

아래 예제에서 <LinearLayout>의 layout_weight 속성을 가지는 요소는 자신의 UI가 차지하는 %를 숫자(6 -> 60%)로 표현한 것이고, weightSum은 없으면 알아서 배열하지만, 아래 예에서는 10으로 입력해 놓았다. 그리고 가로(horizontal) 또는 세로(vertical)의 비율로 크기를 맞추는 방법은, 가로를 맞추기 위해서는 layout_width, 세로로 맞추기 위해서는 layout_height을 ‘0dp’로 입력하면 된다.

아래는 위에서 설명한 화면의 구성을 비율로 구성한 예이다.

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
    android:id=”@+id/linearLayout”
    android:orientation=”horizontal”
    android:layout_width=”fill_parent”
    android:background=”#568dfb”
    android:weightSum=”10.0″
    android:layout_gravity=”center_vertical”
    android:layout_height=”40dp”>

    <TextView android:id=”@+id/textView”
        android:text=” “
        android:visibility=”visible”
        android:paddingLeft=”8dp”
        android:layout_width=”0dp”
        android:layout_weight=”6″
        android:textColor=”@android:color/white”
        android:layout_height=”40dp”
        android:textAppearance=”?android:attr/textAppearanceMedium”/>

       <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
        android:id=”@+id/linear_container”
        android:orientation=”horizontal”
        android:layout_width=”0dp”
        android:layout_height=”40dp”
        android:layout_weight=”4″
        android:background=”#568dfb”
        android:gravity=”right”
        android:layout_gravity=”center_vertical”>
       
        <ProgressBar
            android:layout_gravity=”right|center_vertical”
            android:background=”#568dfb”
            android:layout_width=”30dp”
            android:layout_height=”30dp” />
       
        <TextView
            android:id=”@+id/loadingTextView”
            android:layout_width=”wrap_content”
            android:layout_height=”40dp”
            android:layout_gravity=”right”
            android:background=”#568dfb”
            android:gravity=”center_vertical”
            android:paddingLeft=”4dp”
            android:paddingRight=”4dp”
            android:text=”Loading…”
            android:textAppearance=”?android:attr/textAppearanceMedium”
            android:textColor=”@android:color/white”/>
    </LinearLayout>
</LinearLayout>

 

안드로이드(Android) 페이스북(Facebook) SDK 사용하기

안드로이드(Android) 앱에서 페이스북(Facebook) SDK를 사용하는 내용이다. 아래는 페이스북 SDK를 연동하면서 정리한 내용이고 이클립스를 기준으로 설명한다.

1.  https://github.com/facebook/facebook-android-sdk 다운로드 및 압축해제
1.1. 압축을 해제한 프로젝트에서 facebook 폴더의 프로젝트를 이클립스에 import 한다.

 

 1.2 기존의 프로젝트에 reference 하기
– Project > Properties > Android > Library > Add로 com_facebook_sdk를 추가한다.

  

2. OpenSSL 설치
2.1. 리눅스 설치 : http://www.ibrtses.com/linux/openssl.html
2.2. 윈도 설치 : http://www.slproweb.com/products/Win32OpenSSL.html 에서 환경에 맞게 설치를 한다. 혹, bin 디렉토리가 PATH에 안 잡혀 있어서 페이스북에 등록해야 하는 해시키 생성에 실패할 수 있으니 확인이 필요하다.

3. 해시키 만들고 등록하기
3.1 해시키 만들기 : 아래의 명령을 통해서 해시키를 만든다.
> keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
3.2 만들어진 해시키를 페이스북에 등록한다.
Facebook Developer 페이지의 Step 5의 이미지를 보면 쉽게 확인할 수 있다.

4. 테스트 하기..
테스트 코드도 역시 Facebook Developer 페이지에서 확인하면 된다.

* Reference
Facebook Developer 페이지

Android에서 앱 Activity 관리 및 앱 종료 detect하기..

안드로이드(Android)에서 앱의 Activity나 앱 종료를 체크하기 위해서, Activity Stack을 설정한 개수만큼만 유지시켜주는 클래스를 만들었다.

ActivityManager.java

import java.util.concurrent.LinkedBlockingQueue;
import android.app.Activity;
/**
 * Activity Manager Class
 * @author mcsong@gmail.com
 *
 */
public class ActivityManager {
    private static final int max = 13;
    private static final int size =12;
    private static LinkedBlockingQueue queue = new LinkedBlockingQueue(max);
    private static final String CNAME = ActivityManager.class.getSimpleName();

    public static void createActivity(Activity activity) {
        if(activity == null)
            return;

        queue.add(activity);
        if(queue.size() > size) {
            try {
                queue.take().finish();
            } catch (Exception e) {
                LogUtil.e(CNAME, LogUtil.TAG, ExceptionUtil.getException(e));               
            }
        }
    }

    public static boolean isRootActivity(Activity activity) {
        if(activity == null)
            return false;

        try {
            if(activity == queue.peek())
                return true;
        } catch (Exception e) {
            LogUtil.e(CNAME, LogUtil.TAG, ExceptionUtil.getException(e));               
        }

        return false;
    }

    public static void clear() throws InterruptedException {
        while(queue.size() > 0) {
            queue.take().finish();
        }
    }
}

사용방법 및 효과
– Activity 생성(onCreate 메소드에서)시에 createActivity()를 호출한다. 자연스럽게 size만큼 Activity Stack이 관리가 된다.
– 앱 종료 detect는 isRootActivity()로 확인을 하면 된다.. ture인 경우 각 Activity 클래스에서.. onBackPressed()를 Override해서 확인하면 된다.. 참고로, AbstractActivity 클래스를 만들어서 상속해서 AbstractActivity 클래스에서 이 코드를 삽입하면 각각의 Activity 클래스에서 이 코드를 삽입할 필요가 없다.
– 앱을 종료하면서 clear()를 호출해서 Activity stack에 있는 Activity들을 다 날려주셔야 Activity 관리가 명확해 집니다.. ^^

안드로이드 activity의 동작형태는 android:launchMode=”standard” 에서 잘 동작한다.

안드로이드 퍼미션 리스트

아래는 안드로이드 퍼미션 목록이다.


ACCESS_CHECKIN_PROPERTIES      체크인데이터베이스의_속성테이블로_액세스
ACCESS_COARSE_LOCATION         코스_로케이션_액세스_(Cell-ID/WiFi)
ACCESS_FINE_LOCATION           파인로케이션_액세스(GPS)         
ACCESS_LOCATION_EXTRA_COMMANDS 로케이션_옵션_커맨드_액세스      
ACCESS_MOCK_LOCATION           목_로케이션_프로바이더_생성_(테스트용)
ACCESS_NETWORK_STATE           네트워크_상태_접근               
ACCESS_SURFACE_FLINGER         서피스_플링거_접근               
ACCESS_WIFI_STATE              WiFi상태_접근                    
ADD_SYSTEM_SERVICE             시스템서비스_추가                
BATTERY_STATS                  배터리_상태                      
BLUETOOTH                      블루투스                         
BLUETOOTH_ADMIN                블루투스_어드민                  
BRICK                          디바이스_실효성_지정             
BROADCAST_PACKAGE_REMOVED      제거된_패키지에_대한_notification_브로드캐스트
BROADCAST_SMS                  SMS에_대한_브로드캐스트          
BROADCAST_STICKY               인텐트_브로드캐스트              
CALL_PHONE                     통화                             
CALL_PRIVILEGED                통화(긴급전화_포함)              
CAMERA                         카메라                           
CHANGE_COMPONENT_ENABLED_STATE 컴포넌트의_실효성_변경           
CHANGE_CONFIGURATION           컨피그_변경                      
CHANGE_NETWORK_STATE           통신상태_변경                    
CHANGE_WIFI_STATE              WiFi상태_변경                    
CLEAR_APP_CACHE                어플리케이션_캐시_클리어         
CLEAR_APP_USER_DATA            어플리케이션의_유저데이터_클리어 
CONTROL_LOCATION_UPDATES       위치정보_갱신                    
DELETE_CACHE_FILES             캐시파일_제거                    
DELETE_PACKAGES                패키지_제거                      
DEVICE_POWER                   전원상태에_대한_로우레벨_접근    
DIAGNOSTIC                     진단리소스_읽고쓰기              
DISABLE_KEYGUARD               키_가드_끄기_DUMP_덤?           
EXPAND_STATUS_BAR              상태표시줄_확장                  
FACTORY_TEST                   팩토리_테스트                    
FLASHLIGHT                     플래시라이트                     
FORCE_BACK                     포스백                           
GET_ACCOUNTS                   어카운트_획득                    
GET_PACKAGE_SIZE               패키지_획득                      
GET_TASKS                      태스크_획득                      
HARDWARE_TEST                  하드웨어테스트                   
INJECT_EVENTS                  유저이벤트_키/트랙볼             
INSTALL_PACKAGES               패키지_인스톨                    
INTERNAL_SYSTEM_WINDOW         내부_시스템윈도_활용             
INTERNET                       인터넷                           
MANAGE_APP_TOKENS              어플리케이션_토큰관리            
MASTER_CLEAR                   마스터_클리어                    
MODIFY_AUDIO_SETTINGS          오디오설정_편집                  
MODIFY_PHONE_STATE             전화상태_편집                    
MOUNT_UNMOUNT_FILESYSTEMS      파일시스템_편집                  
PERSISTENT_ACTIVITY            액티비티_지속                    
PROCESS_OUTGOING_CALLS         전화_발신처리_접근               
READ_CALENDAR                  캘린더_읽어오기                  
READ_CONTACTS                  주소록_읽어오기                  
READ_FRAME_BUFFER              프레임버퍼_읽어오기              
READ_INPUT_STATE               입력상태_읽어오기                
READ_LOGS                      로그_읽어오기                    
READ_OWNER_DATA                owner_data읽어오기               
READ_PHONE_STATE               통화상태_읽어오기_READ_SMS_SMS읽어오기
READ_SYNC_SETTINGS             동기설정_읽어오기                
READ_SYNC_STATS                동기상태_읽어오기                
REBOOT                         reboot                           
RECEIVE_BOOT_COMPLETED         boot완료                         
RECEIVE_MMS                    MMS수신                          
RECEIVE_SMS                    SMS수신                          
RECEIVE_WAP_PUSH               WAP수신                          
RECORD_AUDIO                   오디오_수신                      
REORDER_TASKS                  태스크_Z오더                     
RESTART_PACKAGES               패키지_리스타트                  
SEND_SMS                       SMS송신                          
SET_ACTIVITY_WATCHER           액티비티_왓쳐지정                
SET_ALWAYS_FINISH              액티비티_전체_종료               
SET_ANIMATION_SCALE            스케일_애니메이션_지정           
SET_DEBUG_APP                  디버그어플리케이션_지정          
SET_ORIENTATION                스크린_로테이션지정              
SET_PREFERRED_APPLICATIONS     자주_사용하는_어플리케이션_지정  
SET_PROCESS_FOREGROUND         포어그라운드_처리지정            
SET_PROCESS_LIMIT              제한처리_지정                    
SET_TIME_ZONE                  타임존_지정                      
SET_WALLPAPER                  배경화면_지정                    
SET_WALLPAPER_HINTS            배경화면_힌트_지정               
SIGNAL_PERSISTENT_PROCESSES    지속처리_시그널_지정             
STATUS_BAR                     상태표시줄_지정                  
SUBSCRIBED_FEEDS_READ          서브스트립드_피즈_읽어오기       
SUBSCRIBED_FEEDS_WRITE         서브스트립드_피즈_쓰기           
SYSTEM_ALERT_WINDOW            알림_윈도우                      
VIBRATE                        진동                             
WAKE_LOCK                      알람                             
WRITE_APN_SETTINGS             APN설정_쓰기                     
WRITE_CALENDAR                 캘린더_쓰기                      
WRITE_CONTACTS                 주소록_쓰기                      
WRITE_GSERVICES                G서비스_쓰기                     
WRITE_OWNER_DATA               owner_data쓰기                   
WRITE_SETTINGS                 설정_쓰기
WRITE_SMS                      SMS쓰기
WRITE_SYNC_SETTINGS            동기설정_쓰기

* Reference
http://javaexpert.tistory.com/329