'Android'에 해당되는 글 20건

  1. 2017.05.17 Google AAD - 구글에서 인증한 안드로이드 개발 자격증
  2. 2017.05.12 android 6.0 권한관리 쉽게 적용하는 RxPermission 사용법
  3. 2017.04.01 구글 firebase는 무엇인가? 제공하는 기능은? 1
  4. 2017.03.30 App이 foreground 인지 background 인지 구별하기 1
  5. 2015.10.14 android face detecting ( FaceDetector vs google-play-vision )
  6. 2014.06.11 외부 library에 소스 경로 추가하기
  7. 2013.09.09 [android] NDK 개발환경 세팅
  8. 2013.08.21 [android] FFmpeg 빌드 for android with shared-lib
  9. 2013.06.19 [android] CheckBox에서 image와 text 간격
  10. 2013.05.31 [android] Volley - Network & ImageLoading 라이브러리 ( google I/O 2013 )

Google AAD - 구글에서 인증한 안드로이드 개발 자격증

개발 2017. 5. 17. 00:10

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

2016년 google I/O에서 발표했다고 하는데요, 구글에서도 과거 MCSE 같은 인증 자격증 제도를 운영하고 있습니다. 

과거 Java의  SCJP 를 취득한다고 취업에 크게 도움이 되지 않았고, Microsoft의 MCSE 도 비슷했다. 우리나라의 정보처리기사 정도의 가치가 있을런지.. 


2017년 3월 14일 기준으로 61개국에서 322명이 취득했다고 하니, 그렇게 인기가 많은건 아닌거 같다. 개발 해보면 알듯이 개발 능력을 어떤 시험으로 책정하기가 어렵기에, 이런류의 자격증은 base-line을 검증하는, 즉 최소 이정도는 알고 있다는 의미정도를 부여할수 있다. 


구글에서는 AAD를 소개하는 동영상도 만들었다. 정확한 명칭은 AAD (Associate Android Developer) 인증프로그램이라고 한다. 


구글의 기술블로그에도 소개가 되어 있다. 

https://developers-kr.googleblog.com/2017/03/introducing-associate-android-developer.html


응시료가 149달라라고 하니 대략 15만원. 비싸구나. 그리고 시험에 응시하면 48시간동안 문제를 풀어서 제출해야 한다고 한다. 물어 보는 내용은 다음과 같다. 


테스트 및 디버깅

    로컬 JVM 유닛 테스트 작성 및 실행

    장치 UI 테스트 작성 및 실행

    문제 설명이 주어지면 실패를 복제하십시오.

    디버그 정보를 출력하려면 시스템 로그를 사용하십시오.

    애플리케이션 크래시 디버깅 및 수정 (포착되지 않는 예외)

    활동주기 문제를 디버그하고 수정합니다.

    뷰에 문제 바인딩 데이터 디버그 및 수정


응용 프로그램 사용자 인터페이스 (UI) 및 사용자 경험 (UX)

    응용 프로그램의 기본 화면과 탐색 흐름 모의

    UI, 백그라운드 작업 및 데이터 지속성 간의 상호 작용을 설명하십시오.

    XML 또는 Java 코드를 사용하여 레이아웃 만들기

    사용자 정의보기 클래스 만들기 및 레이아웃에 추가

    사용자 정의 응용 프로그램 테마 구현

    공통 위젯 그룹에 맞춤 스타일 적용

    RecyclerView 항목 목록 정의

    로컬 데이터를 RecyclerView 목록에 바인딩

    메뉴 기반 또는 서랍 탐색 구현

    응용 프로그램의 UI 텍스트를 다른 언어로 현지화하십시오.

    접근성을 위해보기에 내용 설명 적용

    사용자 정의보기에 접근성 후크 추가


기본 응용 프로그램 구성 요소

    응용 프로그램의 주요 기능 및 비 기능 요구 사항 설명

    레이아웃 리소스를 표시하는 활동 만들기

    백그라운드 스레드에서 로더를 사용하여 디스크에서 로컬 데이터 가져 오기

    로더를 통해 데이터 변경 사항을 UI로 전파

    알람을 사용하여 시간에 민감한 작업 예약

    JobScheduler를 사용하여 백그라운드 작업 예약

    서비스 내부 백그라운드 작업 실행

    비표준 작업 스택 탐색 (딥 링크) 구현

    외부 지원 라이브러리의 코드 통합


영구 데이터 저장소

    데이터베이스 스키마를 정의하십시오. 표, 필드 및 색인 포함

    응용 프로그램 전용 데이터베이스 파일 만들기

    단일 결과를 반환하는 데이터베이스 쿼리 작성

    여러 결과를 반환하는 데이터베이스 쿼리 작성

    데이터베이스에 새 항목 삽입

    데이터베이스의 기존 항목 업데이트 또는 삭제

    콘텐츠 공급자를 통해 다른 응용 프로그램에 데이터베이스 노출

    원시 리소스 또는 자산 파일 읽기 및 구문 분석

    사용자 입력에서 영구적 인 환경 설정 데이터 생성

    환경 설정 값을 기반으로 응용 프로그램 로직 토글


