Tech/Android 개발2015.07.09 18:29

Android Studio에서 Junit 기반 단위 테스트(Unit Test) 환경 구축하기

안드로이드 Instrumentation 테스트의 경우에는 안드로이드 장치 또는 시뮬레이터에 직접 테스트 코드를 올려서 테스트가 진행됩니다. 이러한 과정 때문에 비교적 느립니다. 다른 방식으로 데스크탑 환경에서도 테스트를 할 수 있습니다. 이 방식에서는 보통 Junit을 기반으로 다양한 Mocking 라이브러리 또는 Robolectric과 같은 프레임워크를 사용하여 테스트가 진행됩니다. 이 포스트에서는 이런 방식의 가장 기본이 되는 Junit 테스트 환경을 구축하는 방법에 대해 설명하겠습니다.


진행환경

* Window 8.1  /  * Android Studio 1.2.2


1. 프로젝트 생성

Blank Activity 프로젝트를 기본 옵션으로 하나 생성합니다.


2. Unit Test 폴더 구조 생성

안드로이드에서 Instrumentation 테스트의 경우는 src/androidTest/java를, Junit 테스트의 경우에는 src/test/java를 기본 테스트 폴더로 인식합니다. 

프로젝트를 생성하시면 기본적으로 androidTest 폴더가 생성되어있을 것입니다. 상단 좌측의 프로젝트 구조 보기를 'Project'로 선택하시고 androidTest폴더에서 우클릭 -> Refactor -> Rename 을 통해 test로 이름을 변경하면 됩니다.


3. 빌드 스크립트에 Junit 추가

app의 build.gradle 파일을 열어서 dependency에 testCompile 구문을 추가합니다.

dependencies {
  ...
  testCompile 'junit:junit:4.12'
  ...
} 

메뉴에서 Tools -> Android -> Sync Project with Gradle Files 를 선택해 Gradle 파일을 Sync 시켜 줍니다.


4. Test Artifact 설정

좌측 하단 Build Variant 탭을 클릭한 후 Test Artifact를 Unit Tests로 설정해 줍니다.

여기까지 하시면 안드로이드가 java 폴더를 테스트 폴더로 인식하여 첫번째 사진과 같이 초록색 아이콘 으로 표시되어야 합니다.


5. Unit Test 코드 작성

이제 환결 설정은 다 끝났습니다! 작동하는지 알아보기 위해 간단히 Calculator 클래스를 만들어서 두 정수를 더하는 메소드를 테스트 해보겠습니다.

아래와 같이 Calculator랑 CalculatorTest 클래스를 생성하고 코드를 써줍니다.

 Calculator.java

CalculatorTest.java 

public class Calculator {
  public int add(int a, int b) {
    return a+b;
  }
}

import org.junit.Test;
import static org.junit.Assert.assertTrue;

public class CalculatorTest {
  @Test
  public void testAdd() {
    Calculator calculator = new Calculator(); 
    int actual = calculator.add(10, 10); 
    int expected  = 10+10;
    assertTrue(actual == expected);
  }
}


6. 테스트하기

테스트 java 폴더에서 우클릭 -> Run -> All Tests를 통해 테스트를 실행할 수 있습니다. 성공하면 아래와 같은 결과가 나옵니다.

끝!


참조

https://developer.android.com/training/testing/unit-testing/local-unit-tests.html
http://tools.android.com/tech-docs/unit-testing-support


신고
Posted by 비둘기야
Tech/Android 개발2015.06.19 17:02

SignalR 이란?

웹 서버와 브라우저 간의 실시간 양방향 통신을 위해 HTML5 표준인 WebSocket이 있습니다. 그러나 아직 WebSocket이 지원되지 않는 환경이 많습니다. Signal R은 MS에서 만든, 추상화를 통해 단일한 API로 서버와 클라이언트 간의 실시간 양방향 통신을 가능하게 해주는 라이브러리입니다. 내부적으로는 환경에 따라서 WebSocket을 사용하기도 하고 Long Poliing을 사용하기도 하는 등 다양한 방식을 사용합니다. 또한, 이러한 기능을 하는 대표적인 라이브러리로는 Node.js 기반의 Socket.IO가 있습니다! 


Android에서 SignalR 사용하기

만들려고 하는 예제

  • 서버와 클라이언트 허브에 각각 'hello' 라는 메소드가 있고 이 메소드는 문자열 하나를 인자로 받습니다.
  • 안드로이드 클라이언트에서 서버에 hello 메소드를 통해 문자열을 보내면 서버도 클라이언트로 hello 메소드를 통해 같은 문자열을 보냅니다.
  • 안드로이드 앱은 서버로부터 문자열을 받으면 Toast 메시지로 이를 보여줍니다.

구현하기 

1. 라이브러리 추가
signalR 자바 및 안드로이드 버전 클라이언트 라이브러리와 gson이 필요합니다. signalR 라이브러리들은 현재 jar을 공식적으로 받을 수 있는 곳은 없고 github 저장소에서 소스를 빌드하여 사용하셔야 합니다. gson은 로컬에 jar이 없어도 jcenter나 maven 저장소의 dependency를 지정함으로써 사용할 수 있긴합니다. 일단 이 예제를 진행하면서 빌드해 놓은 라이브러리 파일들과 bintray에서 받은 gson jar 파일을 첨부합니다. 

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.google.code.gson:gson:2.3.1' compile files('libs/signalr-client-sdk.jar') compile files('libs/signalr-client-sdk-android.jar') }


2. Permission 추가 

네트워크 통신을 사용하므로 <uses-permission android:name="android.permission.INTERNET"/> 를 Android Manifest 파일에 추가해 줍니다.


3. 멤버변수 선언

public class MainActivity extends ActionBarActivity {

    HubConnection mConnection;
    HubProxy mHub;

MainActivity.java를 생성하고 통신의 주체가 되는 모듈인 HubConnection 과 HubProxy를 선언해 줍니다. 여러 곳에서 사용되기 때문에 이번 예제에서 간편함을 위해 멤버변수로 선언하였습니다.


4. 연결 설정 및 초기화

    private void initialize() {
        String serverUrl = "http://server.url";
        String hubName = "hubName";

        Platform.loadPlatformComponent(new AndroidPlatformComponent());
        mConnection = new HubConnection(serverUrl);
        mHub = mConnection.createHubProxy(hubName);
    }

SignalR 서버 Url과 서버에서 사용하는 hubName을 설정합니다. 


5. 메시지 받을 준비 하기

    private void prepareGetMessage() {
        mHub.on("hello", new SubscriptionHandler1<String>() {
            @Override
            public void run(final String msg) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
                    }
                });
            }
        }, String.class);
    }

Hub의 on 메시지를 통해서 서버가 hello 메소드를 호출할 경우의 리스너를 등록합니다. 앞서 말씀드렸듯이 이 메소드는 인자를 하나만 받기 때문에 리스너로 SubscriptionHandler1을 사용하였습니다. 인자가 여러 개일 경우 개수에 따라서 SubscriptionHanlder2, SubscriptionHanlder3, ... 클래스를 사용하시고 알맞은 클래스 타입을 설정해주면 됩니다. 
( 안드로이드는 아직 Java8을 지원하지 않아 Lambda Expression을 사용하지 못하여 코드가 상당히 기네요ㅜㅜ ) 


6. 연결 성립하기

private void connectToServer() { try { SignalRFuture<Void> awaitConnection = mConnection.start(); awaitConnection.get(); Toast.makeText(this, "Connected", Toast.LENGTH_LONG).show(); } catch(Exception e) { Log.e("SignalR", "Failed to connect to server"); } }

동기 방식(Synchronous)으로 연결을 합니다. 따라서 Exception 없이 awaitConnect.get() 구문이 수행되고 나면 연결이 성립되었다고 볼 수 있습니다. 안드로이드에서 네트워크 통신 작업은 UI Thread에서 수행이 불가능하지만 위 메소드는 UI Thread에서도 호출이 가능합니다. 왜냐하면 실질적인 통신작업은 사실상 비동기로 이루어지고 awaitConnect.get()이 세마포어를 획득하기 위해 기다리는 식으로 구현되었기 때문입니다. 


7. 메시지 보내기

    private void sendMessage(String msg) {
        try {
            mHub.invoke("hello", msg).get();
        } catch( Exception e ){
            Log.e("SignalR", "Fail to send message");
        }
    }

Hub의 invoke 메소드를 통해 서버 Hub 메소드를 호출하는 식으로 메시지를 보냅니다. 이 역시 연결 성립할 때와 같은 방식으로 동기로 진행되며 UI Thread에서도 사용 가능합니다.


8. 연결 해지

    @Override
    protected void onDestroy() {
        mConnection.stop();
        super.onDestroy();
    }

stop 메소드를 통해 연결을 해지합니다. 이 예제에서는 앱의 onDestory가 호출 될 때 연결 해지를 하였습니다! 


9. 최종 결과 앱


지금까지 말씀드린 내용을 구현한 소스파일을 첨부합니다.

activity_main.xml

MainActivity.java


참조

Github : SignalR/java-client

Github : SignalR/java-samples

Getting Started with the Java SignalR SDK



신고
Posted by 비둘기야
Tech/Android 개발2015.04.13 10:31

알려진 안드로이드 HLS 스트리밍 이슈들

안드로이드에서 HTML video 태그를 이용하여 HLS를 서비스할 경우 정상적인 시청 환경을 제공할 수 없을 정도로 이슈가 많다는 것은 널리 알려진 사실입니다. 아래는 대표적인 HTML5 동영상 플레이어 중 하나인 JWPlayer에서 정리한 이슈 입니다.


Android 2.3 (Gingerbread)
  · 지원 안함
Android 3.0 (Honeycomb)
  · HLS 스트림이 장치와 충돌을 일으킨다.
Android 4.0 (ICS)
  · VOD에서 seek 불가능
  · 영상 가로세로 비율이 감지되지 않아 이미지 변형을 일으킨다.
  · 전체화면 진입시 영상이 처음부터 다시 시작된다.
Android 4.1+ (Jelly Bean)
  · 영상 가로세로 비율 이슈는 수정되었지만 여전히 seek이 불가능하다.
  · 크롬에서 HLS를 인식하지 못해 mimetype 을 감지하지 못한다.
  · 전체화면 진입 시 오류가 발생하고 장치가 멈춘다.


Seek 불가, 화면 비율 깨짐, 전체화면 진입시 오류 발생 등 굵직한 이슈들이 많이 보입니다. 


2015년 4월, 국내 주요 기기들에서의 안드로이드 HLS 이슈

위 JWPlayer 포스트는 약 2년전인 2013년 2월 27에 작성되었습니다. 모바일 세상에서의 변화의 속도를 감안하면 결코 짧지 않은 약 2년여의 시간이 지난 지금은 이슈들이 많이 없어졌을까요? 자이닉스에서 현재 사용되고 있는 국내 주요 기기들에서도 이슈들이 발생하는지 테스트를 진행해 보았습니다. 

테스트 환경

1) 서버 환경
 Wowza 3.6.2

2) 테스트 기기 목록

 번호

기기명 

 운영체제

제조사

발매일 

 Galaxy S3

 4.1 (Jelly Bean)

 삼성 

 2012.09

 Galaxy Note2

 4.4 (KitKat) 

 삼성

 2012.09

 Galaxy Note3

 4.4 (KitKat)

 삼성

 2013.09

 Galaxy S5

 5.0 (Lollipop) 

 삼성

 2014.03

 VEGA Racer

 4.1 (Jelly Bean) 

 팬텍

 2011.06

 VEGA IRON2

 4.4 (KitKat)

 팬텍

 2014.05

 Optimus LTE2

 4.1 (Jelly Bean) 

 LG

 2012.05

 LG G Pro2

 4.4 (KitKat)

 LG

 2014.02

 Nexus5

 5.1 (Lollipop)

 LG

 2013.10

* 위 테스트 기기들에 대해 기본 브라우저 및 Chrome 에서 진행
* 단 Nexus5는 Chrome이 기본 브라우저여서 Chrome만 진행함.
* Chrome 버전은 41로 테스트를 진행

테스트 결과

이슈 내용 

 발생한 환경

 영상이 가로세로 비율이 무시되고 화면에 꽉찬다.

 ① Galaxy S3-기본 브라우저
 
② Galaxy Note2-기본 브라우저

 전체화면[각주:1] 진입 시 영상의 끝으로 간다.

 ① Galaxy S3-기본 브라우저

 현재 시간이 계속 0초로 남아있다.

 ① Galaxy S3-Chrome
 
⑤ VEGA Racer-Chrome

 Seek이 불가능하다.

 ① Galaxy S3-Chrome
 ② Galaxy Note2-Chrome
 
⑤ VEGA Racer-Chrome

 영상 전체 길이가 짧아진다. ( 예: 59분 59초 영상 -> 56분 45초 )

 ② Galaxy Note2-기본 브라우저
 
③ Galaxy Note3-기본 브라우저, Chrome
 
⑤ VEGA Racer-Chrome
 
⑥ VEGA IRON2-기본,브라우저, Chrome

비교적 최신 기기들과 OS에서는 이슈가 없는 경향을 보이지만 테스트 표본이 작고 명시적으로 보장한다는 명세가 없어 확신은 할 수가 없습니다. 또한 나온지는 조금 지났어도 아직 제법 높은 점유율을 가지고 있는 Galaxy S3나 Note2등의 기기에서는 확실히 정상적인 시청이 불가능할 정도의 많은 이슈가 있습니다. 따라서 아직까지는 안드로이드 HTML5에서 HLS 스트리밍을 제공하기에는 많은 어려움이 따른다는 결론을 낼 수 있을 것 같습니다.


안드로이드 네이티브 App으로 HLS 스트리밍을 할 때의 이슈

안드로이드 HTML HLS 스트리밍의 대안으로써 네이티브 앱을 제작하는 방법이 종종 제안되고는 합니다. 간단히 시청만 가능한 프로토타입 앱[각주:2]을 제작하여 위와 같은 테스트 환경에서 확인해 보았습니다. 다수의 기기에서 어느정도 시청은 가능한 수준이라고 볼 수 있으나, 아래와 같은 공통적인 이슈가 발생하였습니다. 또한 아래 이슈들은 내장 플레이어에서도 동일하게 발생함을 확인하였습니다.

이슈내용
 * 영상 전체 길이가 짧게 나타난다. (59분 59초 영상 -> 56분 45초)
 * Seek시 Seek한 시간보다 뒤로 이동한다. ( 25:00 Seek -> 26:30으로 이동 )
 * 작게 측정된 전체 시간 이후의 시간을 재생하고 있는 동안은 Seek이 안 되는 현상 발생

발생 기기
 
① GalaxyS3② Galaxy Note2, ③ Galaxy Note3, ⑤ VEGA Racer


  1. 전체화면은 video 엘리먼트의 webkitEnterfullscreen 메소드를 의미합니다. [본문으로]
  2. 안드로이드 SDK의 VideoView를 사용 [본문으로]
신고
Posted by 비둘기야
Tech/Android 개발2011.04.15 12:21

Android 개발환경 설정

 

자 이제 우리도 안드로이드 개발을 해봅시다.

안드로이드 개발에 앞서 필요한 환경은 일단 세가지 입니다.

 

제일 먼저, 안드로이드는 JAVA를 기반으로 구현된 플랫폼 입니다.

그러니 JAVA개발환경부터 세팅을 해야하지요.

자 일단, JDK를 설치해 봅시다.

1. JAVA개발환경 설정

1.1  JAVA SDK설치

JDK에는 세가지 버전이 있는데, 가장 보편적인 SE(Standard Edition)을 사용하도록 합시다.

https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jdk-6u24-oth-JPR@CDS-CDS_Developer

이 링크를 따라가서 자신의 OS환경에 맞춰 다운을 받으시면 됩니다.

대략 80MB정도의 용량입니다.

다운받고 설치를 하시면, 이제 JAVA를 개발할 수 있습니다!

 


1.2
환경변수 설정

하지만, JAVA의 컴파일은 커맨드 기반으로 진행되기 때문에, 편의를 위해서 환경변수 등록을 해줍시다.

왜 환경변수 설정을 하느냐?

일단, JAVA개발에 있어서 가장 자주 사용하는 커맨드는 두개, 컴파일하는 javac, 실행하는 java 입니다.

이것을 환경변수를 설정하지 않고, 사용하려고 하면

 

 

이런 오류가 나옵니다.

커맨드를 사용하려면 실행파일이 있는 폴더까지 가서 실행해야 하는 불편함이 있지요.

현재 위치에 상관없이 어느 위치에서나 커맨드를 사용 가능하도록 하기 위해 환경변수를 설정하는 것입니다.

그럼 어디가서 환경변수를 설정하느냐?


시스템 속성창을 여시면 고급탭 하단에 환경변수 버튼이 보입니다.

버튼을 클릭하게 되면,



이런 창이 뜹니다.

여기서 아래 시스템 변수 영역에서 path변수에 JAVA의 실행파일들이 위치한 폴더를 추가해줍시다.


경로는 JDK가 설치된 폴더 하위의 bin폴더 입니다.

이렇게 환경변수를 설정하고 나서 다시 커맨드를 실행해봅시다.

 

 

아까와는 다르게 실행방법에 대한 설명이 주루루룩 나옵니다.

이제 JAVA개발환경은 준비가 되었습니다.


 

2.     Android SDK설치하기

이제 기반이 되는 JAVA는 설치를 마쳤으니, Android도 설치를 해봅시다.

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

JDK와 마찬가지로 자신의 OS에 맞춰 Android SDK를 다운 받아봅시다.

현재 설치형 버전과 압축형 버전 두가지가 제공되고 있는데, 별 차이는 없습니다.
다만 설치형이 조금더 편하기에 설치형을 사용해 봅시다.

40MB가 조금 못되는 용량입니다. 다운을 받고 설치를 진행하게 되면 다음과 같은 창이 뜹니다.


여기서 Android OS버전별 업데이트를 진행할 수 있습니다.

필수적으로 해야하는 업데이트는 Android SDK Tools, Android SDK Platform-tools 입니다.

업데이트까지 진행하고 나면, Android SDK설치는 완료되었습니다.

 

3. Eclipse 설치하기

3.1 Eclipse
설치


자 그럼 Android개발에 사용할 툴을 설치해봅시다.
Android
가 지원하는 개발툴은 Eclipse입니다.
그럼 이것도 설치를 해봅시다.

http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/helios/SR2/eclipse-jee-helios-SR2-win32.zip

대략 300MB정도 됩니다. 가장 크죠.

 

Eclipse는 설치가 필요없이 다운받아서 압축만 풀어서 사용할 수 있습니다.

다운받은 파일의 압축을 풀어봅시다.

압축을 풀게되면, 다음과 같은 파일들을 보실 수 있습니다.

 


이중에서 딱 봐도 아이콘이 있는 eclipse.exe를 실행해 봅시다.

 


