Android2015. 4. 3. 17:24

모든 파일에서 텍스트 찾기: ctrl + shift + f

해당부분 자동 완성(임포트, 인터페이스 자동 구현 등): alt + enter

정의 된 위치로 이동: ctrl + b

어디에서 사용되어지고 있는지 찾기: alt + f7

모두 찾기: shift + shift

실행: shift + f10

액션 찾기: ctrl + shift + a

이름바꾸기: shift + f6

파라미터 보기: ctrl + p

생성하기(생성자, 세터, 게터등..): alt + insert

자동 임포트: ctrl + alt + o

현재 에디터(클레스)에서 찾기: ctrl + f12

추가1 Android Studio(intelliJ) 의 단축키가 불편하다면 File>Setting>keymap>keymapss 에서 Eclipse등 주로 사용하는 개발툴 단축키로 변경 가능합니다.

추가2 help>Default keymap Reference 메뉴를 클릭하시면 Android Studio(intelliJ) 의 모든 단축키에 대한 설명을 PDF 파일로 다운받을 수 있습니다.

Posted by 위푸
Android2014. 7. 8. 19:52

안드로이드 NDK를 개발할 때 다른 기능 개발을 위해 따로 프로젝트를 나누거나 기존에 개발되어있는 NDK 라이브러리를 가져와서 쓰고 싶을 때가 있습니다.
이때 다른 프로젝트에서 개발된 .so 파일을 이용하여 프로젝트를 개발하려는 경우 빌드설정 방법에 대하여 공유합니다.

1) 개발하려는 프로젝트의 jni폴더에 다른 프로젝트에 개발된 .so파일을 넣어둘 폴더를 생성하고 생성한 폴더에 .so파일을 복사합니다. 그리고 라이브러리를 사용하기 위한 .h(해더파일)을 복사합니다.
2) .so파일을 복사한 폴더에 Android.mk파일을 만든후 아래와 같이 Android.mk에 입력합니다.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libexttest
LOCAL_SRC_FILES := libexttest.so
include $(PREBUILT_SHARED_LIBRARY)

3)실제 NDK소스를 빌드할 폴더의 Android.mk 파일에 사용할 라이브러리를 명시해 줘야됩니다. 아래와 같이 입력합니다.
LOCAL_C_INCLUDES :=  $(call my-dir)/libexttest
LOCAL_LDLIBS := -L$(call host-path, $(PROJECT_PATH)/libexttest) \
               -lexttest

실제로 NDK 빌드가 정상적으로 된다면 성공한 것입니다. 여기서 중요한 것은 2)번의 include $(PREBUILT_SHARED_LIBRARY)입니다.

Posted by 위푸
Android2014. 4. 6. 13:18

ListView 2개를 ScrollView로 감싸서 ListView2개가 ScrollView 높이를 초과하게 되면 스크롤 되어 보여지게 UI를 구성했습니다.

문제는 ListView 2개의 heigh를 wrap_content나 match_parent를 주고 ScrollView로 감싸게 되면 ScrollView에서는 ListView의 height를 제대로 인식하지 못해서 ScorllView안의 ListView들이 제대로된 height 만큼 표시되지 않고 잘려서 표시되게 됩니다.

그렇다고 ListView에 heigh를 고정 크기로 지정해주게 되면 정작 ListView의 아이템 개수에 맞게 ListViewt를 표시 할수 없는 문제가 생깁니다.

그래서 ListView를 제대로 표시할 수 있는 방법을 찾아보니 ListView의 초기화 및 Item(data)을 갱신한후 ListView의 height를 계산하여 ListView에 LayoutParams을 설정하는 방법이 있더군요 이방법을 적용해보니 ListView가 제대로 표시되고 스크롤도 가능하게 됩니다.

소스코드를 공유 하자면

