2012년 7월 18일 수요일

[JAVA] Reflection - 정해지지 않은 클래스를 사용하자


Reflections on Java Reflection


원문 : http://onjava.com/pub/a/onjava/2007/03/15/reflections-on-java-reflection.html
번역판 : http://www.hanb.co.kr/network/view.html?bi_id=1369

2012년 7월 10일 화요일

[안드로이드] API15>16젤리빈 변경 클래스 - ContentResolver

public final ContentProviderClient acquireUnstableContentProviderClient (Uri uri)

Since: API Level 16
acquireContentProviderClient(Uri)와 흡사하나, 대상 컨텐트 프로바이더의 안정성을 신뢰하지 않는 경우 사용한다. 이는 대상 컨텐트 프로바이더의 프로세스가 사라질 경우, 컨텐트 프로바이더에 의존된 프로세스들의 플랫폼 클린업 메카니즘을 해제 한다. 일반적으론, 한번 프로바이더를 얻으면 필요한 만큼 제약없이 사용 할 수 있으며, 프로세스가 백그라운드 상태여도 사라지지도 않는다고 가정 할 수 있다. 이 메소드를 사용 하면, 프로바이더와의 통신중 어떠한 오류가 발생 하더라도 나중에 재연결 할 수 있게, 반드시 close에 주의를 기울여야 한다. 특히, DeadObjectException을 잡아 컨텐트 프로바이더가 죽어버렸다는 걸 알 수 있는데, 이는 현재 ContentProviderClient 오브젝트가 유효하지 않으며, 이를 해제 해야 한다는 것을 나타낸다. 만일 프로바이더를 재시작해 새로운 작업을 수행하려 한다면, 새로 얻으면 된다.

public final ContentProviderClient acquireUnstableContentProviderClient (String name)

Since: API Level 16
acquireContentProviderClient(String)와 흡사 하나,  대상 컨텐트 프로바이더의 안정성을 신뢰하지 않는 경우 사용한다. 이는 대상 컨텐트 프로바이더의 프로세스가 사라질 경우, 컨텐트 프로바이더에 의존된 프로세스들의 플랫폼 클린업 메카니즘을 해제 한다. 일반적으론, 한번 프로바이더를 얻으면 필요한 만큼 제약없이 사용 할 수 있으며, 프로세스가 백그라운드 상태여도 사라지지도 않는다고 가정 할 수 있다. 이 메소드를 사용 하면, 프로바이더와의 통신중 어떠한 오류가 발생 하더라도 나중에 재연결 할 수 있게, 반드시 close에 주의를 기울여야 한다. 특히, DeadObjectException을 잡아 컨텐트 프로바이더가 죽어버렸다는 걸 알 수 있는데, 이는 현재 ContentProviderClient 오브젝트가 유효하지 않으며, 이를 해제 해야 한다는 것을 나타낸다. 만일 프로바이더를 재시작해 새로운 작업을 수행하려 한다면, 새로 얻으면 된다.

public final Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)

Since: API Level 16
주어진 URI로 쿼리를 수행해, 결과 집합의 Cursor를 리턴 한다.
최적의 성능을 위해, 호출자는 다음과 같은 가이드 라인을 따라야 한다:
  • 사용되지 않을 데이터를 저장소에서 읽는 것을 막기 위해 명시적인 프로젝션을 사용하라. 
  • selection 파라메터에 명시적인 값 대신에 'phone=?'와 같은  물음표 파라메터 마커를 사용하여, 해당 값만 다르게 하여 캐 동일한 쿼리로 인식 될 수 있도록 하라.
