Pages

Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

February 9, 2014

[Android] 하나의 TextView에 서로 다른 여러 스타일의 텍스트를 입력하기

TextView를 하나만 써서 여러 가지 스타일을 가진 텍스트를 입력해야만 할 때가 있다. 아래 방법을 알기 전에는 스타일이 바뀔때마다 TextView를 생성해서 배치를 해야 하나 생각했다. 그런데 안드로이드에서 지원되는 생각외로 간단한 방법이 있어서 소개한다.

위와 같이 TextView의 텍스트에 Html이 지원된다. 모든 태그가 지원 되는 것은 아니고 지정한 몇가지만 가능한데 이 링크를 참고하여 지원되는 태그를 확인해보도록 하자.

February 2, 2014

[Android] dp to px or px to dp

안드로이드 앱 개발을 하다가 보면 DP 단위를 Pixel 단위로 바꾸거나 그 반대로 해야할 일이 종종 생긴다.

아래 코드에 두가지 변환을 할 수 있는 함수가 있다.  이렇게 기본적으로 많이 쓰이는 유틸리티 함수들은 따로 클래스를 만들어서 모아 두면 편리할 것 같다.


[Android] Drawable String형 이름으로 Integer형 리소스 아이디 찾기

간단한 팁이지만 필요할 때가 종종 있다.

여기선 두가지 방법을 소개하는데 하나는 Java의 Reflection을 이용한 방법이고 (아래 소스 코드 위쪽 방법) 하나는 Android API에서 제공되는 Method를 이용한 방법이다. (아래 소스 코드의 아래쪽 방법)

Reflection을 이용한 방법이 성능상의 이점이 있다고 한다.  그러나 현재 작업 중인 프로젝트의 패키지가 아닌 다른 패키지에서의 리소스 아이디를 알아야 할 일이 있다면 Android API를 이용한 방법이 유용할 것 이다.



November 21, 2013

[Android] Genymotion최신 버전에서 삭제된 구글 플레이 스토어와 ARM Translation기능 추가하기

최근에 소개한 Android Emulator의 대안 Genymotion이 최근에 큰 업데이트를 하면서 라이센스 문제로 인해 제공하는 Android Rom에서 구글 앱과 ARM Translation기능을 제거하였다. 나로썬 Unity에서 개발한 게임을 주로 Genymotion VirtualMachine에서 테스트하곤 하였는데 Unity는 x86 타겟의 앱빌드를 지원하지 않는다. 따라서 Genymotion 업데이트와 함께 Unity 게임이 동작하지 않음으로 인해 활용 가능성이 확 떨어졌는데 역시 XDA의 용자님들께서 해결 책을 내놓으셨다.

XDA Developers의 원문 링크는 여기로.


절차는 굉장히 간단하다.