기술면접 자료로 사용해도 될것 같다. 

자세한 자료는 다음을 참고 

https://developers.google.com/training/certification/





:

android 6.0 권한관리 쉽게 적용하는 RxPermission 사용법

android 2017. 5. 12. 21:18

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

안드로이드 개발에도 점점 RxJava 를 많이 사용하고 있는데요, 

RxJava를 사용하고 있다면, mashmallow (android 6.0) 이상에서 구현해야 하는 권한 관리를 편하게 추가할 수 있습니다. 

 권한 설정 구현은 targetSdkVersion 23 이상으로 해서 빌드하면 반드시 구현해야 되는 항목입니다. 

targetSdkVersion 23


RxPermisstion을 적용하는 단계는 다음과 같습니다. 


[ 설정 ] 

build.gradle에 다음과 같이 추가해 줍니다. dependencies 부분에.. 

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar' // 이부분
testCompile 'junit:junit:4.12'
}

만약에 RxJava2를 사용하고 있다면..  아래 빨간 글씨처럼 2를 붙여주면 됩니다. 

dependencies {
    compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
}


[ 적용 ] 

1단계 

Activity의 onCreate() 에서 객체를 생성해 줍니다. 

public class CameraActivity extends BaseActivity {

RxPermissions rxPermissions;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.camera_activity_layout);
rxPermissions = new RxPermissions(this);

}


그런 다음에 필요한 권한을 요청하고 구독하면 됩니다. 

아래는 camera 권한을 요청하고  

사용자가 허가하면 ( granted ), 카메라를 열고

거절하면 alert을 띄워주는 흐름입니다.  

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.camera_activity_layout);
rxPermissions = new RxPermissions(this);


rxPermissions
.request(
Manifest.permission.CAMERA )
.subscribe(permission -> {
if (granted) {

openCamera();
}
else {
PermissionUtils.
alertPermission(this, Manifest.permission.CAMERA );

}
})
;
}


코드도 간략하고, 흐름도 너무 자연스러운게 좋습니다. 

그냥 구현하려면, 사용자 응답을 받는  onRequestPermissionsResult 함수에서 뭘하고, 해야 하다 보면 흐름이 이상해지는 경우나, 꼬이거나 해서 코드가 지져분해지기 쉬운데요, RxPermissions를 사용하면 너무나 쉽게 적용할 수 있습니다. 


request에 여러 permission을 동시해 요청할 수도 있습니다. 

여러 권한을 요청하면 granted 값은 모든 요청을 사용자가 동의한 경우이고, 하나라도 거절하면 false로 들어옵니다. 

rxPermissions
.request(Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION
)


만약 여러권한에 대해서 개별적으로 응답을 받고 싶으면 request 대신에 requestEach를 사용하면 됩니다. 

rxPermissions
.requestEach(Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION
)
.subscribe(permission -> {
// 요청한 permission 수만큼 호출된다.
if (permission.granted) {

}
else {

}
})
;


그리고 어떤 권한이 있는지 확인 하기 위해서는 아래처럼 간단하게 호출해 볼수 있습니다. 

if (rxPermissions.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)) {
// 위치정보 관련 작업
}


[ 사용시 주의사항 ]

권한요청중에 앱이 다시 시잘될 수가 있으므로, onCreate같은 초기화 함수에서 request를 처리해야 합니다. 절대로 onResume에서 사용하면 안됩니다. 


[Tip]

* RxPermissions 사용시 추가해야할 proguard 설정은? 없습니다. 



더 자세한 정보를 위해서는 개발자의 page에 직접 방문해 보세요. 

https://github.com/tbruyelle/RxPermissions





:

구글 firebase는 무엇인가? 제공하는 기능은?

android 2017. 4. 1. 01:38

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

2016년에 출시된 구글의 firebase에 대해서 알아 보자. 

firebase는 앱개발을 할때 필요한 도구와 인프라를 제공하기 위해서 구글에서 만들었다. 



초창기 안드로이드앱은 서버와 연동 없어 혼자 동작하는 기능의 앱이 많았다면, 요즘에는 앱혼자 동작하기 보다는 서버에서 데이터를 받아서 연동는 기능이 거의 필수처럼 구현되고 있는 상태이다. 그래서 구글에서는 앱개발자가 앱개발에만 전념할수 있도록 앱개발 이외의 모든것을 제공하기 위해서 firebase라는 이름으로 제공하고 있다. 

그럼 firebase에서 제공하는 것들은 어떤 것이 있는지 대략적으로 알아보자. 



이미지출처 : https://firebase.google.com/




위의 그림에서 보듯이, 크게 3가지의 카테고리로 제공하고 있다. 

구글에서 firebase를 사용하면 고품질의 앱을 빠르게 개발하고, 사용자층을 확대하고, 더많은 수익을 창출할 수 있는 모바일 플랫폼으로 설명하고 있다. 

이중에서 개발에 관련된것 위주로 간략하게 살펴보자. 