처음 실행하게 되면, 위와 같은 창이 뜹니다. 프로젝트를 저장할 작업 폴더를 설정해줘야 합니다.
사용할 작업 폴더 경로를 입력하고 OK를 클릭합시다.

 


자 그러면 Eclipse는 설치가 완료되었습니다.

 

3.2 Toolkit설치

하지만, Android개발을 위해서는 또, 설정을 해줘야합니다.

뭐가 참 많죠? ㅠㅠ

일단 Android SDK와 연결을 위한 Toolkit을 설치해야 합니다.

 

메뉴의 Help -> Install New Software를 선택합니다.



그리고 화면 상단의 ADD버튼을 클릭하여, Toolkit을 다운 받을 경로를 설정해줍시다.


 

경로를 설정하게 되면, 설치가능한 툴킷목록이 주루룩 나옵니다.

  


일단 네가지 다 설치합니다.

 

다 설치하고 나면, 프로그램을 재시작하라는 다이얼로그가 뜹니다.

재시작!


 

3.3 Android SDK 경로 설정


다시 실행된 Eclipse를 보면 뭔가 Android스러운 아이콘들이 몇 개 보이기 시작합니다.

하지만 아직 끝나지 않았습니다.

이제 마지막 입니다.

Eclipse 2번에서 설치한 Android SDK를 연결하기 위해서 Android SDK가 설치된 폴더경로를 지정해 주어야 합니다.

메뉴의 Window -> preferences 를 클릭해보시면

 


이런 창이 뜹니다.

목록중에 Android가 보이시죠?

저기에서 설정하면 됩니다.

 


이렇게 SDK가 설치된 폴더경로를 설정해주고, Apply를 클릭하면 설치된 Android버전들이 주루룩 나타납니다.
OK
를 누르시면 종료!

자 이제 Android개발을 위한 환경 설정을 마쳤습니다.

 

4. Hello! World!

4.1 프로젝트 생성하기

자 그럼 다 설치했으니, 설레는 마음으로 Hello! World!를 해봅시다.

먼저 프로젝트를 생성합니다.


좌측의 Package Explorer에서 우클릭을 통해 메뉴를 열거나 상단 메뉴의 File -> New 에 보시면 Android Project가 보입니다! (보이지 않는 경우에는 맨 아래의 Other를 클릭하시면 Android -> Android Project를 찾으실 수 있습니다) 꾹 눌러주시죠.

나타나는 창에서 어플리케이션에 대한 대략적인 설정을 해줘야 합니다.
OS
버젼, 어플리케이션 이름, 패키지 명, Activity(Main 역할을 합니다.)등을 작성하고 Finish를 클릭합니다.

프로젝트를 생성하면 기본적으로 Hello World가 템플릿 형식으로 구현되어 있습니다.
그래서 바로 실행을 해보도록 합시다.

Package Explorer영역의 프로젝트에서 우클릭후 Run As-> Android Application을 클릭합니다.

 


4.2 Virtual Device
생성하기

 

 


실행하려고 하면 위와 같이 다이얼로그가 뜹니다.
아직 만들어진 에뮬레이터가 없어서 만들라는 얘기지요. Yes를 클릭해서 한번 만들어봅시다.

  


우측 상단의 New를 클릭합니다.

에뮬레이터의 이름과 대상OS버젼, SD카드 사이즈를 설정하고 Create AVD를 클릭합시다.


이제 에뮬레이터가 만들어졌습니다.

 


4.3 Hello! World!


자 이제 준비는 끝났습니다. 좀 전과 같이 프로젝트를 실행하면


짜잔 에뮬레이터가 실행됩니다. (대략 시간이 좀 걸립니다 -_-)

 


Hello World!!
이렇게 대략적으로 Android 개발 준비를 마쳤습니다!!

이제 다함께 삽질의 세계로~


신고
Posted by 즐회장님