1. 이 링크(http://goo.gl/JBQmPa)에서 ARM Translation Installer를 다운 받는다.
2. 다운 받은 zip파일을 드래그하여 Genymotion VirtualMachine 에 드롭한다. File Transfer 창이 뜨고 잠시후 아래 스샷과 같은 창이 나타난다.


OK 를 선택



성공적으로 인스톨이 되었고 버추얼 디바이스를 리붓을 해야 한다. 오른쪽 아래 파워 버튼을 이용해서 디바이스를 셧다운 하고 다시 시작한다.  이제 ARM Translation Library는 추가되어서 Unity에서 빌드한 앱을 설치하고 실행할 수 있다.

3. 이번엔 구글 플레이 스토어를 사용하기 위해 구글 앱들을 설치하자.
주의 : 버추얼 디바이스의 안드로이드 버전에 따라 다른 구글 앱 패키지를 설치해야 한다.
4. 버전에 맞는 구글 앱 패키지를 다운받아 zip 형태의 파일을 버추얼 디바이스에 드래그&드롭하도록 하자. 마찬가지로 File Transfer 창이 나타나고 ARM Translation Library를 설치할 떄와 마찬가지 방법으로 워닝창에서 OK를 선택후 버추얼 디바이스를 재시작하도록 하자.


App Drawer에서 Play Store, Gmail등 구글 핵심 서비스가 등록된것을 볼 수 있다.


Goolgle 계정으로 로그인 하면 구글 플레이 스토어를 사용할 수 있다.

이상으로 Genymotion에서 ARM 기반 바이너리와 구글 플레이 스토어를 사용할 수 있는 방법을 알아 보았다.




November 11, 2013

[Android] 안드로이드 시뮬레이터의 대안 Genymotion

안드로이드 어플리케이션 개발과정에서 가장 마음에 안드는 점을 고르라면 아마도 안드로이드 시뮬레이터를 대부분의 개발자들이 뽑을 것이다. iOS 시뮬레이터와 윈도우즈 폰 에뮬레이터에 비교하면 안드로이드 에뮬레이터는 과연 이것을 쓰라고 만든것인지. 구글의 개발자 지원이 이것밖에 안된다는 것에 상당한 실망을 하게된다.

특히 느려터진 퍼포먼스 때문에 아마도 대부분의 개발자들이 에뮬레이터에서 테스트는 포기하고 실제 디바이스를 가져다가 개발하며 디바이스에서 테스트 해 가며 열악한 상황에서 개발을 하고 있으리라 사료된다.

 이러한 상황에서 안드로이드 개발자들을 구원하고자 Genymotion이 등장했다.



Genymotion은 VirtualBox 위에서 돌아가는 안드로이드 버츄얼 머신으로써 강력한 개발 머신위에서라면 심지어 실제 안드로이드 디바이스보다도 좋은 성능으로 안드로이드 OS를 돌릴 수 도  있다. 이러한 이점을 얻기 위해 내가 들여야 하는 노력은 심지어 안드로이드 개발 SDK를 설치하는 것보다 간단하다.

OSX 상에서는 VirtualBox를 설치하고 Genymotion을 설치하면 끝.
빠르다는 이점외에도 Genymotion 개발사에서 직접 관리하고 있는 Android Rom 을 통해 신뢰할 수 있는 안드로이드 버츄얼 머신으로 내가 만든 앱을 테스트할 수 있다. 그리고 또 하나의 장점은 버츄얼 머신에 빌트인된 하드웨어에 대한 컨트롤을 제공하는 점이다. 아래 스샷을 통해 볼 수 있듯이 GPS를 에뮬레이터하면서 동시에 쉽게 현재 위치를 조작할 수 있는 UI를 제공한다. 카메라, 배터리 등도 마찬가지로 여러가지 옵션을 쉽게 조정할 수 있다.



그리고 또 하나는 Genymotion에서 제공하는 롬중에 안드로이드 앱들이 설치된 채로 배포되는 롬이 있다. 이 롬을 사용하면 구글 플레이 스토어에 접속하여 다른 앱들을 다운로드 받아 에뮬레이터에 설치할 수 도 있다. 거의 실제 디바이스와 다를바 없이 동작하게 되는 것이다.

그리고 Android Studio/Eclipse 플러그인을 제공함으로써 개발 툴과 fully integrated 된 개발이 가능하다는 점이다.

이런 장점들에 반해 약간의 버그가 조금씩 있는데 이제 베타란 딱지를 붙이고 출시된 프로덕이라 앞으로 많이 개선이 되리라 예상된다. 물론 Genymotion에 테스트 되었다고 실제 하드웨어 디바이스에서 테스트 하지 않아도 되는 것은 아니지만 개발에 속력을 붙여 줄 것은 확실하다.







October 11, 2013

[Android] API Level에 따른 Android 버전과 코드내에서 버전 구분하여 구현하기

검색 해보면 금방 찾을 수 있는 내용이긴 하지만 기록을 위해서 보관한다.

아래표는 구글 API Guide에서 긁어온 내용임을 밝힌다.
Platform VersionAPI LevelVERSION_CODENotes
Android 4.318JELLY_BEAN_MR2Platform Highlights
Android 4.2, 4.2.217JELLY_BEAN_MR1Platform Highlights
Android 4.1, 4.1.116JELLY_BEANPlatform Highlights
Android 4.0.3, 4.0.415ICE_CREAM_SANDWICH_MR1Platform Highlights
Android 4.0, 4.0.1, 4.0.214ICE_CREAM_SANDWICH
Android 3.213HONEYCOMB_MR2
Android 3.1.x12HONEYCOMB_MR1Platform Highlights
Android 3.0.x11HONEYCOMBPlatform Highlights
Android 2.3.4
Android 2.3.3
10GINGERBREAD_MR1Platform Highlights
Android 2.3.2
Android 2.3.1
Android 2.3
9GINGERBREAD
Android 2.2.x8FROYOPlatform Highlights
Android 2.1.x7ECLAIR_MR1Platform Highlights
Android 2.0.16ECLAIR_0_1
Android 2.05ECLAIR
Android 1.64DONUTPlatform Highlights
Android 1.53CUPCAKEPlatform Highlights
Android 1.12BASE_1_1
Android 1.01BASE
그리고 코드내에서 안드로이드 버전에 따라 구현을 다르게 하고 싶다면 다음과 같이 구분한다.


    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        // Android OS Version 4.1 이상에서 동작할 내용
    } else {
        // Android OS Version 4.1 미만의 OS에서 동작할 내용
    }


October 3, 2013

[Android] 각종 무료 Custom View들을 한자리에




안드로이드 앱 개발에 유용하게 쓸 수 있는 각종 Custom View들을 간략한 스샷과 함께 소개하는 사이트.

아직은 좀 많이 부족하고 소개가 되어 있지 않은 것들도 많지만 Major급들의 커스텀 뷰는 이곳에서 확인할 수 있다.

September 30, 2013

[Android] android.app.application 을 이용한 공유 변수사용하기

안드로이드 앱을 만들다 보면 각 Activity 전환에 상관없이 항상 유지해야 하는 상태값등을 어떻게 저장해야 할지에 대한 애매한 상황이 발생한다.

