Android/App개발2011. 9. 3. 18:33


Locale을 생성 후 updateConfigurations로 변경한다.
 

Locale locale = new Locale("ko"); 

Locale.setDefault(locale);

Configuration config = new Configuration();

config.locale = locale;

getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());


변경 후 액티비티를 다시 시작하여야 변경된 로켈이 적용된다.
 
finish();

Intent myIntent = new Intent(MainActivity.this, MainActivity.class);

startActivity(myIntent);


이렇게 하면 해당 액티비티에만 적용된다.
액티비티를 시작할 때 이전에 선택한 로켈로 시작되게 하려면 onCreate에서 지정해야 한다.

onCreate(..) {
         Locale locale2 = new Locale("en"); 

    Locale.setDefault(locale2);

        Configuration config2 = new Configuration();

        config2.locale = locale2;

        getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());


        setContentView(R.layout.main);

}

setContentView(.)보다 이전에 설정해주어야 한다.

만일 이렇게만 하면 런타임에 로켈을 바꾸면 화면이 점점 더 작아지는 황당한 상황을 겪을 것이다.
Manifest에 다음을 추가해라.

<supports-screens

android:smallScreens="true"

android:normalScreens="true"

android:largeScreens="true"

android:anyDensity="true"

/>




 
Posted by 삼스
Android/App개발2011. 6. 16. 18:31

안드로이드 개발시 유닛테스트를 하는 방법에 대해 정리한다.

두가지 케이스정도로 정리해보면
 1. 액티비티 테스트 : UI 테스트 자동화
 2. 클래스 테스트 : 로직을 담고 있는 클래스들을 테스트 자동화

방법은 Android project를 만들 때 Android Test Project로 만든다. 이 때 테스트하고자 하는 앱을 지정하게 되어 있다. 
 
1. 액티비티 테스트 
 -  ActivityInstrumentationTestCase2를 확장
public class HelloActivityTest extends ActivityInstrumentationTestCase2<HelloActivity> 
 - 일부 메소드 override
protected void setUp()
protected void tearDown()
 - test 메소드들 구현
 - Activity에 접근은 this.getActivity()로 가능하다. 

2. 클래스 테스트
 - InstrumentationTestCase 를 확장
 
 public class MetadataManagerTest extends InstrumentationTestCase 
 - 일부 메소드 override
protected void setUp()
protected void tearDown()
 - test 메소드들 구현
 
AsyncTask를 테스트할 때는 CountdownLatch를 이용해서 비동기 스레드를 테스트 할 수 있다.
출처 : http://kingori.egloos.com/4554640
public class AsyncTaskTest extends InstrumentationTestCase {

  public void testAsyncTask() {
    final Data data = new Data();
    final CountDownLatch signal = new CountDownLatch(1); // countdown 1을 기다리는 랫치

    Callback a = new Callback() {
      onPrepare() { data.val = 1; }
      onSuccess() { data.val = 2; signal.countDown();} // 작업이 끝나면 1을 내려 유닛테스트 쓰레드가 진행되게 한다.
      onFail() { data.val = 3; signal.countDown(); } // 실패할 수도 있으니..
    }

    runTestOnUiThread( new Runnable() {
      public void run() {
        Manager.getInstance().doSomething(a);
      }
    });
    signal.await(); // 랫치 값이 0이 될 때 까지 대기 상태
    assertEquals( data.val, 2 ); //결과 확인
  }
}

Posted by 삼스
Android/App개발2011. 6. 10. 13:08
http://www.hanb.co.kr/network/view.html?bi_id=1033
 

저자:
 김대곤

Java Native Interface에 관련된 서적을 찾으려고 아마존을 뒤적일 때, 다음과 같은 서평을 보게 되었다. “한 가지 분명한 사실은 JNI를 쓰지 않는 것이 훨씬 좋다는 것이다. JNI는 다루기 힘들고, 불안정하며, 에러가 발생할 소지가 많으며, 무엇보다도 JNI가 쏟아내는 Runtime 에러는 자바 가상 머신을 날려 버릴 수 있는 사악한 기술이다.” 이 서평을 쓴 사람은 그 책을 사서 봤을 것이며, 단지 관심에서가 아니라 심각하게 Java Native Interface를 사용했을 것이며, 아마도 사용하고 있을 것이다. JNI는 자주 사용되지는 않지만, 그렇다고 불필요한 기술도 아니다. 아니 절대적으로 필요한 기술임이 틀림없다.