protected void onCreate(Bundle savedInstanceState) {
        ListView listview1 = (ListView) view.findViewById(R.id.list1);
        ArrayAdapter<Data> adapter = new ArrayAdapter<Data>(this, R.layout.simple_list_item, listData1);
        listview1.setAdapter(adapter);

        ListView listview2 = (ListView) view.findViewById(R.id.list2);
        adapter = new ArrayAdapter<Data>(this, R.layout.simple_list_item, listData2);
        listview2.setAdapter(adapter);

        setListViewHeightBasedOnChildren(listview1);
        setListViewHeightBasedOnChildren(listview2);
}

public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter(); 
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
}

리스트 뷰가 갱신될때 setListViewHeightBasedOnChildren() 호출을 하게 되면 ListView를 ScrollView로 감싸게 UI를 구성하더라도 ListView 정상적으로 표시되고 스크롤이 되게 됩니다.

 

Posted by 위푸
Android2013. 6. 13. 20:34

Drawable에 Image(bitmap)를 가져와서 지정해주고 colorFilter를 지정해 주면 bitmap에 ColorFilter가 적용된 Drawable을 이용하여 view에 배경을 지정해 줄 수 있습니다.

보통의 경우

BitmapDrawable bd = new BitmapDrawable(bitmap);
view.setBackgroundDrawable(bd );


위와 같이 적용하면 되는데
아래와 같이 stateDrawable을 사용하여 배경을 지정해 주게 되면 ColorFilter가 적용되지 않은 원본 bitmap 배경이 지정되는 문제가 생깁니다.

BitmapDrawable bd = new BitmapDrawable(bitmap);
StateListDrawable stateDrawable = new StateListDrawable();
stateDrawable.addState(new int[]{-android.R.attr.state_pressed}, bd);
view.setBackgroundDrawable(stateDrawable); 

그러하여 위와 같은 문제를 해결하기 위해서

Bitmap orgBitmap = getResources().getDrawable(id);
paint = new Paint();
Bitmap copyBitmap = Bitmap.createBitmap(orgBitmap.getWidth(), orgBitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(copyBitmap);
canvas.drawBitmap(orgBitmap, 0, 0, paint);
BitmapDrawable bd = new BitmapDrawable(copyBitmap);
StateListDrawable stateDrawable = new StateListDrawable();
stateDrawable.addState(new int[]{-android.R.attr.state_pressed}, bd);
view.setBackgroundDrawable(stateDrawable);

위와 같이 ColorFilter를 적용하여 새로 만든 Bitmap에 그리고 StateListDrawable에 새로 만든 bitmap을 지정한 Drawable을 적용하게 되면 StateListDrawable을 사용하게 되도 ColorFilter가 적용된 배경이 보여지게 됩니다.

 

 

Posted by 위푸
Android2013. 5. 31. 18:30

NetworkOnMaintThreadeEception 이 발생하는 원인이 여러가지 있겠지만 그 중 한가지로 안드로이드 3.0(honeycomb) 부터 기본적으로 수행되는  StrictMode때문에 발생할 수 있습니다. App이 실행되는 os가 honeycomb이하의 경우는 정상정으로 실행되나 honeycomb이상의 os부터는 NetworkOnMaintThreadeEception 이 발생 하면서 App이 정상 동작을 하지 않는 이유입니다.

Android에서  Strict Mode 도입하게 된 이유나 사용법에 대해서는 아래 블로그 참조 

http://dev.kthcorp.com/2012/01/31/android-strict-mode-howto/


NetworkOnMaintThreadeEception을 처리하기 가장 좋은 방법은 mainThread에서 하는 네트워크 관련 작업등 mainThread에서 오래 실행되는 작업을 새로운 Thread를 통하여 실행되게 수정하는 것이 가장 좋은 방법입니다.  

아래 블로그 참조

http://ironheel.tistory.com/48

http://ralf79.tistory.com/85


이외에 Thread 분리 작업이 너무 많아져서 임시로 NetworkOnMaintThreadeEception을 처리하고 싶은 경우는 아래의 코드를 Activity의 onCreate()에 넣어주시면 NetworkOnMaintThreadeEception가 발생되지 않습니다. 

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

중요한 점은 임시로 처리 하는 방법이기 때문에 오래 실행되는 작업은 mainThread와 따로 Thread를 분리하는 방법으로 Exception을 처리하는걸 권장합니다.

Posted by 위푸
Android2011. 6. 7. 09:35
Android에서 View의 크기를 알아오고 싶을때 일반적으로

 view.getWidth();
 view.getHeight();
위의 api를 써서 원하는 view의 크기를 얻어 옵니다.
위의 방법은 View가 onDraw를 통하여 화면에 그려 졌을 경우에 크기를 얻을 수 있습니다. 만약 그전에 위의 api를 호출하게 된다면 0값을 얻어오게 됩니다.

만약 onDraw전에 View에 크기를 알고 싶은 경우에는
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 
view.getMeasuredWidth();
 view.getMeasuredHeight();
위의 api를 사용하면 됩니다.
여기서 중요한 것은 view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED) 메소드 인데 이 메소드를 통하여 view의 부모에게 크기를 위임하여 알아오게 해줍니다. 위 메소드의 파라미터로 넘겨지는 MeasureSpec은