Parameters
uri컨텐트를 명시하기 위해 content:// 스키마를 사용하는 URI.
projection리턴받을 column의 리스트. NULL을 넣으면 모든 column을 리턴 하므로 비효율적임.
selection어떤 row를 리턴 할지 SQL WHERE 구문(WHERE 자체는 제외)형식으로 선언한 필터. NULL을 넣으면 모든 주어진 URI의 모든 row를 리턴함.
selectionArgs만일 selection에 ?를 사용 했다면, 순서대로 selectionArgs의 값들로 치환된다. 값들은 Strings으로 묶이게 된다.
sortOrder각 row를 어떻게 나열할지 SQL ORDER BY 구문(ORDER BY 자체는 제외) 형식으로 지정. NULL을 넣으면 기본값인 "unordered"가 사용된다.
cancellationSignal처리 중에 해당 작업을 취소시키기 위한 시그널로 없으면 null지정. 작업이 취소되면 쿼리가 수행된 후 OperationCanceledException 이 던져 진다.
Returns
  • 첫 항목의 바로 전을 가리키는 Cursor 오브젝트, 또는 null
See Also

[안드로이드] 젤리빈 추가 클래스 - CancellationSignal

원문
http://developer.android.com/reference/android/os/CancellationSignal.html
public final class
CancellationSignal
extends Object
java.lang.Object

android.os.CancellationSignal

Class Overview


진행중인 작업을 취소 할 수 있는 기능을 제공 합니다.

Summary


Nesterd Classes
interfaceCancellationSignal.OnCancelListener취소 후 호출될 리스너.
Public Constructors
CancellationSignal ()
 취소 시그널을 생성하며, 처음엔 취소되지 않은 상태 입니다.
Public Methods
voidcancel ()
작업을 취소하고 취소 리스너에 알립니다.
booleanisCanceled ()
작업이 취소되었다면 true를 반환합니다.
voidsetOnCancelListener ( CancellationSignal.OnCancelListener listener)
취소되면 호출될 취소 리스너를 지정합니다.
voidthrowIfCanceled ()
작업이 취소되면 OperationCanceledException을 던집니다..

[펼치기]
Inherited Methods
 From class java.lang.Object

Public Constructors



public CancellationSignal ()

Since: API Level 16 
취소 시그널을 생성하며, 처음엔 취소되지 않은 상태 입니다.

Public Methods



public void cancel ()

Since: API Level 16 
작업을 취소하고 취소 리스너에 알립니다. 만일 작업이 아직 시작되지 않았다면, 가능한한 바로 취소됩니다.

public boolean isCanceled ()

Since: API Level 16 
작업이 취소되었다면 true를 반환합니다.
Returns
  • 작업이 취소되었다면 True.

public void setOnCancelListener CancellationSignal.OnCancelListener linstener)

Since: API Level 16 
취소시 호출될 취소 리스너를 설정합니다. 이 메소드는 오래 걸리는 작업을 수행하는 동안, 취소 요청을 처리할 목적으로 데이터베이스나 컨텐트 프로바이더와 같은 취소 시그널의 수신자에 의해 사용될 것입니다. 이 메소드는 응용 프로그램 자체에서 사용되도록 의도된 메소드가 아닙니다. 만일 cancel()이 이미 호출 되었다면, 지정된 리스너도 즉시 호출됩니다. 이 메소드는 리스너가 제거된 뒤에는 호출되지 않음을 보장 합니다.
매개 변수
listener취소 리스너, NULL값을 지정하면 현재 지정된 리스너를 제거함.

public void throwIfCanceled ()

Since: API Level 16 
작업이 취소되면 OperationCanceledException을 던짐.
Throws
OperationCanceledException작업이 취소됨.

2012년 7월 8일 일요일

[안드로이드] 멀티스크린과 안드로이드 마켓


안드로이드 마켓에 릴리즈시 하나의 어플리케이션에 두개의 APK파일을 등록할 수 있는 MultipleScreens 기능이 있다.

AndroidManifest.xml 의 스크린사이즈가 다르거나 SDK Version이 다른 두개의 APK파일을 업로드 하여 Publish하면 되는거.. 하지만 해상도의 구분이 애매하였다.

열심히 구글링을 해보면...아래값들을 컨트롤하면 된다.
smallScreens = true (normalScreens 보다 작은 사이즈 지원)
normalScreens = true (normalScreens 사이즈 지원)
largeScreens = true (normalScreens 보다 큰 사이즈 지원)
xlargeScreens = true (largeScreens 보다 큰 사이즈 지원)