Java Native Interface는 자바에서 다른 언어로 개발된 기능을 내부적으로 사용할 수 있게 해 준다. 이미 C 언어나 C++로 개발된 기능이 있다면 그것을 자바 프로그램 안에서 사용할 수 있게 해 준다. 이 글은 JNI을 사용하는 두가지 간단한 예제를 통해 JNI가 무엇이며, JNI를 어떻게 사용하는지에 대해 간단히 살펴볼 것이다. 첫 번째 예제는 항상 등장하는 HelloWorld식 예제이고, 두 번째는 C 언어로 개발된 정렬 프로그램을 자바 프로그램에서 사용하는 예제이다. 

썬 자바 사이트에는 JNI를 구현하는 여섯가지 단계를 설명하고 있다.
1. Native 메소드를 호출하는 자바 코드 작성.
2. 첫 단계에서 쓴 자바 코드의 컴파일.
3. javah 명령어를 사용하여 헤더 파일의 생성.
4. 지정된 언어로 호출되는 Native 메소드를 구현.
5. Native 메소드를 구현한 코드를 동적 라이브러리로 컴파일.
6. 실행.

Native 메소드를 호출하는 자바 코드에는 세 가지 요소가 포함된다. Native 메소드의 선언, 실제 Native 메소드의 사용, 동적 라이브러리를 시스템 상에 상주하도록 불러오는 것이다. 이 세 가지는 아래 코드에서 강조되어 있다.


[HelloWorld.java]
/*
 * Created on 2004. 12. 31.
 * File name : HelloWorld.java
 * @author DaeGon Kim
 *
 */
public class HelloWorld {

              String greeting = "Hello Java World";

              public native void display();

              public static void main(String[] args) {

                            HelloWorld hw = new HelloWorld()
              System.out.println(hw.greeting);
                            hw.display();
                            System.out.println(hw.greeting);

              }

              static {
                            System.load("D:\\Project\\Java\\hello.dll");
              }

}


두 번째와 세 번째 단계에서는 javac 명령어로 HelloWorld.java를 컴파일한 후, javah 명령어로 헤더 파일을 생성한다. 
> javac HelloWorld.java
> javah HelloWorld
javah 명령을 실행하면, 아래에 보이는 HelloWorld.h가 생성되며, 이 파일을 수정하지 않는다.


[HelloWorld.h]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    display
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_display
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


헤더 파일에서 강조된 부분은 실제 C 언어로 구현되어야 하는 함수이다. JNIEXPORT와 JNICALL과 같은 자바와 관련된 용어의 등장에서 알 수 있듯이, 헤더 파일에 정의된 함수를 구현하는 C 파일을 컴파일하기 위해서는 자바 시스템에서 포함되어 있는 파일이 필요하다. 환경설정에 관한 설명은 C 파일의 컴파일 단계에서 설명하기로 하고, C 언어로 위 함수를 구현해 보자.


[HelloWorld.c]
#include 
#include "HelloWorld.h"
#include 


JNIEXPORT void JNICALL Java_HelloWorld_display(JNIEnv *env, jobject this) {

    jfieldID       fldid;
    jstring        greeting;
    const   char   *temp;

    // 넘겨지는 객체 this의 클래스를 가져온다.   
    jclass instance = (*env)->GetObjectClass(env,this);

    printf("   Start of C implementation.\n");
    
    if ( this == NULL ) {
        fprintf(stderr, "Input pointer is null!");
        return;
    }
    
    // 클래스 안에서 greeting이라는 속성이 가진 위치를 가져온다.
    fldid = (*env)->GetFieldID(env, instance, "greeting", "Ljava/lang/String;");
    
    if ( fldid == NULL ) {
        fprintf(stderr, "Failed to get the field id\n");
        return;
    } 
    
    // 실제 객체에서 fldid에 있는 값을 읽어온다.
    greeting  = (*env)->GetObjectField(env, this, fldid);
    // 일어온 값을 C 데이터로 변환한다.
    temp      = (*env)->GetStringUTFChars(env, greeting, NULL);
   
    printf("      %s \n", temp);

    // 자바의 String 필드에 저장할 값을 만든다.
    greeting = (*env)->NewStringUTF(env, "Hello C World");
   
    if ( greeting == NULL ) {
        printf("Out of memory\n");
        return;
    }
    
    // greeting에 저정돤 값을 자바 객체로 전달한다.
    (*env)->SetObjectField(env, this, fldid, greeting);

    printf("   End of C implementation \n");
   
    return;

}


이제 필요한 모든 파일을 갖추어졌다. 이제 컴파일하고 실행하는 일만 남아 있다. 컴파일 하기 위해서는 몇 가지 설정이 필요하다. 앞으로 기술되는 설정은 윈도우를 기준으로 하고 있고, 마이크로 소프트 C 컴파일러를 쓴다는 가정하에서 기술되었다. 먼저, jni.h가 필요하다. 이 파일은 자바 홈디렉토리(이하 JAVAHOME) 아래 include 디렉토리에 있으며, 그 아래에 있는 win32 디렉토리도 include에 포함되어 있어야 한다.