MeasureSpec.AT_MOST : wrap_content 에 매핑되며 뷰 내부의 크기에 따라 크기가 달라진다.
MeasureSpec.EXACTLY : fill_parent, match_parent 로 외부에서 미리 크기가 지정되었다.
MeasureSpec.UNSPECIFIED : Mode 가 설정되지 않았을 경우. 소스상에서 직접 넣었을 때 주로 불립니다.

위와 같은 설정을 지원해줌으로 원하는 설정값을 넘겨주시면 됩니다.

도움이 되셨으면 좋겠네요~ ^^
Posted by 위푸
Android2010. 11. 30. 00:37

토요일날에 테이크폰 구매하게 되서 지금까지 써보다 테이크폰에 대해서 많은 분들이 궁금하실꺼 같아서 간단하게 스크린 샷하고 나름 느낀점을 써볼까 합니다. 개인적인 주관이 담겨있는 글이겠지만 구매하시는데 조금이나마 도움이 되었으면 좋겠네요 ㅎㅎ



위에 화면은 테이크 바탕화면 입니다. 일단 터치감은 굉장이 괜찮은거 같습니다 안드로이드 폰중에 굉장히 괜찮은 터치감을 보이는 것 같네요. 위에 보이는 것처럼 테이크는 특이한 홈(Luncher)로 구성되어 있는데요 아래에 왼쪽부터 3칸은 사용자가 이용하기 편한 어플로 변경이 가능합니다. 그리고 좋은 기능중 하나가 설정에서 스크린샷 찍기를 체크하시면 옵션 버튼을 길게 누를때 화면을 찍어주는 기능을 쓸수 있습니다. 옵티머스에도 있는 기능인데 개인적으로 편리한 기능인것 같습니다. 3번째 화면에는 뮤직 플레이어 위젯이 있네요 참 단순합니다ㅎㅎ 제가 지금까지(몇일 안되었지만)써본 결과로는 테이크의 홈은 지금까지 나온 안드로이드 폰중에 가장 잘만든 홈중에 하나가 아닐까 하네요.

음.. 단점으로는 홈이 가끔은 좀 버벅임 같은 느낌이 들때도 있다는거... ㅡ.ㅡ













































테이크의 메뉴 화면입니다. 갤럭시와 같이 좌우로 넘겨가면서 어플들의 아이콘을 표시해줍니다. 3번째 화면은 편집 화면입니다. X표시를 누르면 어플들을 삭제하실 수 있습니다. 1,2번째 화면을 보면 은근 KT 내장 어플들이 많이 포함되어 있고 아쉽게도 삭제가 불가능 하게 되어 있네요.

























위 화면은 테이크의 기본 뮤직 플레이어 입니다. 상당히 깔끔하게 되어 있는데요. 기본 뮤직플레이어 치고 나름데로 쓸만 하지 않을까 생각되네요. 뮤직플레어의 기본기능은 다되고 이퀄라이저 기능까지 지원합니다. 깔금한게 은근 마음에 드네요 ㅎㅎ

