이러한 경우 안드로이드 앱이 실행되면 자동으로 객체가 생성되는 android.app.application을 상속받는 클래스를 사용하는 것이 한 방법이 될 수 있다. 이 경우 Context.getApplicationContext() 함수를 호출하여 필요한곳 어디서든 android.app.application  상속 클래스의 인스턴스를 받아서 활용할 수 있다.

AndroidManifest.xml 내에서 아래와 같이 application에 해당하는 클래스를 지정해준다.



...



그리고 android.app.application 을 상속받는 MainClass는 아래와 같이 구현한다.


public class MainApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // 전역 범위의 초기화 작업 진행
    }
}

더 자세한 사항은 이 링크를 참조하도록 하자

September 26, 2013

[Android] 디바이스 시간 설정 변경 이벤트 캐치하기

디바이스의 시간 설정이 변경되었음을 나의 앱이 알아차리기 위해서는 시스템이 시간 관련 설정이 변경 되었을 때 Broadcast하는 Intent를 앱이 캐치하도록 하면된다.

여기서 시간 설정 변경이란 사용자가 디바이스의 시간을 수동으로 변경하는 경우나 시간 서버와 동기화로 인해 시간이 변경되는 경우를 의미하고 시간이 흐르는 이벤트는 별개의 것으로 다룬다.

사용자가 시간을 변경하는 경우


사용자가 설정 메뉴을 이용하여 수동으로 시간을 바꾸는 경우 발생하는 이벤트이다. 이 경우 관심을 가져야 하는 Intent는 ACTION_TIME_CHANGED,  ACTION_TIMEZONE_CHANGED로 다음과 같이 Broadcast Receive에 Intent filter를 적용하고 이벤트를 캐치하도록 한다.

  1. ACTION_TIME_CHANGED : 시간, 날짜 변경에 관계 없이 어느 하나라도 변경하는 경우 발생한다. 실제로 디바이스상에서 시간값을 변경하면 이 Intent가 2번 브로드캐스트 되는데 안드로이드 OS의 버그로 보인다. 시간 변경창을 띄우고 시간을 바꾸지 않더라도 뒤로가기 버튼을 누르면 창이 닫히면서 1번 브로드캐스트된다. 명백한 버그로 보인다.
  2. ACTION_TIMEZONE_CHANGED : 타임존 관련 세팅이 변경되면 발생한다. 차를 타고 시간 존이 변경되는 지역을 지나가면 이 이벤트가 발생하는지 안하는지는 테스트 해보지 않았으나 정상적으로 OS가 구현이 되었다면 발생해야 할 것 같지만 위에서 보듯이 안드로이드 OS도 버그가 많아서..어쩔지는 미지수이다. 


AndroidManifest.xml

    
        
        
        
        
    


DeviceEventReceiver.java
public class DeviceEventReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (Intent.ACTION_TIME_CHANGED.equals(action)
            || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
                // 시간이 변경된 경우 해야 될 작업을 한다.
         doSomething();
        }
    }
}


시간이 흐름에 따라 시간이 변경되는 경우

이 경우 캐치해야 하는 Intent는 ACTION_TIME_TICK 혹은 ACTION_DATE_CHANGED이다.

  1. ACTION_TIME_TICK : 매 분마다 이벤트가 발생한다. 이 이벤트는 AndroidManifest에 Intent filter를 적용하는 것으로 캐치할 수 없고 코드내에서 동적으로 등록을 해야한다. 아마도 실수로 이 이벤트에 대한 로직을 추가하여 디바이스 배터리 광탈을 막기위한 목적이 아닌가 한다.
  2. ACTION_DATE_CHANGED : 이 이벤트는 날짜가 변경 될 때 발생한다. 다시 설명하면 어느 날의 11:59  PM에서 자정으로 넘어가 날짜가 변경되는 경우 브로드캐스트 되는 Intent이다. 

각 경우의 예제 코드는 다음과 같다.

ACTION_TIME_TICK 이벤트

SomeActivity.java
private static BroadcastReceiver _tickReceiver;

@Override
public void onCreate() {
    super.onCreate();
    
 _tickReceiver = new BroadcastReceiver() {
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();

         if (action.equals(Intent.ACTION_TIME_TICK)) {
             doSomeTask();
         }
     }
    };

    IntentFilter _intentFilter = new IntentFilter();
 _intentFilter.addAction(Intent.ACTION_TIME_TICK);

    registerReceiver(tickReceiver, _intentFilter);
}

@Override
public void onStop() {
 super.onStop();
 
 //unregister broadcast receiver.
 if (_tickReceiver != null)
  unregisterReceiver(_tickReceiver);
}
ACTION_DATE_CHANGED 이벤트

AndroidManifest.xml

    
        
        
    


DeviceEventReceiver.java
public class DeviceEventReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (Intent.ACTION_DATE_CHANGED.equals(action)) {
                // 날짜가 변경된 경우 해야 될 작업을 한다.
         doSomething();
        }
    }
}