반응형


android 2.3 gingerbread 등에서 layout hierarchy가 너무 중첩돼 있으면, StackOverflowError가 난다.

android 3 이상에서는 잘 나지 않는 것 같다.

따라서, 레이아웃을 최소화 하는 것이 관건..!!
하위 레이아웃이 많이 겹쳐있으면 에러 발생..

에러 발생하는 레이아웃에서 중첩되는 레이아웃을 하나씩 주석처리하고 실행해보자.
그러면 어느 레이아웃 때문에 에러가 발생되는지 알 수 있음..

You have (way) too many nested layouts. You can check out the official Android blog at d.android.com to get tips and tricks on how to optimize layouts.

You have too many nested viewgroups (see: java.lang.StackOverFlow error. Suspected too many views? for tips on how to reduce some of them) 

반응형
,
반응형

ConnectivityManager manager =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo mobile = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
     
    if (mobile.isConnected() || wifi.isConnected()) {
        // Connected 연결됨
         
        return true;
    } else {
        // Disconnect 연결 안됨
        Dialog dialog = new Dialog(getBaseContext());
        dialog.setContentView(R.layout.internet);
        return false;
    }


반응형
,
반응형

키보드에서 특정 키를 꾹 누르고 있으면 그 키에 해당하는 문자가 계속 타이핑 되듯이 

안드로이드에서도 특정 버튼을 누르면 어떠한 액션이 반복적으로 실행되는 리스너를 찾아보았습니다. 

 

원본 링크 : http://stackoverflow.com/questions/4284224/android-hold-button-to-repeat-action

 

이곳에 보면 버튼 반복 방법이 두가지 나오는데요, 첫번째 보다 두번째 방식이 더 간결하고 쓰기 좋습니다.

(첫번째 방법은 버튼 셀렉터 먹이기가 힘들더군요 ㅇㅁㅇ;)

 

일단 RepeatListener.java 를 생성합니다.

 

import android.os.Handler;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.View.OnTouchListener;

 

/**

 * A class, that can be used as a TouchListener on any view (e.g. a Button).

 * It cyclically runs a clickListener, emulating keyboard-like behaviour. First

 * click is fired immediately, next after initialInterval, and subsequent after

 * normalInterval.

 *

 * <p>Interval is scheduled after the onClick completes, so it has to run fast.

 * If it runs slow, it does not generate skipped onClicks.

 */

public class RepeatListener implements OnTouchListener {

 

    private Handler handler = new Handler();

 

    private int initialInterval;

    private final int normalInterval;

    private final OnClickListener clickListener;

 

    private Runnable handlerRunnable = new Runnable() {

        @Override

        public void run() {

            handler.postDelayed(this, normalInterval);

            clickListener.onClick(downView);

        }

    };

 

    private View downView;

 

    /**

     * @param initialInterval The interval after first click event

     * @param normalInterval The interval after second and subsequent click 

     *       events

     * @param clickListener The OnClickListener, that will be called

     *       periodically

     */

    public RepeatListener(int initialInterval, int normalInterval, 

            OnClickListener clickListener) {

        if (clickListener == null)

            throw new IllegalArgumentException("null runnable");

        if (initialInterval < 0 || normalInterval < 0)

            throw new IllegalArgumentException("negative interval");

 

        this.initialInterval = initialInterval;

        this.normalInterval = normalInterval;

        this.clickListener = clickListener;

    }

 

    public boolean onTouch(View view, MotionEvent motionEvent) {

        switch (motionEvent.getAction()) {

        case MotionEvent.ACTION_DOWN:

            handler.removeCallbacks(handlerRunnable);

            handler.postDelayed(handlerRunnable, initialInterval);

            downView = view;

            clickListener.onClick(view);

            break;

        case MotionEvent.ACTION_UP:

            handler.removeCallbacks(handlerRunnable);

            downView = null;

            break;

 

        case MotionEvent.ACTION_CANCEL:

            handler.removeCallbacks(handlerRunnable);

            downView = null;

            break;

 

        }

        return false;

    }

 


 

 

그후 onCreate()에 Button 리스너를 줍니다.

 

 ((Button)findViewById(R.id.btn)).setOnTouchListener(new RepeatListener(400, 50, new OnClickListener() {

  @Override

  public void onClick(View view) {

  //할 것!!

  }

}));

 

여기서 400은 처음 터치한 후 반복이 실행되기 까지의 대기시간, 50은 반복속도입니다. 자유롭게 주셔도 됩니다.


반응형
,
반응형

안드로이드 폰에서 기본으로 제공하는 기본 카메라 및 갤러리

불러보기 및 이미지 Bitmap 처리

 

Button btnCamera = (Button)FindViewById(R.id.btnCamera)

Button btnGallery = (Button)FindViewById(R.id.btnGallery)

 

카메라와 갤러리를 실행 할 버튼을 만든다!

위에 XML과 연결을 해준다~

 

카메라의 사진을 저장하기 위해선 저장할 경로가 필요하다.

 

cameraTempFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmp_image.jpg";

File imageFile = new File(cameraTempFilePath);
Uri imageFileUri = Uri.fromFile(imageFile);

 

저장할 파일 경로를 설정한다! (실질적으로 저장할 위치에 폴더가 존재하지 않으면 에러가 발생한다.

물론 임시파일사진도 저장되지 않는다.)

 

Intent intent = new Intent();

intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);                  
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);

 