requiresSmallestWidthDp = 600 (Android 3.2 API Level 13이후부터 지원하는 attribute. 
600에 largeScreens = true, xlargeScreens = true를 설정하면 타블렛만 지원되는 어플이 된다.)


<supports-screens android:resizeable=["true"| "false"]
                  android:smallScreens = ["true" | "false"]
                  android:normalScreens = ["true" | "false"]
                  android:largeScreens = ["true" | "false"]
                  android:xlargeScreens = ["true" | "false"]
                  android:anyDensity=["true" | "false"]
                  android:requiresSmallestWidthDp="integer"
                  android:compatibleWidthLimitDp="integer"
                  android:largestWidthLimitDp="integer"/>

즉.....2.3에선 requiresSmallestWidthDp를 사용할 수 없고, 갤노트와 갤S2는 아래와 같이 구분하여 적용 시키면 마켓 필터링이 가능하다.


*. 갤럭시 S2
<supports-screens
     android:smallScreens="false"
     android:normalScreens="true"
     android:largeScreens="false"
     android:xlargeScreens="false"
     android:anyDensity="true"
/>


 *. 갤럭시 노트
<supports-screens
     android:smallScreens="false"
     android:normalScreens="false"
     android:largeScreens="true"
     android:xlargeScreens="false"
     android:anyDensity="true"
/>

추가로 엄청 중요한 사항이 생겼다. 위와 같이 했을 경우 마켓 릴리즈시 버전코드가 갤럭시 S2가 더 낮아야 한다. 즉!! 갤럭시 S2의 버전코드가 100이라면 갤럭시 노트의 버전코드는 101이 되어야 정상적인 릴리즈가 가능하다. 만약 갤럭시 노트의 버전 코드가 더 낮다면 빨간색 에러줄을 마주치게 된다. 아...이것때문에 엄청 암울했는데...ㅠㅠ 
혹 여기서 10.1인치를 필터링 시키려면 안드로이드마켓 등록시 지원등록단말에서 수동 삭제하면...ㅋㅋㅋㅋ된다.
내가 삽질한건??? 내가 원한건 다른 사이즈들은 다빼고 딱 normalScreens만 지원하고 싶었을 뿐인데...
이게 normalScreens = true로 하고, 다른 스크린을 false로 설정해도 normalScreens~xlargeScreens까지 지원된다는거다...
그래서 찾아보다가 아래와 compatible-screens를 찾게되었다. 역기서 screenSize="normal"로 설정하면 마켓상에서 딱!!! normalScreens만 지원된다...
허나...compatible-screens를 적용시키면 지원단말에서 국산단말은 제외되고, 해외향 단말만 지원된다.
젠장...된장...진장...아래처럼 모든 Density에 모든 screenSize를 설정해도 국내향단말은 지원단말에서 제외되어있다...ㅠㅠㅠㅠ
이걸 하나씩 확인해보다...왜 갤노트는 제외되지...왜 갤S2는 제외되지...
그러다 모든걸 적용시켜도 안된다는걸 알고 포기함.

    <compatible-screens>
        <screen android:screenDensity="xhdpi" android:screenSize="small"/>
        <screen android:screenDensity="ldpi" android:screenSize="small"/>
        <screen android:screenDensity="mdpi" android:screenSize="small"/>
        <screen android:screenDensity="hdpi" android:screenSize="small"/>
        <screen android:screenDensity="xhdpi" android:screenSize="normal"/>
        <screen android:screenDensity="ldpi" android:screenSize="normal"/>
        <screen android:screenDensity="mdpi" android:screenSize="normal"/>
        <screen android:screenDensity="hdpi" android:screenSize="normal"/>
        <screen android:screenDensity="xhdpi" android:screenSize="xlarge"/>
        <screen android:screenDensity="ldpi" android:screenSize="xlarge"/>
        <screen android:screenDensity="mdpi" android:screenSize="xlarge"/>
        <screen android:screenDensity="hdpi" android:screenSize="xlarge"/>
        <screen android:screenDensity="xhdpi" android:screenSize="large"/>
        <screen android:screenDensity="ldpi" android:screenSize="large"/>
        <screen android:screenDensity="mdpi" android:screenSize="large"/>
        <screen android:screenDensity="hdpi" android:screenSize="large"/>    
     </compatible-screens> 