위 화면은 음악 플레이중에 노티영역을 내렸을 때에 화면입니다. 노티영역에서 뮤직플레이어를 컨트롤할 수있게 지원해주는게 마음에 드네요
























위 화면은 테이크 기본 어플중에 시계 어플과 작업관리자 어플입니다. 시계어플은 특별할껀 없구.. 작업관리자 어플은 따로 내장하고 있어 프로그램 관리 하기 편리하고 좋네요~

락스크린도 찍어서 올리려구 했는데 안찍혀서 못올리네요ㅠ.ㅠ  락스크린에 여러가지 기능을 스클되게 해서 락스크린이 해제 되었을 때 바로 바로 실행시켜주는 기능은 참 좋더라구요... 음악이 재생되고 있으면 스크린에 표시해주는 기능도 좋구요~

이외에도 여러가지 기능들이 많은데 이정도로 정리 할까 하네요. 제가 예전에도 KT Tech의 피처폰을 써봤는데 KT Tech폰은 사용자들의 편의를 위한 기능들을 상당히 많구나 했었는데 이번 테이크도 역시나 입니다 ㅎㅎ

현재까지 쓰면서 단점이라고 한다면 도시락 어플의 오류, 올레마켓의 엄청나게 느린 속도, 배터리가 생각보다 빨리 소모되는점 외에는 모든 면에서 현재까지 나온 안드로이드 폰들중에 최고중 하나라고 생각하네요 특히 런처(홈), 락스크린, 사용자 편의 기능에 있어서는 정말 최고인듯!!!

현재 중고가? 프리미엄급의 스마트폰 치고는 가격이 싸게 나온 것으로 아는데 사서 써보시면 후회하지 않으실꺼라고 생각합니다!!

Posted by 위푸
Android2010. 8. 13. 09:23

ImageView에 테두리를 넣는 방법이 필요하신 분이 있으실 것 같아서 공유합니다.
이 방법 외에도 다른 방법도 있을 것 같으니 참고 하시는 정도로 보시면 좋을 것 같습니다.

테두리가 없는 AlarmClcok의 이미지를 ImageView에 표시한 화면입니다.
 

ImageVIew에 테두리를 넣기위해서 ShapeDrawable을 이용합니다.
ShapeDrawble는 코드로 간단하게 색을체우거나 그라데이션 효과를 줄 수있는 기능을 제공합니다.
자세한 사항은 http://www.androidpub.com/2113 을 참고하세요

ShapeDrawble을 ImageVIew에 사용하기 위해서 image_border.xml을 만들어서 Drawable 폴더에 넣습니다.
 image_border.xml의 소스 입니다.
 <?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <solid android:color="#0fff"/>
    <stroke android:width="1px" android:color="#ffaeaeae" />
    <padding android:left="1px" android:top="1px"
            android:right="1px" android:bottom="1px" />
</shape>
간단하게 설명하면 solid는 해당 View를 채우는 설정입니다.
stroke는 View의 테두리를 설정해줍니다. padding은 view의 padding값을 설정해 줍니다.
위의 ShapeDrawable을 테두리를 설정해줄 ImageView에 지정을 해줍니다.

 해당 ImageView 소스입니다.
 <ImageView
     android:id="@+id/border_image"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
     android:src="@drawable/image_border"
     android:background="@drawable/clockdroid2_dial" />     

위의 소스를 적용한 화면입니다.


위의 화면과 같이 ImageView에 테두리가 들어간것을 확인 하실수 있습니다.
위에서와 같이 xml에 ShapeDrawable을 설정하지 않고 코드상에서 설정 하실수도 있습니다.
 ImageView iv = (ImageView)findViewById(R.id.border_image);
  Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.clockdroid2_dial);
  iv.setBackgroundResource(R.drawable.image_border);
  iv.setImageBitmap(bitmap);

도움이 되셨으면 좋겠네요~

Posted by 위푸
Android2010. 8. 9. 11:30

GridView에 View를 생성하여 넣으면 GridView가 보여질때 상하좌우에 여백이 있는 것을 보실수 있습니다.


이렇게 GridView의 background에 white color를 지정하여 보면 white color의 여백이 남는 것을 볼수 있습니다.
이 여백을 없에기 위해 margin이나 padding을 아무리 주어도 없어지지 않는데요 여백을 없에기 위해서 몇일을 찾아 본 결과 list selector에 padding이 지정되어 있어서 여백이 생기게 된다는 것을 알게 되었습니다.

혹시나 저 같이 GridView에 여백을 없에기위해 고민하시는 분을위해 여백을 없에는 방법을 공유합니다.
방법은 GridView에 listSelector에 있습니다.

GridView는 AbsListVIew를 상속받게 되어 있는데요 이 AbsListView에 기본으로 지정되어 있는 listSeletor에 padding이 들어가 있어서 GridView에 여백이 생기게 됩니다.
GridView에 여백을 없에기 위해서는 GridView에 listSelector속성에 padding을 제거한 selector를 지정하면 됩니다.

padding을 제거하기 위한 selector xml의 소스 입니다.

 <selector xmlns:android="http://schemas.android.com/apk/res/android"
 android:variablePadding="false">  
</selector>
위의 소스를 list_selector.xml로 저장하여 drawable 폴더에 넣으신 후
GridVIew의 listSelector 속성에 위에 XML을 지정하시면 됩니다.
http://developer.android.com/guide/topics/resources/drawable-resource.html 의 XMLBitmap 부분을 참조하시면 selector를 xml로 설정하는 것에 대한 설명이 나와있습니다.

GridView에 listSelcotr속성을 적용한 소스 입니다.
 <GridView
      android:id="@+id/anim_grid"   
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:stretchMode="columnWidth"
      android:listSelector="@drawable/list_selector"
      android:background="#ffff" />

이렇게 적용하여서 실제로 보게되면 여백이 없어지는 것을 확인할 수 있습니다.


안드로이드의 가장 좋은 공부방법은 풀소스 분석과 Developer 사이트의 Guide를 보는것과 Reference를 꾸준히 익히는 것이라고 생각되네요
-----------------------------------------------------------------------------------------------------------------

추가로 안드로이드 api를 직접 호출하여 여백을 없에는 방법입니다. (진작 올렸어야되었는데 많이 늦었네요.. ㅜ.ㅜ)

gridView.setSelector(new StateListDrawable()); 

GridView의 setSelector를 호출하시면 쉽게 여백을 제거 할수 있습니다.

Posted by 위푸
Android2010. 1. 3. 15:25
Android API에서는 데이터 베이스의 데이터 값이 변경되었을경우 Notifications을 제공해주는 ContentObserver라는 API를 제공하여 줍니다.  

- 사용법 예제 소스입니다.

public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

// 해당 데이터베이스의 데이터값이 변경시에 onChange() method가 호출됩니다.
private ContentObserver bookmarksObserver = new ContentObserver(new Handler()) {
     @Override
     public void onChange(boolean selfChange) {
          super.onChange(selfChange);
          Log.d("Boookmarks", "onChanged : " + selfChange);
     }
};

// ContentObserver에 해당 데이터 베이스의 URI를 등록합니다.
private BookmarksManager(Context context) { 
     this.context = context;
     this.contentResolver = context.getContentResolver();
     contentResolver.registerContentObserver(BOOKMARKS_URI, true, bookmarksObserver );
}

// 해당 Manager Class가 소멸될경우 꼭 ContentObserver에서 해제 시켜주어야 합니다
public static void destroy() {
     if (instance != null && instance.contentResolver != null && instance.bookmarksObserver != null) {
          instance.contentResolver.unregisterContentObserver(instance.bookmarksObserver);
     }
     instance = null;
}
Posted by 위푸