2015년 12월 27일 일요일

Handler를 이용해서 특정 시간 후에 특정 작업을 실행시키기





Handler를 이용해서 특정 시간 후에 특정 작업을 실행시키기

특정 시간 후에 특정한 작업이 실행되도록 하는 방법으로 AlarmManager를 이용할수 있지만 간단하게 처리할수 있는 방법으로는 Handler를 이용하면 더 쉽게 처리할수가 있다.
대표적으로 ProgressDialog를 특정 시간 경과 후 종료 시키는 방법을 구현한다면 아래와 같이 간단히 처리할수 있다.
아래 코드는 7초 후에 ProgressDialog를 중지시키는 코드이다.
실행하기 원하는 작업(코드)를 Runnable 인터페이스의 추상 메소드인 public void run() 안에 두면 run안의 코드가 특정 시간 경과후(여기서는 7초) 실행이 된다.
즉 ProgressDialog의 객체인 pDialog를 show() 한 후에 

      ProgressDialog pDialog = new ProgressDialog(this,            
                                                   AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
      pDialog.setCancelable(false);
      pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
      pDialog.setMessage("주변의 BLE 장치를 검색 중입니다.");
      pDialog.show();

      mHandler.postDelayed(new Runnable() {
          @Override
          public void run() {
              pDialog.dismiss();
          }
      }, 7000);


Handler 클래스의 해당 메소드를 보면 다음과 같이 되어 있다.

public final boolean postDelayed (Runnable r, long delayMillis)
⇒ Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached.

r : The Runnable that will be executed.
delayMillis : The delay (in milliseconds) until the Runnable will be executed.

Runnable 객체를 message queue에 추가한 후에 delayMillis 시간 경과 후에 Runnalbe 객체 r을 실행시킨다. 이렇게 처리하면 Thread로는 처리 불가능한 UI 관련 작업도 처리할수 있다.

r : 실행할 코드를 담고 있는 Runnable 객체. Runnable의 추상 메소드 public void run()안에 있는 코드를 실행한다.
delayMillis : 여기에 설정된 시간만큼 경과 후에 r을 실행한다.

2015년 12월 21일 월요일

현재의 디바이스가 BLE(Bluetooth Low Energy)를 지원하는지 확인하는 법





현재의 디바이스가 BLE(Bluetooth Low Energy)를 지원하는지 확인하는 법

일단은 Manifest파일에 아래의 permission을 추가해야한다.

    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

BLE가 지원되는 여부를 파악하기 위해서는 PackageManager의 도움을 받으면 된다.
PackageManager의 객체는 Context 클래스에 있는 아래 메소드로부터 객체를 획득할수 있다.

public abstract PackageManager getPackageManager ()

그리고 PackageManager 클래스에 있는 아래 메소드를 통해 BLE 지원 여부를 확인할 수 있다.

public abstract boolean hasSystemFeature (String name)

아래는 코드 조각이다.

        PackageManager pkgMan = getPackageManager();
        if (pkgMan.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "BLE가 지원되는 디바이스 입니다.", 1).show();
        } else {
            Toast.makeText(this, "BLE가 지원되지 않습니다.", 1).show();
        }

2015년 12월 17일 목요일

Android Studio에서 화면 넓게 사용하는 Tip





Android Studio에서 화면 넓게 사용하는 Tip

※ Android Studio 1.5 버전을 중심으로

요즘의 노트북들은 세로 화면보다는 가로 화면이 넓은 형태인데 eclipse를 사용하다가 Android Studio를 사용해 보면 화면이 좁다는 느낌을 갖게된다. 
이러한 불편함을 해소할수 있는 기능이 Android Studio에서는 아주 잘 제공이 되고 있다. 어떤 면에서는 감탄스럽다.

(1) 불필요한 몇 가지 Bar 표시 안되게
Status Bar와 Navigation Bar 표시 안되게
아래 그림과 같은 Status bar와 Navigation Bar는 굳이 없어도 될만한 정보이다. 이 2개의 bar를 표시되지 않게 할려면 View 메뉴에서 Status Bar와 Navigation Bar의 체크 상태를 해제하면 된다.




(2) Distraction Free Mode 사용하기
아래 이미지에서와 같이 오직 메뉴만 보여지는 상태로 코딩할수 있는 화면이다.
View - Enter Distraciton Free Mode를 클릭하면 아주 넓은 화면상태에서 여유롭게 코딩을 할수가 있다. 이 상태를 해제시는 다시 View메뉴로 들어가서 Exit Distraction Free Mode를 클릭하면된다. 




(3) Full Screen 사용하기
아래 이미지와 같이 Tool 버튼들과 각 클래스 탭만으로 보여주는 화면 상태가 Full Screen 상태이다. 
View - Enter Full Screen를 클릭하면 사용할수 있는 화면이다.
이때 만일 메뉴들을 보기 원하면 F10키나 마우스를 화면 최상단으로 옮기면 숨겨져 있는 메뉴가 다시 나타나게된다.
이 상태의 해제는 View - Exit Full Screen을 클릭하면된다.