1. 마지막으로 dpi구하는 공식
  context.getResources().getDisplayMetrics().density; 
2. dpi를 픽셀로 변환하는 공식
public static int convertDipToPx(Context context, int dip){
  final float scale = context.getResources().getDisplayMetrics().density;
  return (int) (dip * scale + 0.5f);
}


참조 : http://sptraulyo.tistory.com/447

[안드로이드] 스마트폰 레이아웃


요샌 안드로이드 폰 종류도 너무 많고 레이아웃, 해상도도 천차 만별...
외우려면 힘드니 이곳에 정리 하려 한다.

갤럭시넥서스: layout-sw360dp
갤럭시노트: layout-xhdpi-1280x800 (or layout-normal-xhdpi)
갤럭시탭10.1: layout-xlarge-mdpi(3.2이상 버전에서는 layout-sw800dp로도 가능)
HD(1280x720)폰: layout-xhdpi-1280x720 (layout-normal-xhdpi)
HTC Evo4g: layout-hdpi-960x540

OS버전 3.2이상에서는 layout-sw800dp와 같이 너비(짧은축의 길이)의 dip값으로 하면 편리할 듯 합니다.

해상도별 스크린 레이아웃안드로이드 2012/02/21 12:37
QVGA(240x320), 120dpi : HTC Tatoo
HVGA(320x480), 160dpi : 안드로원, HTC G1
WVGA(480x800), 240dpi : 넥서스원, 갤럭시A
FWVGA(480x854), 240dpi : 모토로이


1. Low desity 120 - ldpi
    QVGA(240x320)  : 2.6~3.0
    WQVGA(240x400) : 3.2~3.5
    FWQVGA(240X432) : 3.5~3.8


2. Medium density 160 - mdpi
   HVGA(320X480) : 3.0~3.5
   WVGA(480x800) : 4.8~5.5
   FWVGA(480X854) : 5.0~5.8


3. High density 240 - hdpi
   WVGA(480x800) : 3.3~4.0
   FWVGA(480X854) : 3.5~4.0


4. x High density 320 - xhdpi
    (720*1280)


갤럭시탭 10.1
drawable-xlarge-mdpi
layout-xlarge 또는 layout-1280x800


갤럭시탭 7.0
drawable-large-hdpi
layout-1024x600


일반폰 (480x800)
drawable-hdpi
layout


HD폰(1280x720)
drawable-xhdpi
layout-1280x720



갤럭시넥서스: layout-sw360dp
갤럭시노트: layout-xhdpi-1280x800 (or layout-normal-xhdpi)
갤럭시탭10.1: layout-xlarge-mdpi(3.2이상 버전에서는 layout-sw800dp로도 가능)
HD(1280x720)폰: layout-xhdpi-1280x720 (layout-normal-xhdpi)
HTC Evo4g: layout-hdpi-960x540

res/layout/ 폴더를 더더욱 구분하여 스마트폰의 해상도별 xml을 나눌뿐만 아니라
태블릿도 구분할수 있게되었어요(원래 그랬던건지..그냥 새로 만들어준건지는 나도몰라아아아)


res/layout/main_activity.xml          -> 스마트폰
res/layout-sw600dp/main_activity   -> 7인치 태블릿
res/layout-sw720dp/main_activity   -> 10인치 태블릿


public class MyActivity extends Activity 
{
@Override
protected void onCreate(Bundle savedInstanceState) 
{
super.onCreate();


Configuration config = getResources().getConfiguration();


if (config.smallestScreenWidthDp >= 600) 
{
setContentView(R.layout.main_activity_tablet);
} else {
setContentView(R.layout.main_activity);
}
}
}


—리소스포더이름으로구분처리
서로다른스크린의리소스관리
 - res/layout/my_layout.xml