* Realtime Database 

 - On-line으로 제공되는 NoSQL DB 이다. 오프라인 모드를 지원하는 특징이 있다. 

 - 앱에서 하나의 DB를 보게되므로 여러 사용자에게 동기화된 데이터를 제공 가능하다. 

 - 리얼타임 데이터베이스를 사용하면 계시판등을 쉽게 만들수 있을것 같다. 



* Authentication

 - 로그인등의 인증을 제공하는데, Firebase에서제공하는 UI인증을 사용할수도 있고, 

 - Firebase SDK를 사용해서 로직 처리만 사용할 수도 있다. 

 - googke, facebook, twitter, github 와 제휴되어서 각각의 계정으로 로그인 인증을 제공한다. 

 


* Cloud Messaging 

 - 기존의 GCM(Google Cloud Messaging)이 FCM(Firebase Cloud Messaging)으로 이름이 변경된 것이다. 

 - 기존 push와 같은 알림메시지 뿐만이 아니라 데이터 메시지가 추가되었다. 

 - 메시지 전송시에도 기기별, 그룹별, 주제별로 타게팅 해서 보낼수 있다. 



* Storage 

 - 사용자의 사진, 동영상등의 컨텐츠를 저장할 수 있는 공간을 제공한다. 

 - 구글 클라우드 스토리지(Google Cloud Storage) 이다. 



* Hosting 

 - 웹 컨텐츠 호스팅 서비스로, global CDN을 제공한다.  

 - SSL을 기본적으로 제공한다. 

 - 앱개발보다는 웹개발에 적합한 도구로 보인다. 



* Remote Config 

 - 앱 업데이트 없이 어떤 변경을 동적으로 하고 싶을때 사용한다. 

 - GTM(Google Tag Manager)와 같은 방식으로 동작한다. 

 - 예를 들면, theme="white" 로 하면 앱의 전체적인 테마가 white계열로 보이다가, theme="black"으로 설정을 변경하면 앱이 black 계열로 변경되게 하는 것이다. 



* TestLab 

 - 일종의 AB테스트를 지원하는 기능이다. 

 - 예를 들으서 새로운 기능을 출시 할때, 전체 사용자가 아니라 일부 사용자에게만 시범적으로 먼저 사용해보고 피드백등을 받을수 있게 해준다. 

 - 피드백은 스크린샷, 로그, 동영상등으로 받을수 있다. 



* Crash Reporting 

 - 앱이 실행중 crash가 발생할때 어디서 죽었는지 callstack등을 제공한다. 

 - 또한 기기특성, 성능데이터 및 사용자 상황을 같이 제공해서 문제 해결을 도와준다. 



위에서 제공하는 기능들은 앱을 개발할때 필요한데, 서버개발이 필요한 부분이라서 firebase를 이용하면 상당한 도움이 될 것 같다. 제공하는 기능들이 앱개발시 필요한 것이고, 하나하나가 모두 유익한 것들이다. 


위에서 제공하는 기능들이 서로 연동되고 통합하는 중심에는 firebase의 꽃이라고 할 수 있는 Analytics가 존재한다. 


[Analytics] 

 - 기존의 GA(Google Analytics)가 웹페이지를 위한 목적으로 개발되었다면, FA(Firebase Analytics)는 앱을 목적으로 개발된 것이다. 

 - 사용자가 App을 사용하는 방식을 파악할 수 있다. 

 - 다양한 각도에서 여러가지 보고서를 제공한다. 

 - 중요한 것은 제한이 없는 무료라는 것이다.  ( GA는 light한 사용은 무료이고, 일정이상 사용하려면 유료 )

 - firebase 에서 제공하는 다른 기능들과 통합하여 여러가지 관리를 할 수 있다. 



중요한것 한가지를 빼먹었는데, firebase에서 제공하는 기능들 중에서 모두 무료로 제공하는건 아니다. 

Database, Storage, Hosting, TestLab , GoogleCloud Platform 등은 어느정도 까지만 무료로 제공한다. 

아래에서 무료로 지원하는 범위를 정리하였다. 


 Realtime Database

 동시접속

 100명

 저장용량

 1 GB

 다운로드

 10 GB / month

 Storage 

 저장용량

 5 GB

 다운로드

 1 GB / day

 업로드 횟수

 20,000 번 / day 

 다운로드 횟수

 50,000 번 / day

 Hosting

 저장용량 

  1 GB

 전송용량 

  10 GB / month


각각 기능들을 따로 제공하는 서비스들이 있는데, 각각 다른것을 이용하는 것보다 통합된 firebase를 사용하면 어떨까? 

실제 사용에 대한 판단은 사용하는 사람이~~  ( 저는 사용해보는 것에 한표~ ) 


이상으로 간단하게 firebase는 무엇이고, 어떤 기능들을 제공하는지 알아 봤습니다. 

다음으로는 간단하게 firebase를 적용하는 방법에 대해서 알아 보겠습니다. 


2017/04/03 - [android] - 구글 firebase 프로젝트 생성및 적용하기





:

App이 foreground 인지 background 인지 구별하기

android 2017. 3. 30. 22:24

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

안드로이드 App을 만들다 보면은 App이 background로 내려가는 시점을 알아야 할 때가 있다. 