(4) Presentation Mode 사용하기
아래 이미지와 같이 코딩할수 있는 공간 외에는 다른 아무것도 화면에 보이지 않는 상태이다. 글자 크기도 큼지막하게 시원한 화면에서 코딩할수 있다. 물론 이 화면은 프리젠테이션을 목적으로 하는 화면이다. 
여기서 메뉴를 볼려면 F10이나 마우스를 화면 최상단으로 옮기면 메뉴가 다시 보여지게된다.



2015년 12월 16일 수요일

adb shell을 이용한 안드로이드 앱 apk 삭제하기





adb shell을 이용한 안드로이드 앱 apk 삭제하기

DOS 창에서 안드로이드 SDK가 설치된 폴더의 platform-tools 폴더로 이동해서 

adb uninstall 패키지명

ex)C:\....\platform-tools>adb uninstall com.test.myapp


패키지 명을 알려면 DOS 창에서
adb shell
# cd /data/data
# ls를 하면
설치된 패키지들이 죽~ 나온다.
여기서 삭제하기 원하는 패키지(앱)를 확인하면 된다.

Android을 보다 깊고 폭 넓게 공부할려면





Android을 보다 깊고 폭 넓게 공부할려면 두 가지를 해볼 필요가 있다.

① 구글에서 제공하는 API Guides
http://developer.android.com ⇒ 메뉴 중 Develop ⇒ API Guides
여기에서 안드로이드로 할수 있는 전 분야에 대해 배울수 있다. 
Web App을 어떻게 만들것인지, Bluetooth 관련, 구글 맵과 센서 사용관련, 미디어와 카메라 관련, 애니메이션 동작 관련 등 주옥같은 정보들이 담겨있다.

② 구글에서 제공하는 Sample 소스
Android SDK를 다운 받으면 sdk폴더 아래에 samples 폴더가 있는데 이 폴더에는 안드로이드 각 버전별 샘플 소스들이 있다. 이또한 영양가 높은 샘플들이다. 이 소스들을 분석해 보면 배우는 것들이 많을 것이다.
구글의 Sample 소스를 다운 받을려면 Android SDK 폴더에 보면 SDK Manager.exe라는 실행파일을 실행하면 샘플 소스들을 각 버젼별로 다운 받을수 있다.

2015년 12월 15일 화요일

안드로이드 스튜디오(Android Studio)에서 구글 샘플 소스 import 하기





안드로이드 스튜디오(Android Studio)에서 구글 샘플 소스 import 하기

※ Android Studio 1.5 버전을 기준

File - New - Import Sample... - Import Sample이라는 창이 뜨고 여기서 원하는 sample 소스를 import 하면된다.






Sample 소스가 import가 완료되면 위의 그림과 같이 선택할 수 있는 몇 가지 동작에 대한 간략한 소개 화면이 뜬다.
여기서 Alt+1(숫자 1)을 누르면 화면 좌측에 드디어 project 및 파일 구조를 보여주는 view가 보여진다. 
여기서부터 이제 샘플 소스를 주무를 수 있게 된다.



Android 카메라 영상이나 사진이 어두울 때 밝게 하는 방법





Android 카메라 영상이나 사진이 어두울 때 밝게 하는 방법

카메라로부터의 영상과 사진을 밝게 하는 방법으로는 노출(exposure) 값을 조정하는 방법을 통해서 원하는 기능을 구현할수 있다.
Camera.Parameters 클래스에는 카메라에 다양한 옵션들을 설정할수 있는 기능과 해당 값들이 마련되어 있다.
카메라의 zoom 조절, color에 대한 effect 설정, 초점 관련 설정, white balancing 설정, 그리고 노출정도에 대한 설정 등이다.
이 중에서 영상(사진)의 밝기를 결정하는 첫번째가 노출 값을 조정하는 것이고 또 다른 하나는 영상 밝기에 직접적인 영향을 주는 것은 아니나 
white balance를 통해서 일정부분 결과를 만들어낼수 있다. 
밝기 문제를 해결하는 핵심은 노출(exposure)의 값을 변경하는 것이다.
Camera.Parameters 클래스의 아래 메소드를 통해서 간단히 해결할수 있다.

public void setExposureCompensation (int value)

여기서 매개인자 value에 들어갈 값의 범위는 디바이스들 마다 각기 상이하다. 따라서 이 값을 결정하는 메소드가 2가지 제공이 된다.
getMinExposureCompensation()의 값에서 getMaxExposureCompensation()까지의 값이 value에 들어갈 값이다.
보틍은 -n ~ +n까지가 되는데 0이면 노출을 적용하지 않는 것이고 음수이면 기본 밝기보다 더 어두워지고 양수 값이면 기본 밝기 보다 더 밝아진다.

여기서 주의 할 것은 이렇게 설정된 각종 parameter 값들이 적용되는 시점은 android.hardware.Camera 클래스의 setParameters()가 실행될 때이다.

public void setParameters (Camera.Parameters params)

그런데 주의해야할 것은 이 메소드 실행 전에 각종 parameter 값들을 설정시 어떤 parameter 값들은 적용이 안되는 디바이스들이 있다. 이건 디바이스마다 상이하다.
만일 설정되어 있는 parameter 중에서 특정 디바이스에 적용이 안되는 값이 설정되어 있으면 setParameters (Camera.Parameters params) 메소드 실행시 앱이 강제 종료되는 수가 있다. 
예를 들어 아래의 parameter들은 갤S4에서는 강제종료된다. 

parameter.setSceneMode(Camera.Parameters.SCENE_MODE_PORTRAIT); 
parameter.setFocusMode(Camera.Parameters
                                                    .FOCUS_MODE_CONTINUOUS_VIDEO);

그런데 이렇게 강제 종료되지 않도록 Exception 처리를 해 두면 앱은 강제 종료가 되지 않지만 setParameters (Camera.Parameters params)가 정상 실행되지 않았기 때문에
위에서 설정했던 parameter들이 전혀 적용이 되지 않는 상황이 벌어진다. 왜 적용이 안되는가 혼란에 빠질수가 있다.
아래의 코드가 그 예이다.

try {
parameters.setPreviewFrameRate(10);
parameters.setSceneMode(Camera.Parameters.SCENE_MODE_PORTRAIT); 
parameters.setFocusMode(Camera.Parameters
                                   .FOCUS_MODE_CONTINUOUS_VIDEO);

  //위의 두 parameter때문에 여기서 exception 발생하고 이 메소드 실행 안됨
//따라서 앞에서 설정했던 모든 parameter들이 하나도 적용이 안된다.
  mCamera.setParameters(parameters); 
} catch (Exception ex) {
Toast.makeText(mContext, "setParameters failed~", 1).show();
}

이 문제에 대한 해법은 아래와 같이 처리해 줘야 된다.

//public List<String> getSupportedSceneModes ()
List<String> sceneModeList = parameters.getSupportedSceneModes();

//public List<String> getSupportedFocusModes ()
List<String> focusModeList = parameters.getSupportedFocusModes();

try {
parameters.setPreviewFrameRate(10); 
if (sceneModeList != null && 
                       sceneModeList.contains(Camera.Parameters
                                               .SCENE_MODE_PORTRAIT)) {
    parameters.setSceneMode(Camera.Parameters.SCENE_MODE_PORTRAIT); 
  }
if (focusModeList != null && 
focusModeList.contains(Camera.Parameters
                                           .FOCUS_MODE_CONTINUOUS_VIDEO)) {
  parameters.setFocusMode(Camera.Parameters
                              .FOCUS_MODE_CONTINUOUS_VIDEO);
  }
mCamera.setParameters(parameters);
} catch (Exception ex) {
  Toast.makeText(mContext, "setParameters failed~", 1).show();
}

아래는 코드 조각이다.

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mCamera == null) return;
  Camera.Parameters parameters = mCamera.getParameters();

//WHITE_BALANCE_FLUORESCENT 
//WHITE_BALANCE_DAYLIGHT 
//WHITE_BALANCE_CLOUDY_DAYLIGHT 
//WHITE_BALANCE_INCANDESCENT 
//WHITE_BALANCE_SHADE : 약간 어둡다.
//WHITE_BALANCE_WARM_FLUORESCENT : 약간 어둡다.
parameters.setWhiteBalance(Camera.Parameters
                                                  .WHITE_BALANCE_CLOUDY_DAYLIGHT); 
int maxExpo = parameters.getMaxExposureCompensation();
parameters.setExposureCompensation(maxExpo); 

  List<String> sceneModeList = parameters.getSupportedSceneModes();
List<String> focusModeList = parameters.getSupportedFocusModes();
try {
  parameters.setPreviewFrameRate(10); 
  if (sceneModeList != null &&  
           sceneModeList.contains(Camera.Parameters.SCENE_MODE_PORTRAIT)) {
parameters.setSceneMode(Camera.Parameters
                                                        .SCENE_MODE_PORTRAIT); 
  }
if (focusModeList != null && 
           focusModeList.contains(Camera.Parameters
                                               .FOCUS_MODE_CONTINUOUS_VIDEO)){
        parameters.setFocusMode(Camera.Parameters
                                                      .FOCUS_MODE_CONTINUOUS_VIDEO);
}
  mCamera.setParameters(parameters);
} catch (Exception ex) {
Toast.makeText(mContext, "setParameters failed~", 1).show();
}
  mCamera.startPreview();