Normal스크린사이즈레이아웃
 - res/layout-small/my_layout.xml
Small 스크린사이즈레이아웃
 - res/layout-large/my_layout.xml
Large 스크린사이즈레이아웃
 - res/drawable-ldpi/my_icon.png
Low density를위한아이콘
 - res/drawable-mdpi/dpi/my_icon.png
MediumDensity를위한아이콘
 - res/drawable-hdpi/my_icon.png
High Density를위한아이콘
 - res/drawable-nodpi/composite.xml
Density 와무관한리소스

* 밀도(Density)
 스크린해상도를기반으로물리적인넓이와높이안에얼마나많은픽셀이들어있는가를나타낸다. Lower density의스크린에서는같은넓이와높이안에더적은수의픽셀이있고, higher density의스크린에서는같은넓이와높이안에더많은수의픽셀이있다. 안드로이드는밀도를high, medium, low 세가지분류로나눈다. 플랫폼에서는실제스크린밀도에맞게리소스들의사이즈를조정한다.
Density-independent pixel (dip)
밀도와상관없이레이아웃의위치를표현할때사용하는가상의pixel 단위. Density-independent pixel 은기본밀도인160dip에서의물리적인 pixel과같다.
픽셀변환공식 pixels = dips * (density / 160)

아...저 토나오는 광경...같은게 하나도 없는 물건들...


갤럭시 노트
해상도  :  1280 * 800
Density  :  xhdpi
크기  :  5.3인치(large screen)
OS  :  Android 2.3 갤럭시 S2
해상도  :  800 * 480
Density  :  hdpi
크기  :  4.3인치(normal screen)
OS  :  Android 2.3  갤럭시 탭 10.1
해상도  :  1280 * 800
Density  :  mdpi
크기  :  10.1인치(xlarge screen)
OS  :  Android 3.0

참조 : http://sptraulyo.tistory.com/447

2012년 7월 6일 금요일

2012년 7월 4일 수요일

[Android] adb shell dumpsys


커맨드 창에 다음과 같이 입력하면 디바이스에 대한 자세한 정보를 확인 할 수 있다.
adb shell dumpsys
추가로 dumpsys 뒤에 옵션을 지정해 표시할 정보를 제한 할 수 있다. 
또한 dumpstate 도 있으니 디버깅에 유용하게 사용 하자.



dumpsys
  dumpsys는 안드로이드 폰의 어플리케이션 및 현재 기기의 상태에 대한 자세한 정보를 제공한다.
  (소스코드 위치: ./frameworks/base/cmds/dumpsys/dumpsys.cpp)

  dumpsys meminfo: 메모리 사용 정보를 표시
  dumpsys cpuinfo: CPU 프로세서 사용 정보를 표시
  dumpsys account: 모든 계정에 대한 정보를 표시
  dumpsys activity: Activity에 대한 정보를 표시
  dumpsys window: 키보드와 윈도우, 그리고 그들의 z order에 대한 정보를 표시
  dumpsys wifi: 접속 가능한 액세스 포인트와 현재의 연결 상태를 표시
  dumpsys power: 전원 관리와 관련된 정보(wakelock, screen off time 등)를 표시

dumpstate
  dumpstate는 device 상태정보를 추출하는 여러 명령어들의 조합으로 구성 (dumpsys를 포함)
  (소스코드 위치: ./frameworks/base/cmds/dumpstate/dumpstate.c)

  Usage: dumpstate  [-d]  [-o  file]  [-s]  [-z]
            -d: 파일 이름에 날짜 정보를 추가 (-o 옵션과 함께 사용)
            -o: 파일에 기록 (screen에는 표시하지 않음)
            -s: 결과를 콘솔 소켓에 기록
            -z: gzip 압축하여 파일로 기록 (-o 옵션과 함께 사용)

[안드로이드] SD 존재 확인

출처 : http://www.androes.com/141


일반적으로 외장카드 영역을 불러올때 /mnt/sdcard 이런 식으로 하드 코딩하시는 분들이 많은데
이런 경우 외장카드를 사용하지 않는 사용자인 경우 에러가 발생하게 됩니다.

사용자 폰에 외장카드 존재유무를 확인하여 처리하는 모듈을 간단히 구현해 봤으니 참고하세요!!

        String mSdPath;
        String ext = Environment.getExternalStorageState();
        if (ext.equals(Environment.MEDIA_MOUNTED)) {
            mSdPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/";
        } else {
            mSdPath = Environment.MEDIA_UNMOUNTED+"/";
        }
        File file = new File(mSdPath);
        if (!file.exists()) mSdPath = "";       

        // 파일 생성
        BufferedWriter out = new BufferedWriter(new FileWriter(mSdPath+"androes.txt"));
        out.write("test text messages");
        out.newLine();
        out.close();

        // 파일 삭제
        File file = new File(mSDPath + "/" + "androes.txt");
        file.delete();


2012년 6월 25일 월요일

[MAC] 맥 폰트가 흐릿한 경우 해결법

맥 폰트 흐릿한 문제

http://clien.career.co.kr/cs2/bbs/board.php?bo_table=cm_mac&wr_id=458305

[MAC] 맥 한글 폰트 바꾸기

맥 한글 폰트는 정말 눈아프다 -ㅁ-;;
이렇게 바꿔 보자

http://blackturtle.tistory.com/711488

2012년 6월 24일 일요일

[Mantis] 첨부파일 용량 늘리기

php의 업로드 용량 조정 또는 mysql의 용량 조정으로 해결 할 수 있다.

http://www.manghon.com/blog/628

[MAC] MAC에 PATH 추가 하기

MAC에 PATH 추가 하기

http://underclub.tistory.com/454

그리고 좋은거 배웠다~
open XXX
명령어로 텍스트 편집기를 열 수 있다는 사실~

2012년 5월 24일 목요일

[안드로이드] /system 디렉토리를 쓰기용으로 마운트 하기


당연히 루팅되어 있어야 합니다.

그리고 커맨드 창에서 adb shell로 쉘 진입후,
su 등으로 루트권한 확보 후

mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system


요래 하면 됩니다.

2012년 5월 8일 화요일

[안드로이드] 부팅시간? 켜진시간??


public static final String ACTION_BOOT_COMPLETED

안드로이드가 껐다 켜지면 위와 같은 액션을 브로드케스트 리시버를 달아 받을 수 있다.
하지만 피치 못할 사정으로 브로드케스트 리시버를 사용 할 수 없다면?

SystemClock에 다음과 같은 두 메쏘드가 있다.

static long elapsedRealtime()
딥슬립 시간을 포함한 부팅 후 경과한 시간을 밀리초 단위로 리턴함.

static long uptimeMillis()
딥슬립 시간을 제외한 부팅 후 경과한 시간을 밀리초 단위로 리턴함.

uptimeMillis()의 경우는 딥슬립 시간을 제외 하니 다른 용도로 써야겠고..
elapsedRealtime()을 쓰면 될듯 하다. System.currentTimeMillis() - elapsedRealtime()하면 부팅 시간이니 말이다.

가령 shared_prefernce 등에 시간을 저장해 두고
OnCreate()에서 그값을 읽어와 부팅시간과 비교해
값이 적다면 새로 부팅한거니 그에 따른 처리를 한뒤 shared_prefernce에 다시 값을 넣어 주고,
값이 더 크다면 아무 것도 하지 않으면 된다.

물론 BOOT_COMPLETED를 받아야만 하는 경우도 있겠지만, 단순히 우리 어플리케이션이 안드로이드가 부팅되고 처음 실행 되는 건지 아닌지 정도는 구분할수 있다.

2012년 4월 17일 화요일

[안드로이드] SD 마운트-탈착에 관한 인텐트



SD 카드에 관련한 작업을 하다보면 예외적인 상황을 고려하지 않을 수 없다. 작업중에 강제로 SD카드가 뽑히거나, USB 연결등으로 마운트 해제가 될수도 있기 때문이다. 그러한 경우 다행히 Broadcast가 날라 오므로 필요에 맞게 받아 처리 할 수 있다.
  • Intent.ACTION_MEDIA_MOUNTED
SD 카드가 마운트 되면 날라옴
  • Intent.ACTION_MEDIA_EJECT
SD 카드가 강제로 뽑히거나 유저가 마운트 해제 하였을때 날라옴
  • Intent.ACTION_MEDIA_UNMOUNTED
유저가 마운트 해제 하였을때 날라옴
  • Intent.ACTION_MEDIA_REMOVED
SD 카드가 장치에서 제거 되었을때 날라옴
  • Intent.ACTION_MEDIA_BAD_REMOVAL
유저가 마운트 해제 하지 않은체 SD 카드가 강제로 뽑혔을때 날라옴

실제로 SD카드를 강제로 뽑아 보면 다음 순으로 발생 함
Intent.ACTION_MEDIA_BAD_REMOVAL -> Intent.ACTION_MEDIA_EJECT

마운트 해제 하면 다음 순으로 발생함
Intent.ACTION_MEDIA_EJECT -> Intent.ACTION_MEDIA_UNMOUNTED

SD 카드를 새로 꼽으면 다음 순으로 발생함
Intent.ACTION_MEDIA_UNMOUNTED -> Intent.ACTION_MEDIA_MOUNTED
희안하게도 언마운트가 먼저 호출되니 처리시 주의가 필요함

참고로 위 인텐트들을 등록 할 때는 아래와 같이 Data scheme을 지정해 줘야 한다.
<receiver android:name=".TestBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_EJECT" />
        <action android:name="android.intent.action.MEDIA_BAD_REMOVAL" />
        <action android:name="android.intent.action.MEDIA_MOUNTED" />
        <action android:name="android.intent.action.MEDIA_REMOVED" />
        <action android:name="android.intent.action.MEDIA_UNMOUNTED" />
        <data android:scheme="file"></data>
    </intent-filter>
</receiver> 

[안드로이드] 브로드케스트리시버 동적으로 등록/해지 하기

브로드케스트 인텐트를 받기 위해
보통 AndroidManifest.xml 파일에 리시버를 등록 하곤 한다.
이렇게 하면 해당 브로드케스트가 발생하면 항상 실행되게 되는데, 기능에 따라 On/Off 를 하고 싶을 경우가 있다.
뭐 그런 경우 브로드케스트 리시버에서 처리를 안해도 되지만 아예 꺼버린다면 여러모로 효율이 좋게된다.

* 먼저 브로드케스트 리시버를 등록 하는 법
// 인텐트 필터 생성
IntentFilter filter = new IntentFilter();
filter.addAction("com.hermina.broadcast.TEST");
// 브로드케스트 리시버 등록
registerReceiver(reciever, filter);
물론 reciever는 등록할 BroadcastReciever 이며
다룰 인텐트에 따라 필터를 좀더 명확 하게 설정할 수 있다.
filter.addCategory
filter.addDataType
filter.addDataScheme
* 해지 하는법
unregisterReceiver(reciever);

2012년 4월 3일 화요일

[안드로이드] 테마 적용 + 배경이 투명한 액티비티 만들기

안드로이드 ICS가 출시 되면서 Holo.Light 테마가 생겨 났다.
그러한 테마를 적용 하면서 투명 액티비티를 띄우면 투명 액티비티만 테마가 후리다;;;

인터넷에서 찾아 보면 투명 액티비티를 만드는 테마는 다음과 같다.
<activity android:name="Test" android:theme="@android:style/Theme.Translucent">
물론 잘 동작 한다.
하지만 위에서 적었듯이 투명 액티비티에서 보여지는 위젯들은 테마가 적용이 않된 후린 기본 스타일로 보여지게 된다.

내 경우 다이얼로그를 띄워야 하는데 다른 다이얼로그는 테마가 적용 됬는데 투명액티비티에서 띄우는 녀석만 미운오리새끼 같다.

그럼 어떻게 해야 하는가!!