그런데, 안드로이드에서는 Home 버튼을 눌렀는지 알 수 있는 방법이 없어서 약간의 편법을 사용해야 한다. 



먼저 고전적인 방밥으로는 ActivityManager를 이용하는 방법이다. 

코드로 보면 아래와 같다. 


private boolean isAppIsInBackground(Context context) {
    boolean isInBackground = true;
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
        List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
            if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                for (String activeProcess : processInfo.pkgList) {
                    if (activeProcess.equals(context.getPackageName())) {
                        isInBackground = false;
                    }
                }
            }
        }
    } else {
        List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        ComponentName componentInfo = taskInfo.get(0).topActivity;
        if (componentInfo.getPackageName().equals(context.getPackageName())) {
            isInBackground = false;
        }
    }

    return isInBackground;
}


키캣미만에서는 RunningTaksInfo를 이용하고, 키캣이상에서는 RunningAppProcessInfo 를 이용하는 방식이다. 그런데 이 방색을 사용할때는  GET_TASKS 권한을 AndroidManifest.xml에 추가해야 하는데,  GET_TASKS 권한이 deprecated 되었다. 



그래서 다른 방식으로 사용하는것이 Activity의 onStart(), onStop() 함수를 오버라이드(override) 해서 count 하는 방식이다. 대략적인 코드는 아래와 같은 모습이다. 


public class BaseActivity extends Activity {
public static int foregroundCount = 0; // 전역 count 변수

@Override
protected void onStart() {
    super.onStart();
    foregroundCount = foregroundCount+ 1;
}


@Override
protected void onStop() { super.onStop(); foregroundCount = foregroundCount - 1;
} }


Application에서 사용하는 모든 Activity가 BaseActivity를 상속받게 하고, foregroundCount 가 1이상이면 foreground로 볼 수 있는 것이다. 

Activity가 많다면 은근히 작업이 많아 질 수도 있고, 나주에 추가되는 Activity에서 BaseActivity 로부터의 상속을 빼먹으면 버그가 발생하기 쉬운 방식이다. 



그럼 좀 더 안전한 방법은 없을까? 

앱에있는 Application 클래스를 이용하는 방법이 있는데, 

먼저 background에 있는지 체크하는 방법을 알아보자 


public class MyApplication extends Application {
    // ...
    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        if (level == TRIM_MEMORY_UI_HIDDEN) {
           isBackground = true;
           notifyBackground();
        }
    }
}


그런데, onTrimMemory 함수는 screen off 상태일때는 호출이 안되므로, 아래처럼 리시버를 등록해서 체크해야 한다. (screen off 상태는 전원버튼을 눌러서 화면을 끄는것을 말한다. ) 


public class MyApplication extends Application {
  // ...
  @Override
    public void onCreate() {
        super.onCreate();
        // ...
        IntentFilter screenOffFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
              if (isBackground) {
                  isBackground = false;
                  notifyForeground();
              }
            }
        }, screenOffFilter);
      }
}


이렇게 하면 background 상태는 체크가 되는데, foreground 상태는 어떻게 알아 낼 수 있을까?

간단하게 ActivityLifecycleCallback() 함수를 이용하면 된다. 


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

     registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
               // ...
               @Override
               public void onActivityResumed(Activity activity) {
                 if (isBackground) {
                     isBackground = false;
                     notifyForeground();
                 }
               }
               // ...
           });
       }
       // ...
}



이상으로 App이 foreground에 있는지, background에 있는지 체크하는 방법에 대해서 

1. ActivityManager를 이용하는 고전적인 방법 

2. Activity의 onStart(), onStop() 을 활용한 방법

3. Application의 onTrimMemory(), registerActivityLifecycleCallbacks() 를 활용하는 방법

으로 알아 보았습니다. 





:

android face detecting ( FaceDetector vs google-play-vision )

android 2015. 10. 14. 15:02

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 

먼저 혼동하기 쉬운 얼굴인식과 얼굴검출에 대해서 간단하게 짚고 넘어가면..

얼굴검출(face detect)은 이미지에서 얼굴이 어느 영역에 있는지 찾는 것이고

얼굴인식(face recognize)A라는 얼굴과 B라는 얼굴이 유사한지 또는 같은 사람인지 판별하는 것이다.

 

안드로이드에서 face dectect을 하기 위해서는 2가지 방식이 있다.

첫번째는 , Image 소스에서 얼굴을 검출(dectect)하는 android.media.FaceDetector 를 이용하는 방법

두번째는, live stream 소스에서 얼굴을 검출하는 Camera.FaceDetectionListener 를 이용하는 방법

 

Android 에서 얼굴검출을 위해서 3rd party library를 사용하지 않는다면 어쩔수 없이 사용하는 FaceDetector API level 1 부터 사용가능하데, 그래서 그런지 결과나 성능에서 상당히 떨어진다. 그리고 FaceDetector를 사용할때는 한가지 주의 할점이 입력 Bitmap RGB_565 타입을 넘겨야 한다. 대략적인 코드는 아래와 같다.

 