startActivityForResult(intent, REQ_CAMERA_SELECT);

 

인텐트를 생성한다

어디로 가야할지 정해주고 위에서 설정했던 이미지저장할 파일경로를 적어 줍니다.

자 여기서 갤러리 불러오는 방법도!

 

intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
         
startActivityForResult(intent, REQ_GALLERY_SELECT);

 

스타트 엑티비티로 실행이 된 후 그 결과값을 처리해야한다.

그부분은 어디서 하는지 이제부터 시작한다 두둥!!

 

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  
 if(resultCode == RESULT_OK){


if(requestCode == REQ_CAMERA_SELECT{

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;

// (1,2,4,8 이렇게 지정함으로 원본사진의 반,1/4 로 옵션을 설정)
     
Bitmap mImageBitmap = BitmapFactory.decodeFile(cameraTempFilePath, options);

// 비트맵에 값을 가져와서 사용한다
      
 /* Tiny Image Returned : 섬네일 파일 읽기
mBackBitmap = (Bitmap) data.getExtras().get("data");
ourImageView.setImageBitmap(mBackBitmap);
 */

 

// To do 필요한 처리

}

if(requestCode == REQ_GALLERY_SELECT{

 

// 데이타를 받아와서

Uri currImageURI = data.getData();

Bitmap mImageBitmap = BitmapFactory.decodeStream(
       getContentResolver().openInputStream(currImageURI), null, options);

//To do 필요한 처리 

}

 

}

 

위에서 비트맵으로 이미지 데이타를 불러온 부분은 필요에 위해서 처리하면 된다.

중요한걸 빼먹을뻔  했네요~!

 

안드로이드 메니페스트 파일에서 카메라 사용 권한을 주셔야 합니다. 


반응형
,
반응형

가끔 컴파일은 잘 되는데 막상 실행할 때 

 

java.lang.NullPointerException 오류가 발생할 때가 있다.

 

그것은 변수에 null값이 들어있어서 그렇다.

 

자바는 변수값을 주소로 찾아가서 진짜값을 가지고 오게 되어있다.

 

우체국 아저씨는 변수값을 보고 진짜값을 찾아가는데 변수값이 없다면!

주소가 없다면!! 

우체국 아저씨는 주소가 없어서 못 찾겠다고 하소연을 할 것이다.


그것이 java.lang.NullPointerException이다.

 

보통 Parameter를 넘겨 받을 때 값이 안들어가서 생긴다.

 

해결 방법은 Parameter를 받을 때 디폴트 값을 가지면 된다.

 

Or

 

해당 인스턴스 선언할 때 초기화가 누락되었을 경우..

 

이 경우도 유심히 살펴보자!


반응형
,
반응형

나인패치(Nine-patch)란 무엇인가?

 

나인패치는 동적 비트맵 이미지입니다.

쉽게 말하면, 나인패치를 배경 이미지로 사용하면 안드로이드가 컨텐츠 크기에 따라서 자동적으로 사이즈를 조정합니다. 예를 들면 버튼의 경우에는 문자열 길이에 따라서 가변적으로 배경 이미지가 늘어나야 되는데, 나인패치를 사용하면 문자열 길이에 따라 이미지 크기가 자동적으로 늘어납니다.

 

나인패치는 가장자리에 1픽셀의 라인을 포함한는 표준 PNG 이미지로서 반드시 .9.png 확장자로 저장되어야 합니다. 

다음 그림을 보면서 설명드릴께요.

 

 

위의 그림에서 왼쪽과 상단 라인은 이미지 크기를 조정하는데 사용될 픽셀 영역을 지정합니다. 다시 말하면 크기가 늘어나야 되는 픽셀 영역을 지정합니다. 해당 픽셀은 연속적이지 않아도 되고 여러군데를 지정할 수 있습니다.

오른쪽과 하단 라인은 내용이 허용되는 공간을 지정합니다. 그래서 지정되지 않은 공간은 여백입니다. 내용이 가장자리나 모서리에 바짝 붙으면 보기 싫겠죠?ㅎㅎ

 

이제는 나인패치를 제작하는 도구와 방법을 알려드릴께요.

안드로이드에서는 "9 패치 도구"라는 위지윅 기능의 그래픽 편집기를 제공합니다. 내가 첨부한 파일을 다운받아 압축을 푸시고 사용하시면 됩니다.

그러나 이 도구를 사용하려면 반드시 컴퓨터에 JAVA가 설치 되어있어야 합니다.ㅎㅎ

 

 

 

 

나인패치 도구(Draw 9-patch) 사용방법

 

나인패치 이미지를 만들기 위해서는 PNG 이미지가 필요합니다.

 

1. 첨부파일을 다운받아 압축을 풀고 draw9patch.bat를 실행합니다.

 

 

2. PNG 이미지를 나인패치 도구 창으로 드래그앤드랍하거나 메뉴에서 File > Open 9-patch 를 클릭하여 PNG 이미지를 불러옵니다.

 

3. 마우스 왼쪽버튼으로 선을 그리고 오른쪽 버튼으로 선을 지우면 됩니다.

 

 

옵션 컨트롤은 다음과 같습니다 : 

 

  • Zoom그리기 영역에서 이미지를 확대하거나 축소합니다.
  • Patch scale미리보기 영역에서 이미지의 크기를 조정합니다.
  • Show lock: 이미지에 마우스를 올려놓으면 non-drawable 영역을 표시합니다..
  • Show patches: 그리기 영영에서 늘어날 영역(핑크색)을 표시.
  • Show content: 미리보기 이미지에서 콘텐츠 영역(보라색)을 표시.
  • Show bad patches나쁜 패치를 붉은선으로 보여줍니다. 나쁜패치를 모두 제거할 경우 이미지가 시각적 일관성이 유지됩니다.

 

 

나인패치가 적용된 이미지는 다음과 같이 주로 버튼에 사용됩니다.

반응형
,
반응형

가끔 코드를 짜다보면 임의로 그룹을 닫아야 하는 경우가 있다.

 

그럴 때는 아래의 코드 한 줄로 해결 할 수 있다. 

 

mExpandable.collapseGroup(groupPosition); 


반응형
,
반응형

아주 간단한 Button 한개가 추가된 Simple Project를 작성하고 

Button Click Handler를 구성하기 위해 다음과 같이 code를 작성했다.

 

=========================================================================== 

  1  public void onCreate(Bundle savedInstanceState) {
  2      super.onCreate(savedInstanceState);
  3       
  4      try { 
  5          setContentView(R.layout.main); 
  6          btnObject = (Button)this.findViewById(R.id.button1);  <=== exception 
  7          btnObject.setOnClickListener(this);
  8      } 
  9      catch (Exception e) { 
 10       e.printStackTrace(); 
 11      } 
 12  } 
 13 
===========================================================================

 


그런데 이러허게 간단한 code가 왠걸...컴파일 후 실행하면
exception(id=830007829856)이 발생되면서 프로그램이 죽어버린다.

흠.. 몇시간의 구글링을 통해 알아낸 결과로는

button이 소속된 layout의 생성이 되지 않았는데 button id를 호출해서 발생된다는 것

 

그러나 구글링을 통해 알아낼 해결방법은 고작

Layout생성을 위해 setContentView(R.layout.main); 코드를 최상위로 올려라!!


그렇지만 위의 code에서와 같이 벌써 coding되어 있음에도 exception이 발생된다는것은
여전히 main layout이 생성되지 않았다는 것을 의미한다.

몇시간의 삽질 끝에.. main.xml에 다음과 같이 어이가 없는 상황이 발생되어 있음을 알게되었다.

===========================================================================

  1 <?xml version="1.0" encoding="utf-8"?> 
  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3     android:id="@+id/linearLayout1"  <== 이 라인이 추가. 
  4     android:orientation="vertical" 
  5     android:layout_width="fill_parent" 
  6     android:layout_height="fill_parent" 
  7     > 
  8  
  9     <Button 
 10         android:id="@+id/button1" 
 11         android:layout_width="fill_parent" 
 12         android:layout_height="wrap_content" 
 13         android:text="Button" /> 
 14  
 15 </LinearLayout>
===========================================================================


반응형
,
반응형

Url에 있는 사진을 내 앱에 뿌려줄 때, Bitmap으로 변환하는 함수.

 * 주의할점. bitmap 변환 시 out of memory 주의. 

 

public static Bitmap getBitmap(String urlpath) {
        Bitmap bm = null;
        try {
         URL url = new URL(urlpath);
            URLConnection conn = url.openConnection();
            conn.connect();
            BufferedInputStream bis = 
                               new BufferedInputStream(conn.getInputStream());
            bm = BitmapFactory.decodeStream(bis);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (httpclient != null) {
                httpclient.close();
            }
        }
        return bm;
    }


반응형
,
반응형

 

아래의 함수를 만든 다음 boolean값으로 return 받아서 처리하면 됨.

 

public boolean isConnectingToInternet(){
        ConnectivityManager connectivity = (ConnectivityManager) 

    _context.getSystemService(Context.CONNECTIVITY_SERVICE);

          if (connectivity != null) 
          {
              NetworkInfo[] info = connectivity.getAllNetworkInfo();
              if (info != null) 
                  for (int i = 0; i < info.length; i++) 
                      if (info[i].getState() == NetworkInfo.State.CONNECTED)
                      {
                          return true;
                      }
          }
          return false;
    }

반응형
,