set INCLUDE=%JAVAHOME%\include;%JAVAHOME%\include\win32;%INCLUDE%

LIB 속성을 위해서는 JAVAHOME 아래에 있는 lib 디렉토리가 포함되어야 한다.

set LIB=%JAVAHOME%\lib;%LIB%

위에서 설명한 설정은 JNI를 사용하게 됨에 따라 추가적으로 해야 하는 설정이며, Command Prompt에서 VC7 컴파일러를 실행하고자 할 때는 다음의 설정이 추가적으로 필요하다.

INCLUDE : VC 홈 디렉토리 아래에 있는 include 디렉토리
LIB : VC 홈 디렉토리 아래에 있는 lib 디렉토리
PATH : Studio 홈 - Common7 아래에 있는 IDE, VC 홈 디렉토리 아래에 있는 bin 디렉토리.

이제 남은 일은 HelloWorld.c를 컴파일하고 HelloWorld를 실행하는 일만 남았다.

cl HelloWorld.c -Fehello.dll -MD -LD

위의 명령어를 실행하면 hello.dll 파일이 생성된다. 그리고 나서 HelloWorld 클래스를 실행하면 다음과 같은 결과를 얻게 될 것이다. 


Hello Java World
   Start of C implementation.
      Hello Java World
   End of C implementation
Hello C World


이것으로 첫 번째 예제가 성공한 것이다. 이 예제는 일반적으로 JNI가 사용되는 방식과 거리가 있어 보인다. JNI는 개발 중인 자바 어플리케이션이 있으며, 이미 개발된 Native 라이브러리가 존재한다. 두 번째 예제에서는 기존에 C 언어로 개발된 정수 정렬 함수를 자바에서 사용하는 예제이다. 

먼저 Sort.c를 살펴보자. 흔히 볼 수 있는 C로 구현된 Insertion 정렬 함수이다.


[Sort.c]
#include 
#include 

int *sortIntegers(int *A, int n) {
    
    int i   = 0;
    int j   = 0;
    int key = 0;
    
    for ( j=1; j < n ; j++ ) {
        key = A[j];
        i = j - 1;
        while ( i >=0 && A[i] > key ) {
            A[i+1] = A[i];
            i--;
        }
        A[i+1] = key;
    }
    
    return A;
    
}


Sort.h 에는 Sort.c 안에 구현된 함수의 리스트가 나열되어 있다.


[Sort.h]
int *sortIntegers(int *A, int n);


이제 이 함수의 기능을 사용하는 Sorting.java 를 작성하자.


[Sorting.java]
public class Sorting {

    public static native int[] sort(int[] A, int n);
    
    public static void main(String args[]) {
        
        int Input[] = {3,4,7,2,5,6,9,11,1,8,10};
        
        int sorted[] = sort(Input, Input.length);
        
        for (int i=0; i < sorted.length ; i++ ) {
            System.out.println("A[" + i + "] = " + sorted[i]  );
        }
    }
    
    static {
        System.load("D:\\Project\\Java\\sorting.dll");
    }
    
}


Sorting.java를 컴파일 하고, Sorting 클래스를 사용하여 Sorting.h 를 생성한다. 이제 남은 일은 HelloWorld.c 와 같은 입력값과 반환값을 전달해주는 C 프로그램이다. 


[Sorting.c]
#include 
#include "Sorting.h"
#include "Sort.h"
#include 

JNIEXPORT jintArray JNICALL Java_Sorting_sort(JNIEnv *env, jclass cl, jintArray arr, jint n) {

    jint       *A   = NULL;
    jintArray  temp = NULL;
    
    A = (*env)->GetIntArrayElements(env, arr, NULL);
    
    if ( A == NULL ) {
        fprintf(stderr, "Failed to get int array\n");
        return arr;
    }
    
    A = sortIntegers(A, n);
    
    temp = (*env)->NewIntArray(env, n);
    
    (*env)->ReleaseIntArrayElements(env, temp, A, 0);
    
    return temp;

}


Sorting.c 를 컴파일하자. 이 때 다음과 같은 에러가 발생한다면, 

“LINK : warning LNK4098: defaultlib 'LIBC' conflicts with use of other libs; use /NODEFAULTLIB:library”

Sorting.c 와 Sort.c가 다른 방식으로 컴파일 되었기 생긴 에러이다. Sort.c를 MD 옵션으로 다시 컴파일하면, 정상적으로 컴파일될 것이다. 이제 Sorting 클래스를 사용할 수 있다. Sorting 클래스를 실행하면 다음과 같은 출력을 보게 될 것이다.

A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 5
A[5] = 6
A[6] = 7
A[7] = 8
A[8] = 9
A[9] = 10
A[10] = 11


필자는 여기에서 어떻게 Wrapper 프로그램을 작성하는지에 대해서 설명하지 않았다. 하지만 앞에서 다룬 두 예제에는 Primitive 타입인 int, 배열, 객체를 다루었기 때문에 각 경우에 해당되는 함수 리스트만 있으면, 프로그램에 별 어려움이 없으리라 생각된다. 다음 기사에는 JNI가 자바 가상 머신을 날려버려 전체 자바 어플리케이션이 다운되는 것을 피해가는 방법에 대해서 살펴보도록 하자.
Posted by 삼스
Android/App개발2011. 6. 3. 16:42
http://sites.google.com/site/endihom/home/programming-language/android/article/listview-backgrounds

ListView 는 안드로이드에서 가장 널리 사용되는 위젯이다. 사용하기 쉽고, 매우 유연하며 강력하다. ListView는 가끔 이해하기 어려울수 있다.

ListView에서 나타나는 가장 공통된 이슈중에 하나는 커스텀 백그라운드를 사용하고자 할때이다. 다른 안드로이드 위젯처럼 디플트로 ListView는 반투명 배경을 가질수 있는데 이는 개발자가 매우 어두운 회색(현재 다크 테마에서는 #FF191919)디폴트 윈도우 배경을 통해 볼수 있다는 것을 뜻한다. 게다가 ListView는 fading edges를 기본적으로 제공한다. 아래의 스크린샷의 윗 부분을 보면 첫번째 아이템이 점차 검은색으로 페이드 되는것을 알수 있다. 이 기술은 스크롤되는 컨테이너를 가지는 시스템에서 전반적으로 사용된다.

Android's default ListView

패이드 효과는 Canvas.saveLayerAlpha() 와 Porter-Duff Destination Out blending 모드의 조합으로 구현되어 진다.

불행하게도, ListView에서 커스텀 배경을 사용하거나 윈도우의 배경을 변경할때 화면이 이상하게 보일 것이다. 아래 두개의 스크린샷은 윈도우 배경을 변경했을때 어플리케이션에서 어떤일이 일어나는지를 보여준다. 첫번째 화면은 디폴트로 리스트가 어떡해 보여지는지를 볼수 있고 두번째 화면은 터치 제스쳐를 통해 초기화되어 스크롤되는 동안의 모습이다.

Dark fade Dark list

이 랜더링 이슈는 안드로이드 프레임워크가 ListView의 모든 인스턴스에 기본적으로 적용된 최적화 기법에 의한 것이다. 앞서 언급한데로 페이드 효과는 Porter-Duff blending mode를 사용해 구현되었다. 이 구현방법은 정말 잘 동작하지만 화면에 보이지 않는 비트맵에서 렌더링의 일부분을 캡쳐해야 함으로서 매우 고비용이며 드로잉 성능을 저하시킬수 있다. 그래서 추가적인 blending(메모리로부터 다시 읽어 들이는 것을 의미)이 필요하다 

ListView는 거의 대부분 고정 배경화면에서 디스플레이되기 때문에 고비용이 드는 작업으로 내려갈 이유가 없다. 이것이"cache color hit"라 불리는 최적화를 소개하는 이유다. 캐쉬 컬러 힌트는 윈도우의 배경색에 기본적으로 설정되어 있는 RGB색으로 안드로이드 dark테마에서 #191919이다. 이 힌트가 설정되면 ListView(사실 이 클래스의 부모 클래스)는 단일 배경화면으로 그릴 것이므로 고비용의 saveLayerAlpha()와 Porter-Duff 렌더링을 단순한 그레디언트로 대체할수있다는 것을 알게 된다. 이 그레디언트는 완전히 투명한 컬러에서 캐시 컬러 힌트 값까지 그레디언트 되고 이미지 위에서 리스트 바닥에 dark 그레디언트된 보고자 하는 바로 그것이다.

앞서 언급한데로 Listview와 안드로이드 UI 툴킷의 모든 기본 위젯들은 기본적으로 투명/반투명 배경을 가지진다. 이것은 ListView가 child를 다시 그릴때 윈도우 배경과 child를 반드시 혼합(blend)해야한다는 것을 뜻한다. 다시 한번 말하지만, 이것은 고비용의 메모리 다시 읽기를 초래하며 이 메모리 다시 읽기는 초당 수십번의 다시 그리기가 발생하므로 스크롤이나 플리핑하는동안 성능이 매우 떨어지게된다.

스크롤하는 동안 그리기 성능을 향상 시키기 위해 안드로이드 프레임워크는 cache color hint를 재사용한다. 이 힌트가 설정되면 프레임워크는 힌트값(scrolling cache라는 또다른 최적화 기법이 적용되지 않은 상태라고 가정하자)으로 채워진 비트맵안 리스트의 child를 복사한다. 그럼 다음 ListView는 화면에 비트맵을 직접 그린다. 비트맵은 불투명하므로 혼합(blending)이 필요하지 않다. 기본 cache color hint는 #191919이므로 스크롤 되는 동안 각 아이템의 뒤에서 dark 배경색을 볼수 있다.

만약 단일 배경색을 가지지 않거나 hint를 적절한 단일 컬러 값으로 설정한다면 이 이슈를 해결하기 위해 cache color hint 최적화 방법을 꺼 두어야 한다. 코드(setCacheColorHint(int) 참고)나 XML을 적절히 사용(android:cacheColorHint 속성)하여 이 작업을 수행할 수 있다. 최적화를 꺼두기 위해 단순히 투명색 #00000000을 사용하라. 아래의 화면은 XML 레이아웃 파일에 android:cacheColorHint="#00000000"으로 설정한 리스트를 보여준다.

Fade on a custom background

보는것 처럼 나무느낌의 배경화면에서 페이드 효과는 완벽하게 동작한다. cache color hint 기능은 최적화가 어떤 상황에서 개발자를 매우 힘들게 할수도 있으므로 흥미롭다. 하지만 이 특별한 상황에서 기본 동작의 이점은 증가된 복잡도 보다 더 크다.


Posted by 삼스
Android/App개발2011. 6. 2. 13:40


JNI, jstring type example
Java의 String 을 JNI에서 다루는 예

JNI Functions Reference : http://download.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html#wp17314

JNITest.java

public class  JNITest
{
 static{
  System.loadLibrary("my_dll");
 }

 public native String greeting(String name);

 public static void main(String[] args) 
 {
  JNITest test = new JNITest();
  String result = test.greeting("Smith");
  System.out.println("C 함수 리턴값:  "+result);
 }
}



JNITest.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNITest */

#ifndef _Included_JNITest
#define _Included_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNITest
 * Method:    greeting
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */

JNIEXPORT jstring JNICALL Java_JNITest_greeting
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif





my_dll.c

#include <stdio.h>
#include "JNITest.h"
#include <string.h>

JNIEXPORT jstring JNICALL Java_JNITest_greeting
  (JNIEnv *env, jobject obj, jstring jstr) {

 const char *name = (*env)->GetStringUTFChars(env, jstr, NULL);//Java String to C Style string
 char msg[60] = "Hello ";
 jstring result;

 strcat(msg, name);
 (*env)->ReleaseStringUTFChars(env, jstrname);
 puts(msg);

 result = (*env)->NewStringUTF(env, msg); // C style string to Java String
 return result;

}



Posted by 삼스
Android/Porting2011. 5. 25. 14:28

MP3 encoder가 필요해서 작업중이엇는데 누가 아주 잘 설명을 해두었네요.
필요하신 분들을 step by step으로 따라하심 됩니다.

http://blog.libertadtech.com/2011/02/porting-lame-encoder-to-android-arm.html
 

porting compiling lame encoder to Android ARM arch using Android NDK

I was looking for a mp3 encoding application in Android Market, and found very few, the reason I think Android doesn't support mp3 encoding is because mp3 is patented technology. Another reason is I guess people prefer Java programming and Android SDK rather than Android native development kit.

Nevertheless compiling libmp3lame library for Android using Android NDK is very easy actually.
1. download Android NDK(also you need Android SDK and Eclipse with ADT plugin) and create simple project.
2. create directory called "jni" in your project's directory.
3. download lame sources, extract, copy all sources from directory libmp3lame to jni directory. Also copy lame.h which is located in include directory of lame sources.
4. create jni/Android.mk file. it should look like this:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := mp3lame
LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c  quantize.c   reservoir.c tables.c  util.c  VbrTag.c encoder.c  gain_analysis.c lame.c  newmdct.c   psymodel.c quantize_pvt.c set_get.c  takehiro.c vbrquantize.c version.c
include $(BUILD_SHARED_LIBRARY)
5. clean lame sources, remove what's left from GNU autotools, Makefile.am Makefile.in libmp3lame_vc8.vcproj logoe.ico depcomp, folders i386 vector.
6. edit file jni/utils.h, and replace definition extern ieee754_float32_t fast_log2(ieee754_float32_t x);
with this extern float fast_log2(float x);
7. go to the root directory of your Android project and run $pathtoandroidndk/ndk-build and you're done, you'll have limp3lame.so compiled. 
Posted by 삼스
Android/App개발2011. 5. 11. 11:02

Intent.ACTION_SEND를 이용하여 Email, MMS 앱에 파라메터를 번들형태로 넘겨서 해당 액티비티를 호출하는 것이 가능하다.

Email의 경우 아래와 같이 하면 된다.


Intent i=new Intent(Intent.ACTION_SEND); 

i.addCategory(Intent.CATEGORY_DEFAULT); 

    

// for EMail
// mimetype

i.setType("text/plain");
i.putExtra(Intent.EXTRA_SUBJECT, "제목입니다."); 

i.putExtra(Intent.EXTRA_TEXT, "본문이구요 ....");

i.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"user1@website.com"}); 

i.putExtra(Intent.EXTRA_CC, new String[]{"user_cc1@website.com"user_cc2@website.com"}); 

i.putExtra(Intent.EXTRA_BCC, new String[]{"user_bcc1@website.com"}); 

// 파일 첨부
i.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/mic_rec3.wav"));

// 앱선택 박스를 띄움.

startActivity(Intent.createChooser(i, "How do you want to send message?"));


MMS의 경우는 아래와 같이 Extra정보를 설정한다.    

// for MMS

i.putExtra("address", "07011111111;01022222222");

i.putExtra("exit_on_sent", true);

i.putExtra("sms_body", "MMS 테스트입니다."); 

startActivity(Intent.createChooser(i, "How do you want to send message?"));


앱선택박스를 띄우지 않고 바로 특정 앱(MMS, GMail)으로 바로 연결되도록 하려면 해당하는 액티비티 Component를 Intent에 등록하면 된다.

// com.google.android.gm 패키지의 ComposeActivityGmail 액티비티를 명시적으로 기입해도 될듯~!

i.setComponent(new ComponentName("com.google.android.gm","com.google.android.gm.ComposeActivity"));


그러나 위와 같이 하면 permission에러가 나면서 해당 액티비티가 호출되지 않는다.
권한문제를 피해가기 위해 Intent.createChooser()를 이용하여 해당 액티비티로 연결하도록 되어 있다.

이를 피하기 위해서는 권한 문제가 없는 자체적인 Mail client나 MMS client를 직접 작성해야 할것으로 보인다.
그러나 이 문제도 권한문제로 인해 구현이 불가할 수 있다.



Posted by 삼스
Android/App개발2011. 5. 8. 18:03

MIME-Type Description File Extension
application/acad AutoCAD drawing files dwg
application/clariscad ClarisCAD files ccad
application/dxf DXF (AutoCAD) dxf
application/msaccess Microsoft Access file mdb
application/msword Microsoft Word file doc
application/octet-stream Uninterpreted binary bin
application/pdf PDF (Adobe Acrobat) pdf
application/postscript Postscript, encapsulated Postscript, ai, ps, eps
Adobe Illustrator
application/rtf Rich Text Format file rtf rtf
application/vnd.ms-excel Microsoft Excel file xls
application/vnd.ms-powerpoint Microsoft PowerPoint file ppt
application/x-cdf Channel Definition Format file cdf
application/x-csh C-shell script csh csh
application/x-dvi TeX dvi dvi dvi
application/x-javascript Javascript source file js
application/x-latex LaTeX source file latex
application/x-mif FrameMaker MIF format mif
application/x-msexcel Microsoft Excel file xls
application/x-mspowerpoint Microsoft PowerPoint file ppt
application/x-tcl TCL script tcl
application/x-tex TeX source file tex
application/x-texinfo Texinfo (emacs) texinfo, texi
application/x-troff troff file t, tr, roff t, tr, roff
application/x-troff-man troff with MAN macros man
application/x-troff-me troff with ME macros me
application/x-troff-ms troff with MS macros ms
application/x-wais-source WAIS source file src
application/zip ZIP archive zip
audio/basic Basic audio (usually m-law) au, snd
audio/x-aiff AIFF audio aif, aiff, aifc
audio/x-wav Windows WAVE audio wav
image/gif GIF image gif
image/ief Image Exchange Format file ief
image/jpeg JPEG image jpeg, jpg jpe
image/tiff TIFF image tiff, tif
image/x-cmu-raster CMU Raster image ras
image/x-portable-anymap PBM Anymap image format pnm
image/x-portable-bitmap PBM Bitmap image format pbm
image/x-portable-graymap PBM Graymap image format pgm
image/x-portable-pixmap PBM Pixmap image format ppm
image/x-rgb RGB image format rgb
image/x-xbitmap X Bitmap image xbm
image/x-xpixmap X Pixmap image xpm
image/x-xwindowdump X Windows Dump (xwd) xwd
multipart/x-gzip GNU ZIP archive gzip
multipart/x-zip PKZIP archive zip
text/css Cascading style sheet css
text/html HTML file html, htm
text/plain Plain text txt
text/richtext MIME Rich Text rtx
text/tab-separated- values Text with tab-separated values tsv
text/xml XML document xml
text/x-setext Struct-Enhanced text etx
text/xsl XSL style sheet xsl
video/mpeg MPEG video mpeg, mpg, mpe
video/quicktime QuickTime video qt, mov
video/x-msvideo Microsoft Windows video avi
video/x-sgi-movie SGI movie player format movie


MIME 확장명

파일 확장명 

 application/x-silverlight-app  .xap
 application/manifest  .manifest 
 application/x-ms-application  .application 
 application/x-ms-xbap  .xbap
 application/octet-stream  .deploy
 application/vnd.ms-xpsdocument  .xps 
 application/xaml+xml  .xaml
 application/vnd.ms-cab-compressed  .cab
 application/vnd.openxmlformats-officedocument.wordprocessingml.document  .docx
 application/vnd.openxmlformats-officedocument.wordprocessingml.document  .docm
 application/vnd.openxmlformats-officedocument.presentationml.presentation  .pptx
 application/vnd.openxmlformats-officedocument.presentationml.presentation  .pptm
 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet  .xlsx
 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet  .xlsm
 application/msaccess  .accdb
 application/x-mspublisher  .pub
 image/svg+xml  .svg
 application/xhtml+xml  .xht
 application/xhtml+xml  .xhtml

Posted by 삼스
Android2011. 4. 22. 14:59

android SDK에서 제공하는 android tool은 3가지 타입의 프로젝트를 생성하는 방법을 제공한다.

1. 일반적인 안드로이드 애플리케이션 프로젝트를 생성
2. 안드로이드 라이브러리를 생성하는 프로젝트를 생성
3. JUnit test를 확장하는 테스트 프로젝트를 생성

안드로이드 프로젝트의 생성

 android tool을 사용해서 생성한다. 

android create project \
--target <target_ID> \
--name <your_project_name> \
--path path/to/your/project \
--activity <your_activity_name> \
--package <your_package_namespace>
target은 애플리케이션의 빌드타겟인데 이는 안드로이드 플랫폼 라이브러리에 대응된다. 유효한 타겟과 해당하는 ID를 알고 싶으면 android list targets를 수행하면 된다.

name은 프로젝트명이다. 옵션이며 apk파일명이된다.
path는 프로젝트의 폴더명이다. 폴더가 없다면 생성해준다.
activity는 디폴트액티비티명이다.
package는 애플리케이션의 패키지명이다.

아래는 예제이다.
android create project \
--target 1 \
--name MyAndroidApp \
--path ./MyAndroidAppProject \
--activity MyAndroidAppActivity \
--package com.example.myandroid
위 명령을 수행하면 MyAndroidAppProject폴더가 생성되며 그 아래 각종 안드로이드 소스와 리소스들이 자동으로 생성된다.

개발에 사용하는 Android SDK가 업데이트 된 경우 이전 프로젝트코드를 그대로 사용하려면 android update project명령을 수행하면 된다.  이 명령으로 빌드타겟을 바꾸거나 프로젝트명을 바꾸는 용도로 사용할 수 도 있다.

android update project --name <project_name> --target <target_ID>
--path <path_to_your_project>
아래는 예이다.
android update project --name MyApp --target 2 --path ./MyAppProject

라이브러리 프로젝트의 설정

라이브러리 프로젝트는 표준 안드로이드 프로젝트이다. 따라서 애플리케이션 프로젝트 생성법과 동일한 방법으로 생성할 수 있다. 

 android create lib-project --name <your_project_name> \
--target <target_ID> \ --path path/to/your/project \ --package <your_library_package_namespace>
lib-project명령으로 수행하면 표준 안드로이드 프로젝트와 동일한 프로젝트가 생성되고 default.properties파일에 아래 정보가 추가되어 library project가 되게 된다.

android.library=true
완성된 프로젝트에서 default.properties를 열어보면 위 정보가 추가된것을 볼 수 있다.


라이브러리 프로젝트 참조하기

애플리케이션을 개발하면서 라이브러리 프로젝트로부터 코드나 리소스를 사용하고자 한다면 애플리케이션의 build properties에 라이브러리 프로젝트의 참조를 추가하면 된다.

android update lib-project \
--target <target_ID> \
--path path/to/your/project
--library path/to/library_projectA
위 명령은 프로젝트의 build properties에 라이브러리 참조를 추가하게 된다. 
아래는 그 예이다.

android.library.reference.1=path/to/library_projectA
 
 
여러개의 라이브러리를 참조하고자 한다면 인덱싱을 해야 한다. 이 순서는 참조순서가 된다. 파일을 직접 수정함으로 순서를 조정할 수 있다.
android.library.reference.1=path/to/library_projectA
android.library.reference.2=path/to/library_projectB
android.library.reference.3=path/to/library_projectC

manifest file에서 라이브러리 콤포넌트의 선언

 애플리케이션의  manifest파일에는 애플리케이션이 사용하는 모든 콤포넌트들이 정의되어야 하며 참조하는 라이브러리의 콤포넌트들도 정의되어야 한다. 예를 들면 ,activity>, <service>, <receiver>, <provider>은 물론이고 <permission>, <uses-library>등도 필요하면 정의해야 한다.

아래는 예이다.

<manifest>
  ...
 
<application>
    ...
   
<activity android:name="com.example.android.tictactoe.library.GameActivity" />
    ...
 
</application>
</manifest>

Ant tool은 라이브러리 레퍼런스가 있는 경우 내부적으로 모든 라이브러리를 컴파일하고 머지하여 빌드를 진행한다.


 
Posted by 삼스
Android2011. 4. 22. 14:30

Ant build script로 애플리케이션을 빌드하는 방법은 debug mode와 release mode가 있다.
어떤 방법을 사용하던간에 애뮬레이터나 디바이스에서 동작시키려면 signing을 해야 한다.

debug mode로 빌드시 Ant는 debug key로 자동으로 sign한다. 따라서 애뮬이나 디바이스에서 구동 가능하다. 하지만 배포는 불가하다. 릴리즈모드로 빌드하면 unsigned apk 가 만들어진다. 따라서 반드시 private key로 keytool과 jarsigner로 sign해야 한다.

Ant가 설치되어 있지 않다면 Apache Ant home page로부터 설치를 해야 한다. 그리고 실행경로를 설정해야 한다. JAVA_HOME환경변수가 JDK가 설치된 경로를 지정하고 있어야 한다.

윈도우에서는 JDK가  "Program FIles"폴더에 설치되는데 공백때문에 오류가 날수 있으므로 아래와 같이 정의한다.
set JAVA_HOME=c:\Progra~1\Java\<jdkdir>

debug mode로 빌드하는 방법은 프로젝트의 루트위치에서 아래 명령만 치면 된다.

ant debug

이 명령은 bin/ 위치에 여러분의 애플리케이션 .apk파일을 만들어준다. 이 파일은 애뮬이나 디바이스에 바로 설치 및 디버깅이 가능하다.

소스가 변경될 때 마다 이 명령을 수행하여 재빌드한다.

release mode로 빌드하는 방법은 프로젝트의 루트위치에서 아래 명령만 치면 된다.

ant release

이 명령으로 생성된 .apk file은 unsigned apk이다.
따라서 signing과 zipalign을 추가로 해주어야 한다. 이 과정까지 마치면 배포를 위한 준비를 마친게 된다.

원한다면 Android build script가 자동으로 sign하고 align하도록 할 수 있다. keystore와 key alias를 build.properties 파일에 기술하면된다. 이 정보가 존재하면 빌드스크립트는 keystore와 alias password를 입력하는 화면이 나오게 된다.

주의 : Ant가 입력을 다룰수 있기 때문에 빌드프로세싱중 패스워드가 화면에 보여질수 있다. 이게 거슬린다면 매뉴얼로 signing하는것이 좋다. manual로 signing하는것 대신에 unsigned로 빌드 후 signing을 별도로 하면된다.

build.properties에는 아래와 같이 keystore와 alias name을 지정할 수 있다.

key.store=path/to/my.keystore
key.alias=mykeystore

위와 같이 한 수 재빌드하면 sign된 릴리즈모드 apk가 만들어진다.

빌드를 완전히 자동화할 목적으로 사용하고자 한다면 signing중에 password입력 프롬프트가 뜨는것을 부담스러워 할 수 있다.
이 때는 수동으로 해야 하는데 jarsigner에서 수동으로 password를 지정할 수 있다. 위에서 기술한 build.properties방식으로는 동작하지 않으므로 별도로 매뉴얼로 수행해야 한다.

jarsigner -verbose \
             -keystore my-release-key.keystore  \   <- keystore file의 full path
             -storepass 1234 \        <- keystore의 password
             myapp.apk \                <- unsigned apk
             myalias_name                   <- keystore의 alias name

위의 예처럼 하면 프롬프트 없이 signing이 완료된다.



 
Posted by 삼스