android.media.FaceDetector.Face[] scaledFaces = new android.media.FaceDetector.Face[1]; // 얼굴 1개만 인식
Bitmap inputBitmap = buildScaledFace565Bitmap(imageBitmap);
android.media.FaceDetector faceDetector = new android.media.FaceDetector(inputBitmap.getWidth(), inputBitmap.getHeight(), 1);
faceDetector.findFaces(inputBitmap, scaledFaces);

 

그리고 입력 bitmap의 크기가 커질수로 수행시간이 기하급수적으로 늘어난다. 그리고 detecting된 정보도 두 눈사이의 중점 Point, 중점 Point에서 눈사이의 거리 정보만 준다. 즉 얼굴영역(Rect)는 알려주지 않는다.

 

그래서 2015 8월에 google에서 google-play-vision library를 발표했는데, 무척이나 좋다.

간단하게 media.FaceDetector와 비교해본 테스트 성능은 아래와 같다.

 

갤럭시 S4단말

사진크기

FaceDetector 시간

Vision 시간

460 * 560

224ms

154ms

960 * 960

705ms

305ms

1920 * 1200

2380ms

350ms

 

성능도 좋지만 결과 품질도 상당히 좋다. 주요한 장점을 설명하면 아래와 같다.

 

1.     얼굴영역(left/right 정보, width, height)를 알려준다.

 

·                     getPosition() - Returns the top left coordinates of the area where a face was detected

·                     getWidth() - Returns the width of the area where a face was detected

·                     getHeight() - Returns the height of the area where a face was detected

 

 

2.     얼굴이 기울어저 있어도 검출된다.



위그림처럼 y축 기준으로 60도 회전된 얼굴과, xy평면을 기준으로 45도 회전된 얼굴까지 검출이가능하다. 기존 android.media.FaceDetector에 비하면 비약적인 발전으로 보인다. ^^;

 

3.     얼굴의 다양한 특징 포인트를 알려준다.

얼굴의 특징 포인트를 Landmark로 부르는데, 코드에 아래처럼 정의 되어 있다.

public static final int BOTTOM_MOUTH = 0;
public static final int
LEFT_CHEEK = 1;
public static final int
LEFT_EAR_TIP = 2;
public static final int
LEFT_EAR = 3;
public static final int
LEFT_EYE = 4;
public static final int
LEFT_MOUTH = 5;
public static final int
NOSE_BASE = 6;
public static final int
RIGHT_CHEEK = 7;
public static final int
RIGHT_EAR_TIP = 8;
public static final int
RIGHT_EAR = 9;
public static final int
RIGHT_EYE = 10;
public static final int
RIGHT_MOUTH = 11;

 

두눈위치, 입위치, 볼위치, 코위치, 귀위치 등 얼굴에 대해서 상세한 정보를 줄 수 있는데, 물로 검출에 성공한 경우에만 Landmark 위치를 알 수 있다. 실제로 테스트 해보면 귀위치는 잘 안나온다.

 


Image에서 얼굴검출할 때 사용하면 상당히 유용할 듯 한다. 추가로 FaceTracking(live로 얼굴을 검출하고 얼굴이 이동하면 따라가면서 계속 검출하는)도 가능하다. 하지만 FaceTrackinginput 크기가 클 경우 FPS가 잘 안나온다.

 

[관련자료]

https://developers.google.com/vision/face-detection-concepts

http://android-developers.blogspot.kr/2015/08/google-play-services-78-lets-see-whats.html

https://github.com/googlesamples/android-vision


 

 


 

 

 



:

외부 library에 소스 경로 추가하기

android 2014. 6. 11. 13:58

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

안드로이드를 개발할 때 장점은 java로 되어 있어서 android의 소스를 쉽게 참조 할수 있는 점이다. 그런데, 안드로이드 소스외에 추가로 사용하는 library에 대해서는 소스를 볼 수 없어서 답답하곤 했다. 예를 들어서 android의 하위버전 호환 library android-support-v4.jar를 대부분 사용하는데, 개발하다가 ‘F3’ 키로 따라 들어가다 보면 아래와 같은 화면을 만나게 된다.

 


Android –support-v4 opensource라서 project를 다운받아서 봐도 되지만, 개발 환경과 연동이 안되어서 바로바로 소스보기가 불편하다. 그래서 검색해보니 있구나~

 

Google I/O 2012에서 그 방법을 소개하고 있다. ( 48분 부터 보면 된다. ) 

또는 옆의 링크를 눌러도 된다.  Explanation in Google I/O 2012 video

 

간단하게 설명하면 다음과 같다.

 

1. lib 폴더에 jar 파일이름 + “.properties” 라는 파일을 하나 만든다.

   예를 들어서 gson-2.2.4.jar 이면, gson-2.2.4.jar.properties 로 파일을 하나 만든다.


2. 파일에 src 또는 doc 의 경로를 설정하면 된다. ( 절대경로, 상대경로 모두 된다. )

   예를 들면, src=../libs-sources/gson-2.2.4-sources.jar  이렇게 해주면 된다.

   물론 해당 경로에 gson-2.2.4-source.jar 파일이 있어야 한다.

 



