윈도우 이클립스에서 안드로이드 어플을 개발할 때 API 보는 것 대신 소스를 보려면, 두가지 중 하나를 하면 된다.
1. 소스를 다운받기
   tortoiseGit 프로그램을 이용해서 아래 주소에 git 파일을 가지고 clone한다. 
    https://android.googlesource.com/platform/frameworks/base.git  
2. 자바 소스 zip 파일 다운 받기
 https://github.com/android/platform_frameworks_base/tags 디렉토리에 접근해서 버전에 맞게 소스를 다운받으면 된다. 


예전에는 소스를 다운받는 구조로 했었는데.. 별로 안좋은 것 같다. 


웹 브라우져에서 https://github.com/android/platform_frameworks_base/tags  에 접속한다.




나는 안드로이드 2.3.3 어플을 개발중이므로, android_2.3.3_r1을 다운받는다.



안드로이드 소스 연동 이클립스에서 SurfaceView 클래스의 소스를 보려고 했을 때, 아래와 같은 화면이 나타난다.

 




여기서 Attach Source의  External File을 선택후, 다운받은 zip 파일을 연결한다. (사진에 그림을 잘 못 그렸음..)
 



아래와 같이 안드로드이 자바 소스를 확인할 수 있다. 





Posted by 김용환 '김용환'


 

  Bitmap imgBack = BitmapFactory.decodeResource(getResources(), R.drawable.sky);
  imgBack = Bitmap.createScaledBitmap(imgBack, width, height, false);


Bitmap 관련 API

http://developer.android.com/reference/android/graphics/BitmapFactory.html

http://developer.android.com/reference/android/content/res/Resources.html

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

 

구현

http://mainia.tistory.com/468

http://chiyo85.tistory.com/7

 

게임관점에서 본 Bitmap

http://www.google.co.kr/url?sa=t&rct=j&q=bitmapfactory%20api&source=web&cd=5&ved=0CGEQFjAE&url=http%3A%2F%2Fsgap.springnote.com%2Fpages%2F5651353%2Fattachments%2F3262889&ei=X1gWT6iuB4eJmQWT9oHAAw&usg=AFQjCNEKD0mDoGngeA2mN0iIm4v9jo2w2Q

Posted by 김용환 '김용환'


LG U+ 갤택에 아이스크림을 올릴기 위해서, 이것저것 해보고 있다. 
네이버 갤탭 사용자 카페에서 SK와 와탭은 되는데, LG U+ 제품은 잘 안된다고 한다.
안되도 공부하는 셈치고 해보려고 한다. 
xda 개발자가 쓴 내용을 바탕으로 갤택 7인치 아이스크림 버전을 다운받고 컴파일을 완료했다.
http://forum.xda-developers.com/showthread.php?t=1385153


1. 툴 설치

소스 컴파일을 위한 준비를 한다.
http://source.android.com/source/initializing.html
아래 참조 : http://knight76.tistory.com/entry/안드로이드-소스-컴파일-ubuntu-1104-android-gingerbread


2. repo 다운로드

$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > repo
$ chmod a+x repo


3. 안드로이드 소스 다운로드

$ mkdir android4
$ cd android4
$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1
$ repo sync

4.  xda의 cm9 소스  다운로드

mkdir cm9
cd cm9
repo init -u git://github.com/sgt7/android.git -b ics
repo sync

5. 컴파일 준비 및 컴파일

$ . build/envsetup.sh
including device/moto/stingray/vendorsetup.sh
including device/moto/wingray/vendorsetup.sh
including device/samsung/galaxytab/vendorsetup.sh
including device/samsung/maguro/vendorsetup.sh
including device/samsung/toro/vendorsetup.sh
including device/ti/panda/vendorsetup.sh
including vendor/cm/vendorsetup.sh
including sdk/bash_completion/adb.bash


$ lunch cm_galaxytab-userdebug

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.3
TARGET_PRODUCT=cm_galaxytab
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=MR1
============================================

 $ make bacon


 6. 컴파일 결과 확인
타겟 보드향이기 때문에 out/target 에 디렉토리가 있을 것이다.