일단 테마를 만듭니다.
project/res/values/themes.xml 을 추가 하면 된다.
다음과 같이 themes.xml파일의 내용을 체운다.
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="Translucent_Dialog" parent="@android:style/Theme.Holo.Light.Dialog.NoActionBar">
        <item name="android:windowBackground">@android:color/transparent</item>        
    </style>

</resources>
이미 themes.xml 파일이 있다면 style 항목만 추가 하면 되겠죠?

style 에서 "parent" 부분이 상속받을 스타일이고 "item" 으로 배경을 투명하게 지정 한것이다.
사실 "@android:style/Theme.Holo.Light.Dialog.NoActionBar" 테마는 투명액티비티에 필요한 "NoActionBar"라던가 "Dialog"라던가 하는 스타일이 거의 지정 되어 있다.
현재 사용하는 테마 스타일이 다른것이라면 아래와 같은 속성을 추가해 타이틀과 액션바를 없애줘야 할 것 이다.
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
테마가 적용된 투명한 새로운 테마를 생성하였으면 이를 액티비티에 적용해 줘야 한다.
"AndroidManifest.xml" 파일을 열어 투명효과를 적용할 액티비티에 다음과 같이 테마를 지정해 준다.
<activity
    android:name=".TrasparentTestActivity"
    android:label="@string/app_name"
    android:theme="@style/Translucent_Dialog" >
이렇게 하면 투명한 액티비티 생성 완료~

2012년 3월 22일 목요일

[안드로이드] 사용자 정의 permission의 선언

------------ 요기는 삽질 내용입니다. permission의 선언법만 궁금하시면 넘어가세요.
간단한  ContentProvider를 테스트 하기 위해 샘플 프로젝트를 만들어 보았다. 액티비티 하나,  ContentProvider  하나. 이 App를 CPTestApp1 이라 명명해 보았다.

<provider
            android:name="TestContentProvider"
            android:authorities="com.hermina.testcontent">
</provider>


잘동작한다.

이번엔 신규 App CPTestApp2를 생성해 CPTestApp1에서 만든  ContentProvider를 사용해 보기로 하였다.
뭐 잘 된다.

이번엔 CPTestApp1의 ContentProvider에 permission을 지정 해 보았다. 기왕 하는거 퍼미션명도 다르게 지정해 보았다.

<provider
            android:name="TestContentProvider"
            android:authorities="com.hermina.testcontent"
            android:readPermission="com.hermina.permission.CP_READ" >
</provider>



그리고 나서 CPTestApp2에 해당 권한을 넣어 준다.
<uses-permission android:name="com.hermina.permission.CP_READ"/>

젠장 이번엔 안된다.
"com.hermina.testcontent"에 접근 하려면 "com.hermina.permission.CP_READ"권한이 있어야 한다는데...

이쯤에서 인터넷 검색해보고 별짓 다해봤다. ContentProvider에 관련된 자료와 책을 보고 또보고 다른 소스 코드들을 열심히 보았지만 이유를 몰랐다.
그러던중 <permission android:name="xxx.xxxxxx.xxxxx" /> 를 발견하게되고...
분을 삭힐수 있게 되었는데...
어릴땐 책을 사면 아까워서 글자 한톨 그림 구석구석 정독을 했었다. 하지만 언제부턴가 책을 사도 빠르게 필요한 부분만 뽑아 보게 되었다. 내가 만약 안드로이드 permission에 관해 먼저 자세히 알고 있었다면 이런 한심한 삽질은 하지 않았으랴...

------------ 본론입니다.
안드로이드에서 사용자 정의 퍼미션을 선언하는 방법은 다음과 같다.

<receiver android:name=".NewPhotoReceiver">

컨텐트 프로바이더에서 해당 퍼미션을 사용 하려면 다음과 같이 하면 되고

<provider
            android:name="TestContentProvider"
            android:authorities="com.hermina.testcontent"
            android:readPermission=" xxx.xxxxxx.xxxxx " >
</provider>


이를 사용 하는 어플리케이션에서 해당퍼미션을 허용하려면

<uses-permission android:name=" xxx.xxxxxx.xxxxx "/>

처럼 사용 하면 된다.