이렇게 하고 설정이 잘 되었는지 확인하려면 환경설정에서

“Java Build path” -> Libraries -> Android Private Libraries 에서 해당 jar 파일을 찾아서 펼친뒤에 Source attachment를 확인하면 된다.



 

설정하고 위에서럼 확인이 안될때는 F5를 눌러서 refresh를 해보면 된다.

그래도 안되면 projectclose 했다가 다시 열면된다.

그래도 안되면 eclipse를 종료했다가 다시 시작해야 한다.

 

참고로 xxx-source.jar 파일은 maven 중앙 repository 등에서 쉽게 구할수 있다.

http://search.maven.org

 

개발환경이 편리해 저서 뿌듯하다~ ㅋㅋ 

 

 



:

[android] NDK 개발환경 세팅

android 2013. 9. 9. 18:04

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. NDK

앱을 개발할 때 보통은 SDK를 이용하여 개발을 한다. 그러나 SDK 에서 지원하지 않거나, 성능상의 이슈를 해결하기 위해서 NDK를 이용한다. NDK로 할 수 있는 것들은 어떤 것이 있을까를 알아보기 위해서 NDK에서 제공하는 것들을 알아보자.

·         libc (C library) headers

·         libm (math library) headers

·         JNI interface headers

·         libz (Zlib compression) headers

·         liblog (Android logging) header

·         OpenGL ES 1.1 and OpenGL ES 2.0 (3D graphics libraries) headers

·         libjnigraphics (Pixel buffer access) header (for Android 2.2 and above).

·         A Minimal set of headers for C++ support

·         OpenSL ES native audio libraries

·         Android native application APIS

많구나~ ㅋㅋ.  근데 이걸로 멀 할 수 있을까? 현실적인 주요 목적은 기존에 작성된  c/c++ 코드로 구현된 코드를 (java로 처리가 느린 image processing 같은것이 좋은 예) 그대로 이식할 수 있게 된다. 물론 필요에 따라서 java 로직을 c/c++으로 개발 할 수도 있다. 

 

2. NDK 설치하기