android4/out/target/product/galaxytab $ ls -al
total 22428
drwxr-xr-x  8 kimyonghwan kimyonghwan    4096 2012-01-09 20:43 .
drwxr-xr-x  3 kimyonghwan kimyonghwan    4096 2012-01-09 20:36 ..
-rw-r--r--  1 kimyonghwan kimyonghwan 8563349 2012-01-09 20:43 boot.img
-rw-r--r--  1 kimyonghwan kimyonghwan   18719 2012-01-09 20:36 clean_steps.mk
drwxr-xr-x 15 kimyonghwan kimyonghwan    4096 2012-01-09 22:26 obj
-rw-r--r--  1 kimyonghwan kimyonghwan     571 2012-01-09 20:36 previous_build_config.mk
-rw-r--r--  1 kimyonghwan kimyonghwan  590256 2012-01-09 20:42 ramdisk.img
-rw-r--r--  1 kimyonghwan kimyonghwan 3330560 2012-01-09 20:42 ramdisk-recovery.cpio
-rw-r--r--  1 kimyonghwan kimyonghwan 1850517 2012-01-09 20:42 ramdisk-recovery.img
drwxr-xr-x  3 kimyonghwan kimyonghwan    4096 2012-01-09 20:42 recovery
-rw-r--r--  1 kimyonghwan kimyonghwan 8563349 2012-01-09 20:43 recovery.img
drwxr-xr-x  9 kimyonghwan kimyonghwan    4096 2012-01-09 20:42 root
drwxr-xr-x  5 kimyonghwan kimyonghwan    4096 2012-01-09 20:43 symbols
drwxr-xr-x  9 kimyonghwan kimyonghwan    4096 2012-01-09 23:10 system
drwxr-xr-x  2 kimyonghwan kimyonghwan    4096 2012-01-09 20:43 utilities


boot.img, root, system fs 은 나왔는데, zImage 파일이 없다. 자동으로 나올줄 알았는데..
cm9 공부좀 해야겠는데...

Posted by 김용환 '김용환'



http://androidhuman.tistory.com/entry/카메라를-이용하자-SurfaceView에-대한-이해
http://blog.naver.com/PostView.nhn?blogId=foxmann&logNo=90096071680
http://www.androidjavadoc.com/2.3/android/view/SurfaceHolder.Callback.html
http://www.androidjavadoc.com/2.3/android/view/SurfaceHolder.html
http://sozu.tistory.com/35
http://blog.csdn.net/yili_xie/article/details/4803548
http://gamoo.pe.kr/wordpress/?p=295
http://translate.google.co.kr/translate?prev=hp&hl=ko&js=y&u=http%3A%2F%2Fblog.sina.com.cn%2Fs%2Fblog_49bdd36d0100eafj.html&sl=zh-CN&tl=en&history_state0=
http://blog.daum.net/baramjin/16010959
http://forum.falinux.com/zbxe/?document_srl=406102

Posted by 김용환 '김용환'


조금 어플 큰거 다운받으면 '기기에 공간이 부족하다는' 에러가 많이 받았다.

진저브레드이고, 갤택 최신 커널도 설치했고, 메모리도 많은데 무엇이 문제가 있가 했다.


“XXX” 다운로드 중에 오류가 발생했습니다.
기기에 공간이 부족합니다.

 
결론은..
설정-응용프로그램관리-(다운로드됨) 메뉴에서 –마켓 를 선택한 후 업데이트 제거 했더니 잘 받아진다. .

Posted by 김용환 '김용환'

안드로이드 플러그인이 설치된 이클립스에서 새로운 프로젝트를 생성한다.
Create proejcty from existing sample을 선택하면 Sample 컴보박스가 뜬다.





여기서 예제들을 선택하고 개념을 파악하면 쉽다.



Posted by 김용환 '김용환'


http://developer.android.com/sdk/index.html 에 밑에 보면,
ndk 를 다운받을 수 있다.


mac, window(cygwin 이용), linux 버전있는데, linux로 설치해본다.


ndk7이 4.0을 포함한 최신 버전이지만, ubuntu10. 11에서 awk 관련해서 버그가 있다. 32비트에서만 이슈가 있음. 이 부분에 대한 해결방법은 여기에 있다.

나는 ndk 6b를 사용했지만, 위의 7도 동일하게 사용할 수 있다.


리눅스(ubuntu)에 android-ndk-r6b.tar.gz을 설치한다.
tar jxvf android-ndk-r6b.tar.gz

설치는 완료했다.

이제 코드쪽을 본다.
이클립스에서 클래스 하나를 생성하고, jni 함수를 하나를 만들고, 동적 library를 읽도록 한다.

package com.google;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloJni extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
  TextView tv = new TextView(this);
  tv.setText(stringFromJNI());
  setContentView(tv);
    }
    public native String stringFromJNI();
 static {
  System.loadLibrary("hello-jni");   
 }

}




이클립스 workspace의 프로젝트에서 컴파일된 디렉토리로 들어가서
class파일을 통해서 header 파일을 만든다.

프로젝트이름\bin> javah -classpath . com.google.JniHello

그러면, header 파일이 생성된 것을 확인할 수 있다.

> dir
com_google_JniHello.h

이 파일을 이용해서 c 소스를 만든다.

#include <string.h>
#include <jni.h>


jstring
Java_com_google_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}




이 파일을 linux에 설치한 ndk에 특정 위치에 둔다.

설치디렉토리/jni-test/knight/jni 폴더에 둔다.
그리고, make 파일인 Android.mk도 같이 집어 넣는다.

Android.mk 파일은 다음과 같다.

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)




 



설치디렉토리/jni-test/knight/ 디렉토리에서 빌드한다.

설치디렉토리/jni-test/knight # ../../ndk-build

컴파일이 잘되면 이렇게 so 파일이 나온다.
설치디렉토리/jni-test/knight/libs/armeabi/libhello-jni.so 파일이 생성된다.




so파일을 이클립스단으로 복사한다.
그 전에 먼저 jni 파일과 mk 파일을 복사한다.

eclipse 프로젝트의 jni 폴더를 생성하고, jni와 mk 파일을 복사한다.
그리고, so 파일을 libs에 복사한다.
디렉토리는 이렇게 나와야 한다.




이 파일에 대해서 에뮬에서 run하면 다음과 같은 결과가 나온다.




그리고, 보드에다가도 테스트해봤다.
ok 잘돈다.




소스는 아래와 같다.




ndk 를 보면, sample 디렉토리 밑에 많은 샘플(open gl 외 다양한 예제) 들이 있다.
참조해서 만들어보면 좋다.

san-angles 라는 샘플은 움직이는 예제를 보여준다. 터치해주면 잠깐 멈추고 그러니. 테스트하기에 재미있는 예제이다.



* 레퍼런스
 http://developer.android.com/sdk/ndk/index.html 

Posted by 김용환 '김용환'

혼자 잡담) java-jni-cpp 가지고 300만원짜리 알바까지 했는데..
왠걸 다시 하니 기억이 안난다. 오홋 새록새록해~ 그래도 어떻게 하나 열심히 공부해야지~^^




정리하는 내용
- 리눅스에서 java->c 호출
- 리눅스에서 c->java 호출


그래픽이나 c/c++로 만들어진 라이브러리들을 바로 사용할 수 있도록 하는 프레임웤이다.

HelloJNI 테스트 해본다.

class HelloJNI {
 native void printHello();
 native void printString(String str);
 
 static {
  System.load("/work/JniTest/hellojni.so");
 }
 public static void main(String[] args) {
  HelloJNI myJNI = new HelloJNI();
  myJNI.printHello();
  myJNI.printString("Hello in C");
 }
}



삼바를 이용해서 리눅스 /work/JniTest 디렉토리를 생성하고,  HelloJNI.java 복사한다.

컴파일하고, 그  class 파일을 이용해서 header 파일을 생성하도록 한다.
javac HelloJNI.java
javah HelloJNI


HelloJNI.h 파일이 생성

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

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloJNI
 * Method:    printHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_printHello
  (JNIEnv *, jobject);

/*
 * Class:     HelloJNI
 * Method:    printString
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_HelloJNI_printString
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif






HelloJNI.c 소스를 생성

#include "HelloJNI.h"

JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj) {
 printf("Hello World !!! jni\n");
}


JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv *env, jobject obj, jstring string) {
  const char *str = (*env)->GetStringUTFChars(env,string,0);
  printf("%s\n", str);
  return;
}





컴파일을 하여 so 파일이 만들어지도록 한다.

# gcc -c -I$JAVA_HOME/include -I$JAVA_HOME/include/linux HelloJNI.c
# gcc -shared -o HelloJNI.so HelloJNI.o
# ls -al HelloJNI.so
HelloJNI.so

 정상적으로 동작된다.

# java HelloJNI
Hello World !!!
Hello in C!!!

 


이런식으로 표현한 다양한 방식을 샘플로 적어본다.

java 코드

class JniFuncMain {
..
public static native JniTest createJniObject();
..
}

 

class JniTest
{
 private int intField;
 
 public JniTest(int num)
 {
  intField = num;
 }
 
 public int callByNative(int num)
 {
  return num;
 }
 
 public void callTest()
 {
  System.out.println("intField=" + intField);
 }
}



 cpp 코드


#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JniFuncMain
 * Method:    createJniObject
 * Signature: ()LJniTest;
 */
JNIEXPORT jobject JNICALL Java_JniFuncMain_createJniObject
  (JNIEnv *env, jclass clazz)
{
 jclass targetClass;
 jmethodID mid;
 jobject newObject;
 jstring helloStr;
 jfieldID fid;
 jint staticIntField;
 jint result;
 
 // Get the Class staticIntField Value
 fid = env->GetStaticFieldID(clazz, "staticIntField", "I");
 staticIntField = env->GetStaticIntField(clazz, fid);
 printf("[CPP] Get JniFuncMain_Class_staticIntField!!\n");
 printf("[CPP] JniFuncMain_Class_staticIntField = %d\n", staticIntField);
 
 // Find the Class to create object
 targetClass = env->FindClass("JniTest");
 
 // Find the Constructor
 mid = env->GetMethodID(targetClass, "<init>", "(I)V");
 
 // Create a JniTest Object
 printf("[CPP] JniTest_Object Create!!\n");
 newObject = env->NewObject(targetClass, mid, 100);
 
 // Call the Method of Object
 mid = env->GetMethodID(targetClass, "callByNative", "(I)I");
 result = env->CallIntMethod(newObject, mid, 200);
 
 // Set the intField_field of JniObject
 fid = env->GetFieldID(targetClass, "intField", "I");
 env->SetIntField(newObject, fid, result);
 
 // return created Object
 return newObject;
}
#ifdef __cplusplus
}
#endif
 


# g++ -I/$JAVA_HOME/include -I/$JAVA_HOME/include/linux -c jnifunc.cpp
# g++ -shared -o jnifunc.so jnifunc.o
# java 메인클래스실행




이외에 c에서 java로도 호출이 가능하게 할 수 있다.


#include <jni.h>

int main()
{
 JNIEnv *env;
 JavaVM *vm;
 JavaVMInitArgs vm_args;
 JavaVMOption options[1];
 jint res;
 jclass cls;
 jmethodID mid;
 jstring jstr;
 jclass stringClass;
 jobjectArray args;
 
 // 1.JVM에 넘겨줄 아규먼트 셋팅 
 options[0].optionString = "-Djava.class.path=.";
 vm_args.version = 0x00010002;
 vm_args.options = options;
 vm_args.nOptions = 1;
 vm_args.ignoreUnrecognized = JNI_TRUE;
 
 //2.JVM 생성
 res = JNI_CreateJavaVM(&vm, (void**)&env, &vm_args);
 
 //3. 클래스 검색 과 로딩
 cls = (*env)->FindClass(env, "InvocationApiTest");
 
 //4. main 메소드 얻어오기 
 mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
 
 //5.메인메소드의 실제 파라미터값을 지정한다. 
 jstr = (*env)->NewStringUTF(env, "Hello Test from Native!!!");
 stringClass = (*env)->FindClass(env, "java/lang/String");
 args = (*env)->NewObjectArray(env, 1, stringClass, jstr);
 
 //6.main 메소드를 호출한다.
 (*env)->CallStaticVoidMethod(env, cls, mid, args);
 
 //7.JVM를 내린다.
 (*vm)->DestroyJavaVM(vm);
}




클래스 파일

public class InvocationApiTest
{
 public static void main(String[] args)
 {
  System.out.println(args[0]);
 }
}


# gcc -I/$JAVA_HOME/include -I$JAVA_HOME/include/linux -c invocationApi.c

그다음은 jvm 관련 항목을 링크 옵션으로 줘야 jvm이 실행할 수 있다.
# gcc -L$JAVA_HOME/jre/lib/i386/client invocationApi.o -ljvm
(libjvm.so 라는 파일이 $JAVA_HOME/jre/lib/i386/client/libjvm.so 파일이 있어야 한다.)

dependent한 library 가 있는지를 확인한다.

# ldd a.out 

# export LD_LIBRRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/i386/client

# a.out
결과 출력


다음예는
jni onload 함수를 오버라이딩해서,
a라고 하는 함수를 b라는 함수로 호출되도록 바꿔치기 를 할 수 있는 예제이다.


// hellojnimap.cpp

#include <jni.h>
#include <stdio.h>

void printHelloNative(JNIEnv *env, jobject obj);
void printStringNative(JNIEnv *env, jobject obj, jstring string);

// JNI_ONload는 오버라이딩한 것이다.
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
 JNIEnv *env = NULL;
 JNINativeMethod nm[2];
 jclass cls;
 jint result = -1;
 
 if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
  printf("Error");
  return JNI_ERR;
 }
 
 cls = env->FindClass("HelloJNI");
 
 nm[0].name = (char*)"printHello";
 nm[0].signature = (char*)"()V";
 nm[0].fnPtr = (void *)printHelloNative;
 
 nm[1].name = (char*)"printString";
 nm[1].signature = (char*)"(Ljava/lang/String;)V";
 nm[1].fnPtr = (void *)printStringNative;
 
 env->RegisterNatives(cls, nm, 2);
 
 return JNI_VERSION_1_4;
}

void printHelloNative(JNIEnv *env, jobject obj)
{
 printf("Hello World in C++!!\n");
 return;
}

void printStringNative(JNIEnv *env, jobject obj, jstring string)
{
 //const char *str = (*env)->GetStringUTFChars(env, string, 0);
 const char *str = env->GetStringUTFChars(string, 0);
 printf("%s\n", str);
 return;
}

#if 0
JNIEXPORT void JNICALL Java_HelloJNI_printHello
  (JNIEnv *env, jobject obj)
{
 printf("Hello World in C!!\n");
 return;
}

JNIEXPORT void JNICALL Java_HelloJNI_printString
  (JNIEnv *env, jobject obj, jstring string)
{
 const char *str = (*env)->GetStringUTFChars(env, string, 0);
 printf("%s\n", str);
 return;
}
#endif





//HelloJNI.java

class HelloJNI
{
 native void printHello();
 native void printString(String str);
 
 static {
  System.load("/work/JniTest/hellojnimap.so");
 }
 
 public static void main(String[] args) {
  HelloJNI myJNI = new HelloJNI();
  
  myJNI.printHello();
  myJNI.printString("Hello from c!!");
 }
 
}




# g++ -I/$JAVA_HOME/include -I$JAVA_HOME/include/linux -c hellojnimap.cpp
# g++ -shared -o hellojnimap.so hellojnimap.o
# java 메인클래스실행

Posted by 김용환 '김용환'


안드로이드 버전에 탑재된 리눅스 커널 버전을 확인하기 위해서는 위키(http://en.wikipedia.org/wiki/Android_version_history)를 통해 확인할 수 있다.

만약 내가 누군가의 모바일 에서 리눅스 커널 버전을 application으로 확인하기 위한 앱 소스는 다음과 같다.


간단 소스


package com.google;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class OSFinderActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText(System.getProperty("os.version"));
        setContentView(tv);
    }
}




리눅스 커널 버전을 확인






소스에서도 리눅스 커널을 보고 싶다.

froyo는 kernel/Makefile을 보면 확인이 가능하다.

VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 32
EXTRAVERSION = .9

공식문서에 있는 2.6.32 가 맞다.
http://developer.android.com/sdk/android-2.2-highlights.html



진저브레드는 kernel 디렉토리가 없어서 grep 으로 찾아보니. 아래 파일에서 2.6.32 로 나온다.
system/core/ThirdPartyProject.prop

공식문서에서는 2.6.35인데.. ^^;;;
http://developer.android.com/sdk/android-2.3-highlights.html


아이스크림 샌드위치는 공식적으로 커널 버전에 대한 내용은 없다. (현재 2011.11월 말)
다만, 아래 엔가젯에서 "but it's running on an updated build (IRK48) and kernel (3.0.1).
" 이라는 내용이 언급되어 있을 뿐이다.

http://www.engadget.com/2011/09/28/ice-cream-sandwich-gets-a-two-minute-tour-courtesy-of-a-lucky-e/
 



Posted by 김용환 '김용환'

다음 디렉토리 지운다.

(xp)
C:\Documents and Settings\사용자계정\.android

또는

(win7)
사용자 user 디렉토리\사용자계정\.android

Posted by 김용환 '김용환'