설치전 필요한것들  (자세한건 http://developer.android.com/tools/sdk/ndk/index.html#Reqs 참고 )

Android SDK  : android 1.5 SDK 이상

지원하는 운영체제 : windows XP 이상, Mac OS X 10.4.8 이상 ( x86 ), Linux ( GLibc 2.7 이상 )

필요한 개발도구 :

OS에 맞는 GNU Make 3.81 이상

최신 버전의 awk

윈도우의경우 Cygwin 1.7 이상

 

아래를 클릭해서 설치한다. ( 자신의 OS에 맞는 걸로 )  나는 window 64bit를 받았다. 

http://developer.android.com/tools/sdk/ndk/index.html

450MB 크기의 zip파일을 받아서 그냥 아무곳에 압축을 해제하면 된다. (해제하니 1GB 헐 ㅠㅠ)

 

3. Cygwin 설치 (윈도우에서)

다음으로 Windows 환경이므로 cygwin을 설치한다.

http://cygwin.com/install.html

여기서 setup.exe를 받아서 설치한다.

설치 중간에 package를 선택하는게 나오는데 아래는 꼭 선택해야 한다.

gcc-core : C compiler

gcc-g++ : C++ Compiler

make : The GNU version of the ‘make’ utility

 

(본인은 make를 선택안 했다가 나중에 구글링을 좀 했었다. )

그러면 dependency가 걸려 있는 다른 모듈들도 같이 설치된다. ( maven 처럼 좋네~ )

 

Cygwin을 실행한 후에 path를 설정하면 편하다.

vi .bashrc

export PATH=$PATH: {여기에 ndk-build경로 추가}

alias ll=’ls –all’

 

 

4. sample build test

Cywin을 실행한 뒤에 NDK sample 폴더로 이동한뒤에 hello-jni로 이동한다.

그러면 jni 폴더에 2개의 파일이 존재한다.

$ tree jni

jni

├── Android.mk

└── hello-jni.c

 

여기서 ndk-build를 실행하면 libhello-jni.so 파일이 생성된다.  생성후 /libs/armeabi/libhello-jni.so에 설치했다고 나온다.

$ ndk-build

Gdbserver      : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver

Gdbsetup       : libs/armeabi/gdb.setup

Install        : libhello-jni.so => libs/armeabi/libhello-jni.so

 

참고로 .so 파일은 apache의 모듈로 자주 보던 형식이었는데 linux share object 파일으로 윈도우의  dll 과 비슷한 것으로 생각하면 된다. Linexstatic library .a 파일이고, shared-library.so 파일이므로 .so 로 빌드해야 한다. Android .so 파일만 로딩할 수 있다.

 

 

 



:

[android] FFmpeg 빌드 for android with shared-lib

android 2013. 8. 21. 23:11

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

FFmpeg은 동영상을 인코딩/디코딩 해주는 opensource 입니다. 주요 특징은 아래와 같습니다.

라이선스 : LGPL

운영체제 : linux, window, mac-os, android 등 다수 지원 ( 개발은 linux 기반임 )

앞의 FFfast forward를 의미함.

대부분의 동영상 프로그램에서 사용됨. ( 곰플레이어, KMP, MX 플레이어 등 )

 

 

FFmpegandroid 용으로 컴파일 하면서 찾아본 자료 정리와 삽질 내용 정리합니다. 관련 글을 읽어본 후 따라하면 항상 안되는 경우가 발생하는데, 검색해보면 대부분 나오더군요. 제가 격은 문제들은 아래 트러블 슈팅으로 정리 하였습니다.

 

[ 환경 ]

OS : Window에서  Cygwin 으로

Android-NDK : r8e ( 현재는 r9 나와 있네요 )

목적 FFmpegAndroid shared-lib 으로 컴파일 ( static 이었으면 좋았을 것을 )

FFmpeg 버전 : 1.2.2  (http://ffmpeg.org/download.html )

 

[ 관련 글 ]

 

Android 동영상 플레이어 개념

http://helloworld.naver.com/helloworld/8794

 

Android-pub 강좌

http://www.androidpub.com/index.php?mid=android_dev_info&page=1&search_target=tag&search_keyword=FFmpeg&document_srl=1645684

http://www.androidpub.com/index.php?mid=android_dev_info&page=1&search_target=tag&search_keyword=FFmpeg&document_srl=1646144

http://www.androidpub.com/index.php?mid=android_dev_info&page=1&search_target=tag&search_keyword=FFmpeg&document_srl=1646529

http://www.androidpub.com/index.php?mid=android_dev_info&page=1&search_target=tag&search_keyword=FFmpeg&document_srl=1646540

http://www.androidpub.com/1690105

 

*vec.io 의 글 (영문) :

 https://vec.io/posts/how-to-build-ffmpeg-with-android-ndk

 

 

[ 트러블 슈팅 ]

 

l  Config 실패할 경우

원인 : 줄변경하기 위해서 \ 을 사용하는데 \ 뒤에 space 가 있으면 안됨.

이것땜에 시작부터 2~3시간 삽질함.

 

l  config 성공하고 make 실패시

원인 : 생성된 config.h 헤더파일에 줄변경 문자가 포함된 경우가 있음.

참고 : http://stackoverflow.com/questions/14199888/cygwin-make-errors-ffmpeg-compile-with-ndk

Ultra-editor 에서도 않보임. 그냥 eclipse에서 보면 줄변경 되어 있음. 콘솔인경우 VI 에디터로 바로 지우면 편리함. 계속 삽질 ㅠ

 

l  share파일이 libavcodec.so.54 이렇게 생성될 때  

원인 : 1.2.2 버전의 share 모드 스크립트가 그렇게 생겨 먹었음.

참고 :

http://stackoverflow.com/questions/14521588/native-libraries-so-xy-failing-to-link-at-runtime

http://stackoverflow.com/questions/14522510/simple-string-substitution-in-makefile/

수정 : 참고는 그냥 참고일뿐, library.mak 파일에서 link 만드는 부분 수정하면 됨. ( install-lib$(NAME)-shared 로 검색 ) 그리고 configure 파일에서 SLIBNAME_WITH_MAJOR 찾아서 수정하면됨. 삽질은 멈추지 않는다.

 

 

[ 마치면서 ]

윈도우에서 하다가 막혀서 맥에서 해보니 맥이 android NDK 개발하는데 더 좋은 환경인 것 같습니다. 주변에서도 맥에서 android 개발하는 사람들이 꽤 되던데 저도 고려중에 있습니다.

 

[ 기타 참고 ]

https://code.google.com/p/javacv/downloads/list

 

 

 

 



:

[android] CheckBox에서 image와 text 간격

android 2013. 6. 19. 03:51

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

안드로이드에서 checkbox를 사용할 때 주의점이 있다. Check 이미지와 text의 간격을 조정하기 위해서는 paddingLeft를 사용하는데, XML에서 사용하면 API 16 이하에서는 동작하지 않는다. ( API 17 : 젤리빈 에서 수정되었다. )

 

<CheckBox

android:id="@+id/twitter_connect_checkbox"

android:button="@drawable/ selector_common_checkbox"

android:layout_alignParentLeft="true"

android:layout_marginLeft="10dp"

android:paddingLeft="5dp"

android:text="@string/some_text " />

 

android의 버전별로 호환성을 유지하기 위해서는, 위의 paddingLeft XML에서는 빼고 코드로 처리하는 것이 바람직하다.

final float scale = getResources().getDisplayMetrics().density;

checkBox.setPadding(checkBox.getPaddingLeft() + (int)(30.0f * scale + 0.5f),

checkBox.getPaddingTop(),

checkBox.getPaddingRight(),

checkBox.getPaddingBottom());

                     

다른 방법으로는 drawableLeft 사용하여 이미지를 표시하고, 이미지의 간격 조정은 drawablePadding으로, 텍스트의 간격 조정은 paddingLeft 등으로 처리하는 것이다.

아래는 checkbox 대신 ToggleButton으로 변경하여 처리한 방법이다.

 

<ToggleButton

android:id="@+id/twitter_connect_checkbox"

android:drawableLeft="@drawable/ selector_common_checkbox"

android:drawablePadding="5dp"

android:layout_alignParentLeft="true"

android:layout_marginLeft="10dp"

android:paddingLeft="5dp"

android:text="@string/some_text " />

 

drawableLeft, drawableRight, drawableTop, drawableBottom 등으로 component의 원하는 위치에 이미지를 설정할수 있다.  drawablePadding 값은 컨트롤 내부에서 이미지의 간격을 조정하는 값이다. paddingLeft는 이미지와 텍스트사이의 간격을 설정한다.

 

drawableXXX 기능은 TextView에 있는 기능으로 TextView parent로 하는 Button 계열의 컨트롤에서는 모두 사용가능한 방법이다. CheckBox의 상속 구조는 아래와 같다.

CheckBox -> CompoundButton -> Button -> TextView -> View

 

CheckBox ToggleButton interface가 상당히 유사해서 대부분 서로 대체해서 사용할수 있으므로 checkBox의 에러가 android 4.2에서 수정되었으므로 imagetext를 표시해야 하는 부분에서 checkbox 대신에 ToggleButton을 사용하길 권장한다.

( 안드로이드는 TextView에 참 많은 기능이 들어 있다. )

 

 



:

[android] Volley - Network & ImageLoading 라이브러리 ( google I/O 2013 )

android 2013. 5. 31. 14:32

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

Google I/O 2013에서 volley 라는 새로운 라이브러리를 발표했습니다. 주요 역할은 Http통신 및 이미지 로딩을 해주는 것입니다.

 

주요 특징

* requestQueue를 이용한 동시요청 처리

* 요청 우선순위 설정 가능 ( A요청이 B요청보다 먼저 응답을 받아야 할 경우 )

* 요청 취소 기능 ( adapter 같은 곳에서 scrolling 이 빠른경우 응답이 않왔을때는 취소가 필요하죠. )

* android 하위 버전(2.3)에서 존재하던 HttpURLConnection의 버그 해결

* NetworkImageView 제공

 

Google I/O의 발표영상

 

 

초간단 사용법

 

// 초기화

mQueue = Volley.newRequestQueue(context);// thread pool(4)

            

mImageLoader = new ImageLoader(mQueue, new BitmapCache());

기본으로 4개의 thread pool을 사용하게 되어 있다. 

 

 

// requestQueue 이용

final ImageView imageView = (ImageView) findViewById(R.id.image_view);

 

// clear

imageView.setImageBitmap(null);

 

// start load

Listener<Bitmap> listener = new Listener<Bitmap>() {

@Override

public void onResponse(Bitmap result) {

imageView.setImageBitmap(result);

}

};

 

ErrorListener errorListener = new ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

       // error handling

       }

};

 

ImageRequest imageRequest = new ImageRequest(URL_IMAGE, listener, 0, 0, Config.ARGB_8888, errorListener);

imageRequest.setTag(TAG);

mQueue.add(imageRequest);

 ImageRequest를 생성해서 큐(queue)에 넣어주면 되는데, ImageRequest에  url과 성공, 실패시 처리할 리스터(listener)를 넘겨준다.

 

// NetworkImageView 이용

NetworkImageView imageView = (NetworkImageView) findViewById(R.id.network_image_view);

 

// clear

imageView.setImageUrl(null, null);

 

// start load

imageView.setImageUrl(URL_IMAGE, mImageLoader);

NetworkImageView는 정말 간단하다. 그냥 url 과 imageLoader만 넘겨주면 된다.  

 

// GET 호출 ( with parameter )

Listener<String> listener = new Listener<String>() {

                    @Override

                    public void onResponse(String result) {

                           // some action

                    }

             };

 

String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s&param2=%2$s", num1, num2);

             StringRequest myReq = new StringRequest(Method.GET,

                    uri,

                    listener,

                    errorListener);

             mQueue.add(myReq);

GET 방식으로 이미지 호출이 아닌 api 호출해서 data를 받아 오는 경우도 흔하므로 위와 같이 StringRequest 이용해서 사용하면 된다. Parameter Get  방식이므로 url 전달하면 된다. ( Json 형식을 사용할땐, StringRequest 대신에 JsonRequest를 사용하면 된다. )

 

// POST 호출 ( with parameter )

StringRequest myReq = new StringRequest(Method.POST,

                    "http://somesite.com/some_endpoint.php",

                    listener,

                    errorListener) {

 

                    @Override

                    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {

                           Map<String, String> params = new HashMap<String, String>();

                           params.put("param1", num1);

                           params.put("param2", num2);

                           return params;

                    };

             };

             mQueue.add(myReq);

Post로 호출할 경우에는 StringRequestgetParams() 함수를 overriding 해주면 된다. 리턴형식으로 Map<String, String>을 사용하므로 여러 개의 파라미터를 전달 할 수 있다.

 

 

<참고>

valley : https://android.googlesource.com/platform/frameworks/volley

샘플 : https://github.com/ogrebgr/android_volley_examples

 

 

 



: