Android/App개발2009. 10. 14. 23:06
<Android market관련 테스트할 때 쉬운 방법 >

일일이 마켓 접속해서 테스트할 여건이 안될경우... 유용한 방법입니다.
다운로드는 웹페이지만 거치면 가능하고(저는 이멜로 첨부하였습니다). 설치는 market에서 다운로드한거 아니라고 설치가 안될 수 있습니다.

이런 경우 체크루틴을 막으면 되는데요.
/package/apps/src/com/android/packageinstaller/PackageInstallerActivity.java의 onCreate()에서 이를 확인하는 부분을 막으시면 됩니다.
if(!isInstallingUnknownAppsAllowed()) { //ask user to enable setting first //@@yslee TEMP!! showDialogInner(DLG_UNKNOWN_APPS); //@@yslee TEMP!! return; } 요렇게 하면 아무데서나 다운로드한거 다 설치할 수 있습니다.
;;
Posted by 삼스
Android/App개발2009. 8. 28. 14:11

http://www.engadget.com/2009/05/27/

android-2-0-donut-features-demoed-at-google-i-o/


도넛부터 탑재되는 통합검색솔루션

- Web은 물론이고 local의 contacts, mail, application content등을 하나로 검색 관리 가능

Posted by 삼스
Android/App개발2009. 8. 15. 14:49
breakpoint를 잡을수 없는 경우는 framework을 디버그할 때 일것이다.
안드로이드가 framework가 완전하다고는 볼수 없기 때문에 framework를 보아야 하거나 보완해야 할경우가 있다.

이때 유일한 디버깅 방법은 Log를 찍어서 LogCat으로 보는 방법이다.

이때 breakpoint를 볼수 있기를 원할텐데.. 참 답답하지만 이게 쉽지 않다.

코드의 진행을 잠시 멈추어서 현재 화면에 대한 출력을 눈으로 확인하고 싶을 수 있다.
이 때는 Thread.sleep()로 일정시간 실행을 지연시키면서 상태를 보는 방법이 있을 것이다.

더 좋은 방법을 찾았으면 좋겠다.

TRACE32같은 장비로 디버그할 수 있다면 참 좋겟다.
Posted by 삼스
Android/App개발2009. 7. 26. 19:19
기존 액티비티로 하여금 아직 생각해보지 못한 기능의 이점을, 프로젝트를 수정하거나 다시 컴파일할 필요없이 새로운 applicaton component를 통해 취할 수 있도록 해주는 플러그인 모델을 제공한다.

이 방법은 "런타임 메뉴 추가"기능을 의미한다.

<activity android:name=".NostromoController">
  <intent-filter android:label="궤도로부터의 핵 공격">
    <action android:name="com.pad.nostromo.NUKE_FROM_ORBIT"/>
    <data android:mimeType="vnd.moonbase.cursor.item/*/>
    <category android:name="android.intent.category.ALTERNATIVE"/>
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE"/>
</activity>

위 action을 또 다른 액티비티의 메뉴에서 동적으로 사용할 수 있도록 만들 수 있다.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);

Intent intent = new Intent();
intent.setData(MoonBaseProvider.CONTENT_URI);
intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE);

int menuGroup = 0;
int menuItemId = 0;
int menuItemOrder = Menu.NONE;

ComponentName caller = getComponentName();

Intent[] specificIntents = null;
MenuItem[] outSpecificItems = null;

menu.addIntentOptions(menuGroup,
                               menuItemId,
                               menuItemOrder,
                               caller,
                               specificIntents,
                               intent,
                               Menu.FLAG_APPEND_TO_GROUP,
                               outSpecificItems);
return true;
}


** Broadcast Intent **
  인텐트는 액티비티를 호출하는데에만 사용하는 것이 아니라 콤포넌트들간에 메시지를 전달하는데 사용될 수 있다. 어플리케이션내에 브로드캐스트수신자를 장착하여 특정 방송메세지에 귀기울이도록 할 수 있다.

  // 방송하기
  1. Intent 생성
    Intent intent = new Intent(NEW_LIFEFORM_DELETED);
    intent.putExtra("lifeformName", lifeformType);
    intent.putExtra("longitude", currentLongitude);
    intent.putExtra("latitude", currentLatitude);
  2. send
    sendBroadcast(intent);

  // 방송듣기
  1. BroadcastReceiver 생성
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;

  public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Content context, Intent intent) {
      // TODO :수신한 방송에 대해 처리를 한다.
    }
  }
 2. AndroidManifest.xml에 수신자를 등록한다.
  <receiver android:name=".LifeformDeletedBroadcastReceiver">
    <intent-filter>
      <action android:name="com.paad.action.NEW_LIFEFORM"/>
    </intent-filter>
  </receiver>
 3. 또는 code상에서 수신자를 등록하거나 해재할 수 있다. 이 처럼 동적으로 액티비티가 활성화되어 있을경우에만 수신할 수 있도록 하는 제어가 가능하다.
    //등록하기
    IntentFilter filter = new IntentFilter(NEW_LIFEFORM_DETECTED);
    LifeformDetectedBroadcastReceiver r = new LifeformDetectedBroadcastReceiver();
    registerReceiver(r, filter);

    // 해재하기
    unregisterReceiver( r );

안드로이드 시스템에서 정의되어 있는 방송의 종류는 아래와 같다.
  ACTION_BOOT_COMPLETED
  ACTION_CAMERA_BUTTON
  ACTION_DATE_CHANGED, ACTION_TIME_CHANGED
  ACTION_GTALK_SERVICE_CONNECTED, ACTION_GTALK_SERVICE_DISCONNECTED
  ACTION_MEDIA_BUTTON
  ACTION_MEDIA_EJECT
  ACTION_MEDIA_MOUNTED, ACTION_MEDIA_UNMOUNTED
  ACTION_SCREEN_OFF, ACTION_SCREEN_ON
  ACTION_TIMZONE_CHANGED
  // ... http://developer.android.com/reference/android/content/Intent.html


Posted by 삼스
Android2009. 7. 24. 18:27

이글은, 구글 안드로이드 상의 Java 애플리케이션에서 native c/c++ 모듈을 Call 할 수 있는 가에
대한 것이다. 결론적으로 말하면 쉽지 않을 것 같지만 불가능 하지는 않을 듯 하다.
직접 JNI를 통해 결과를 검증해 보지는 않았지만, 대략적인 방법들과 문제점들을 정리해 보고자
한다.
 
 
1. JNI란 무엇인가? - JNI example 중심으로
 
This section presents the ReadFile example program. This example shows how you can use 
the Java Native Interface (JNI) to invoke a native method that makes C function calls to map a 
file into memory. 

About the Example 

You can call code written in any programming language from a program written in the Java 
language by declaring a native Java method, loading the library that contains the native code, 
and then calling the native method. The ReadFile source code below does exactly this. 
However, successfully running the program requires a few additional steps beyond compiling 
the Java language source file. After you compile, but before you run the example, you have to 
generate a header file. The native code implements the function defintions contained in the 
generated header file and implements the business logic as well. The following sections walk 
through all the steps.
import java.util.*;
class ReadFile {
 //Native method declaration
   native byte[] loadFile(String name);
 //Load the library
   static {
     System.loadLibrary("nativelib");
   }
 
   public static void main(String args[]) {
      byte buf[];
 //Create class instance
      ReadFile mappedFile=new ReadFile();
 //Call native method to load ReadFile.java
      buf=mappedFile.loadFile("ReadFile.java");
 //Print contents of ReadFile.java
      for(int i=0;i<buf.length;i++) {
          System.out.print((char)buf[i]);
      }
   }
}
Native Method Declaration 

The native declaration provides the bridge to run the native function in the Java virtual machine.
In this example, the loadFile function maps onto a C function called Java_ReadFile_loadFile.
The function implementation accepts a String that represents a file name and returns the 
contents of that file in the byte array.
native byte[] loadFile(String name); Load the Library
The library containing the native code implementation is loaded by a call to System.loadLibrary().
Placing this call in a static initializer ensures this library is only loaded once per class.
The library can be loaded outside of the static block if your application requires it. You might 
need to configure your environment so the loadLibrary method can find your native code library.
static { 
     System.loadLibrary("nativelib"); 
}
Compile the Program
 
To compile the program, just run the javac compiler command as you normally would: 
javac ReadFile.java
Next, you need to generate a header file with the native method declaration and implement the 
native method to call the C functions for loading and reading a file. 

Generate the Header File 

To generate a a header file, run the javah command on the ReadFile class. In this example, 
the generated header file is named ReadFile.h. It provides a method signature that you have 
to use when you implement the loadfile native function.
javah -jni ReadFile
Note: When running javah on your own classes, be sure to use the fully-qualified class name.
Method Signature 

The ReadFile.h header file defines the interface to map the Java language method to the native
C function. It uses a method signature to map the arguments and return value of the Java
language mappedfile.loadFile method to the loadFile native method in the nativelib library.
Here is the loadFile native method mapping (method signature):
/* * Class: ReadFile * Method: loadFile * Signature: (Ljava/lang/String;)[B */ 
JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile (JNIEnv *, jobject, jstring);
The method signature parameters function as follows:
JNIEnv *: A pointer to the JNI environment. This pointer is a handle to the current thread 
in the Java virtual machine, and contains mapping and other hosuekeeping information. 
jobject: A reference to the method that called this native code. If the calling method is 
static, this parameter would be type jclass instead of jobject. 
jstring: The parameter supplied to the native method. In this example, it is the name of 
the file to be read. 
 
Implement the Native Method
 
In this native C source file, the loadFile definition is a copy and paste of the C declaration 
contained in ReadFile.h. The definition is followed by the native method implementation. 
JNI provides a mapping for both C and C++ by default.
#include <jni.h>
#include <sys/types.h>
#include <sys/
ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
 
JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile
  (JNIEnv * env, jobject jobj, jstring name) {
    caddr_t m;
    jbyteArray jb;
    jboolean iscopy;
    struct stat finfo;
    const char *mfile = (*env)->GetStringUTFChars(
                env, name, &iscopy);
    int fd = open(mfile, O_RDONLY);
    if (fd == -1) {
      printf("Could not open %sn", mfile);
    }
    lstat(mfile, &finfo);
    m = mmap((caddr_t) 0, finfo.st_size,
                PROT_READ, MAP_PRIVATE, fd, 0);
    if (m == (caddr_t)-1) {
      printf("Could not mmap %sn", mfile);
      return(0);
    }
    jb=(*env)->NewByteArray(env, finfo.st_size);
    (*env)->SetByteArrayRegion(env, jb, 0, 
 finfo.st_size, (jbyte *)m);
    close(fd);
    (*env)->ReleaseStringUTFChars(env, name, mfile);
    return (jb);
}
 
You can approach calling an existing C function instead of implementing one, in one of two ways: 
Map the name generated by JNI to the existing C function name. The Language Issues 
section shows how to map between Xbase database functions and Java language code 
Use the shared stubs code available from the JNI page on the java.sun.com web site.

Compile the Dynamic or Shared Object Library 

The library needs to be compiled as a dynamic or shared object library so it can be loaded at 
runtime. Static or archive libraries are compiled into an executable and cannot be loaded at 
runtime. The shared object or dynamic library for the loadFile example is compiled as follows:
Gnu C/Linux:
gcc  -o libnativelib.so -shared -Wl,-soname,libnative.so  
     -I/export/home/jdk1.2/include 
     -I/export/home/jdk1.2/include/linux nativelib.c  
     -static -lc
Gnu C++/Linux with Xbase
g++ -o libdbmaplib.so -shared -Wl,-soname,libdbmap.so  
    -I/export/home/jdk1.2/include 
    -I/export/home/jdk1.2/include/linux 
    dbmaplib.cc -static -lc -lxbase

Win32/WinNT/Win2000
cl -Ic:/jdk1.2/include 
   -Ic:/jdk1.2/include/win32 
   -LD nativelib.c -Felibnative.dll

Run the Example
 
To run the example, the Java virtual machine needs to be able to find the native library. To do this, 
set the library path to the current directory as follows:

Unix or Linux: LD_LIBRARY_PATH=`pwd` export LD_LIBRARY_PATH
Windows NT/2000/95: set PATH=%path%;.

With the library path properly specified for your platform, invoke the program as you normally would 
with the interpreter command:
 java ReadFile
 
 
2. 구글 안드로이드 상에서 JNI 지원 API

아래의 두가지 함수에 대한 안드로이드 상에서의 특별한 제약이 없다면 JNI 을 지원하기 위한 최소한의
조건은 만족된 듯하다
The core functional component is the use of the 'native' keyword and the bindings to the 
java.lang.System.loadLibary() API, which, does seem to be documented within the android reference:
 
java.lang.System
java.lang 
public final class
java.lang.System
java.lang.Object  
       java.lang.System 

Class System provides a standard place for programs to find system related information. 
All System API is static.
static  void  load(String pathName) : Loads the specified file as a dynamic library. 
static  void  loadLibrary(String libName) : Loads and links the library specified by the argument.

3. Dynamic & Shard Object Library 만들기
 
the question here is how to build a native .so (shared library), but we can refer to the JNI example 
above for instructions. we have also been informed, through this list that you can build native code 
on the device, but without UI bindings:
 
이 부분 중, 가장 어렵게 생각되는 부분은 Cross Compiler를 통해 shard object library를 만들 수 있느냐 일듯.
현재 안드로이드의 /system/lib 아래에는 안드로이드 Library들이 .so 형태로 존재함.
Posted by 삼스
Android/App개발2009. 7. 24. 17:15
class public .... extends Service 로 정의된 class들이며 실제 Service와 대응되는것은 아님.

1. MediaScannerService  
    ./packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerService.java
2. CalendarAppWidgetService
    ./packages/providers/CalendarProvider/src/com/android/providers/calendar/CalendarAppWidgetService.java
3. DownloadService
    ./packages/providers/DownloadProvider/src/com/android/providers/downloads/DownloadService.java
4. MediaPlaybackService
    ./packages/apps/Music/src/com/android/music/MediaPlaybackService.java
5. StkAppService
    ./packages/apps/Stk/src/com/android/stk/StkAppService.java
6. MailService
    ./packages/apps/Email/src/com/android/email/service/MailService.java
7. AlertService
    ./packages/apps/Calendar/src/com/android/calendar/AlertService.java
8. BluetoothHeadsetService
    ./packages/apps/Phone/src/com/android/phone/BluetoothHeadsetService.java
9. NetworkQueryService
    ./packages/apps/Phone/src/com/android/phone/NetworkQueryService.java
10. SmsReceiverService
    ./packages/apps/Mms/src/com/android/mms/transaction/SmsReceiverService.java
11. TransactionService
    ./packages/apps/Mms/src/com/android/mms/transaction/TransactionService.java
12. DemoImPlugin
    ./packages/apps/IM/samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java
13. FrontDoorPlugin
    ./packages/apps/IM/src/com/android/im/app/FrontDoorPlugin.java
14. RemoteImService
    ./packages/apps/IM/src/com/android/im/service/RemoteImService.java
15. RssService
    ./development/samples/MySampleRss/src/com/example/codelab/rssexample/RssService.java
16. LocalServiceTest
    ./development/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
17. ServiceStartArgument
    ./development/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java
18. RemoteService
    ./development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
19. NotifyingService
    ./development/samples/ApiDemos/src/com/example/android/apis/app/NotifyingService.java
20. AlarmService_Service
    ./development/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.java
21. LocalService
    ./development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
22. IIORegistry
    ./frameworks/base/awt/javax/imageio/spi/IIORegistry.java
23. MessengerService
    ./frameworks/base/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java
24. LocalService
    ./frameworks/base/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java
25. DisabledService
  ./frameworks/base/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledService.java
26. EnabledService
  ./frameworks/base/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledService.java
27. AbstractInputMethodService
    ./frameworks/base/core/java/android/inputmethodservice/AbstractInputMethodService.java
28. IntentService
    ./frameworks/base/core/java/android/app/IntentService.java
29. ServiceTestClass
    ./frameworks/base/test-runner/android/test/ServiceTestCase.java
30. LoadAverageService
    ./frameworks/base/services/java/com/android/server/LoadAverageService.java

Posted by 삼스
Android/App개발2009. 7. 24. 15:34


App에서 Framework을 통해 시스템서비스를 이용하는 구조에 대한 개념도임.

Posted by 삼스
Android2009. 7. 23. 23:10
Product설정파일을 통해 환경변수를 설정하여 선택적으로 빌드가능
 PRODUCT_NAME : 제품명
 PRODUCT_DEVICE : 디바이스명
 PRODUCT_LOCALE : 지역정보
 PRODUCT_PACKAGE_OVERLAY : 대체될 resource가 있는 Path
 PRODUCT_PROPERTY_OVERRIDES : 추가될 system property 항목이며 /system/build.prop에 저장됨.
 PRODUCT_PACKAGES : 기본적으로 설치될 app 목록

전체 과정을 간략히 설명하면, TARGET_BUILD_VARIANT에 따라서 System Property와 설치될 모듈을 결정합니다. 그 과정을 Makefile을 따라가면서 확인해 보겠습니다.

 

시작은 open_src폴더 아래 Makefile에서 build/core/main.mk로 이동합니다.

/Makefile

### DO NOT EDIT THIS FILE ###

include build/core/main.mk

### DO NOT EDIT THIS FILE ###

 

아래 build/core/main.mk를 보면 환경변수 TARGET_BUILD_VARIANT에 따라서 System Property를 다르게 설정하고 있습니다.

Part 1 : /build/core/main.mk

## user/userdebug ##

 

user_variant := $(filter userdebug user,$(TARGET_BUILD_VARIANT))

enable_target_debugging := true

ifneq (,$(user_variant))

  # Target is secure in user builds.

  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1

 

  tags_to_install := user

  ifeq ($(user_variant),userdebug)

    # Pick up some extra useful tools

    tags_to_install += debug

  else

    # Disable debugging in plain user builds.

    enable_target_debugging :=

  endif

 

  # TODO: Always set WITH_DEXPREOPT (for user builds) once it works on OSX.

  # Also, remove the corresponding block in config/product_config.make.

  ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)

    WITH_DEXPREOPT := true

  endif

 

  # Disallow mock locations by default for user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0

 

else # !user_variant

  # Turn on checkjni for non-user builds.

  ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1

  # Set device insecure for non-user builds.

  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0

  # Allow mock locations by default for non user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1

endif # !user_variant

 

ifeq (true,$(strip $(enable_target_debugging)))

  # Target is more debuggable and adbd is on by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1 persist.service.adb.enable=1

  # Include the debugging/testing OTA keys in this build.

  INCLUDE_TEST_OTA_KEYS := true

else # !enable_target_debugging

  # Target is less debuggable and adbd is off by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0 persist.service.adb.enable=0

endif # !enable_target_debugging

 

## eng ##

 

ifeq ($(TARGET_BUILD_VARIANT),eng)

tags_to_install := user debug eng

# Don't require the setup wizard on eng builds

#eng모드에서 ro.setupwizard.mode property를 뺍니다.

  ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\

          $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES)))

endif

 

 

TARGET_BUILD_VARIANT에 따른 동작은 아래와 같습니다.  Android.mk의 정의된 LOCAL_MODULE_TAGS를 정의하지 않은 모듈은 기본이 user 태그입니다. 따라서 이전에 eng로 설정되어 있는 모듈들이 설치되지 않은 이유는 명시적으로 eng태그를 설정해 주었기 때문입니다.

TARGET_BUILD_VARIANT

Actions

eng

- Installs modules tagged with: eng, debug, user, and/or development.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files, in addition to tagged APKs.

- ro.secure=0

- ro.debuggable=1

- ro.kernel.android.checkjni=1

- adb is enabled by default.

user

- Installs modules tagged with user.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files; tags are ignored for APK modules.

- ro.secure=1

- ro.debuggable=0

- adb is disabled by default.

userdebug

The same as user, except:

- Also installs modules tagged with debug.

- ro.debuggable=1

- adb is enabled by default.

 

 

빌드시 build/tools/findleaves.sh를 사용해서 각 폴더의 첫번째 Android.mk파일을 모두 찾아서 Makefile에 추가합니다. 하위 폴더에 Android.mk파일이 존재하더라도 상위 폴더에 Android.mk가 존재하면 상위 폴더에 있는 Android.mk까지만 찾습니다.

그리고 현재 Product설정파일의 TARGET_DEVICE BoardConfig.mk를 포함시킵니다.

 

Part 2 : /build/core/main.mk

# Can't use first-makefiles-under here because

# --mindepth=2 makes the prunes not work.

subdir_makefiles += \

    $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)

 

# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)

# or under vendor/*/$(TARGET_DEVICE).  Search in both places, but

# make sure only one exists.

# Real boards should always be associated with an OEM vendor.

board_config_mk := \

    $(strip $(wildcard \

        $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \

        vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \

    ))

ifeq ($(board_config_mk),)

  $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))

endif

ifneq ($(words $(board_config_mk)),1)

  $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))

endif

include $(board_config_mk)

TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

board_config_mk :=

 

# Clean up/verify variables defined by the board config file.

TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))

 

#

# Include all of the makefiles in the system

#

 

ifneq ($(ONE_SHOT_MAKEFILE),)

# We've probably been invoked by the "mm" shell function

# with a subdirectory's makefile.

include $(ONE_SHOT_MAKEFILE)

# Change CUSTOM_MODULES to include only modules that were

# defined by this makefile; this will install all of those

# modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE

# so that the modules will be installed in the same place they

# would have been with a normal make.

CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS),))

FULL_BUILD :=

INTERNAL_DEFAULT_DOCS_TARGETS :=

# Stub out the notice targets, which probably aren't defined

# when using ONE_SHOT_MAKEFILE.

NOTICE-HOST-%: ;

NOTICE-TARGET-%: ;

else

include $(subdir_makefiles)

endif

# -------------------------------------------------------------------

# All module makefiles have been included at this point.

# -------------------------------------------------------------------

 

build/tools/findleaves.sh 동작 예제

$find hardware –name “*.mk”

hardware/libhardware/Android.mk

hardware/libhardware/modules/overlay/Android.mk

hardware/libhardware_legacy/Android.mk

hardware/libhardware_legacy/flashlight/Android.mk

hardware/libhardware_legacy/gps/Android.mk

hardware/libhardware_legacy/led/Android.mk

hardware/libhardware_legacy/mount/Android.mk

hardware/libhardware_legacy/power/Android.mk

hardware/libhardware_legacy/qemu/Android.mk

hardware/libhardware_legacy/qemu_tracing/Android.mk

hardware/libhardware_legacy/tests/gpstest/Android.mk

hardware/libhardware_legacy/uevent/Android.mk

hardware/libhardware_legacy/vibrator/Android.mk

hardware/libhardware_legacy/wifi/Android.mk

hardware/ril/libril/Android.mk

hardware/ril/rild/Android.mk

hardware/ril/gpstest/Android.mk

hardware/ril/libsecril-client/Android.mk

hardware/ril/rilclient-test/Android.mk

hardware/ril/secril_multi/Android.mk

hardware/modules/sensors/Android.mk

hardware/msm7k/Android.mk

hardware/msm7k/libaudio/Android.mk

hardware/msm7k/libcamera/Android.mk

hardware/msm7k/libcopybit/Android.mk

hardware/msm7k/librpc/Android.mk

hardware/msm7k/yuv420sp2rgb/Android.mk

 

$ ./build/tools/findleaves.sh hardware Android.mk

hardware/libhardware/Android.mk => 폴더구조의 첫번째 Android.mk만 포함됨

hardware/libhardware_legacy/Android.mk

hardware/modules/sensors/Android.mk

hardware/msm7k/Android.mk

hardware/ril/gpstest/Android.mk

hardware/ril/libril/Android.mk

hardware/ril/libsecril-client/Android.mk

hardware/ril/rilclient-test/Android.mk

hardware/ril/rild/Android.mk

hardware/ril/secril_multi/Android.mk

 

hardware/msm7k/Android.mk 파일에서 아래와 같이 하위의 Android.mk파일을 상황에 따라서 include를 하여 필요한 모듈만 컴파일하여 추가시킬 때 사용할 수 있습니다. (이것을 사용해서 Samsung Open Source쪽 변경 소스 관리를 할 수 있을 것으로 보입니다. )

ifneq ($(filter capella7200, surf, $(TARGET_DEVICE)), )

  include $(all-subdir-makefiles)

endif

 

설치될 모듈들을 선택하고, LOCAL_OVERRIDES_PACKAGES로 선택된 Package를 항목에서 삭제합니다.

Part 3 : build/core/main.mk

# -------------------------------------------------------------------

# Figure out our module sets.

 

# Of the modules defined by the component makefiles,

# determine what we actually want to build.

# If a module has the "restricted" tag on it, it

# poisons the rest of the tags and shouldn't appear

# on any list.

Default_MODULES := $(sort $(ALL_DEFAULT_INSTALLED_MODULES) \

                          $(ALL_BUILT_MODULES) \

                          $(CUSTOM_MODULES))

# TODO: Remove the 3 places in the tree that use

# ALL_DEFAULT_INSTALLED_MODULES and get rid of it from this list.

 

ifdef FULL_BUILD

  # The base list of modules to build for this product is specified

  # by the appropriate product definition file, which was included

  # by product_config.make.

  user_PACKAGES := $(call module-installed-files, \

                       $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES))

  ifeq (0,1)

    $(info user packages for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)

    $(foreach p,$(user_PACKAGES),$(info :   $(p)))

    $(error done)

  endif

else

  # We're not doing a full build, and are probably only including

  # a subset of the module makefiles.  Don't try to build any modules

  # requested by the product, because we probably won't have rules

  # to build them.

  user_PACKAGES :=

endif

# Use tags to get the non-APPS user modules.  Use the product

# definition files to get the APPS user modules.

user_MODULES := $(sort $(call get-tagged-modules,user,_class@APPS restricted))

user_MODULES := $(user_MODULES) $(user_PACKAGES)

 

eng_MODULES := $(sort $(call get-tagged-modules,eng,restricted))

debug_MODULES := $(sort $(call get-tagged-modules,debug,restricted))

tests_MODULES := $(sort $(call get-tagged-modules,tests,restricted))

 

ifeq ($(strip $(tags_to_install)),)

$(error ASSERTION FAILED: tags_to_install should not be empty)

endif

modules_to_install := $(sort $(Default_MODULES) \

          $(foreach tag,$(tags_to_install),$($(tag)_MODULES)))

 

# Some packages may override others using LOCAL_OVERRIDES_PACKAGES.

# Filter out (do not install) any overridden packages.

overridden_packages := $(call get-package-overrides,$(modules_to_install))

ifdef overridden_packages

#  old_modules_to_install := $(modules_to_install)

  modules_to_install := \

      $(filter-out $(foreach p,$(overridden_packages),$(p) %/$(p).apk), \

          $(modules_to_install))

endif

 

추가로Android의 모든 Application은 고유한 Key를 사용해서 Signning을 수행해야 합니다. 어떤 Key Signning을 할지를 결정은 LOCAL_CERTIFICATE에 기술합니다.

packages/apps/Camera/Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_MODULE_TAGS := user

 

LOCAL_SRC_FILES := $(call all-java-files-under, src)

 

LOCAL_PACKAGE_NAME := Camera

LOCAL_CERTIFICATE := media

#LOCAL_CERTIFICATE := vendor/samsung/products/security/media   => 명시적으로 선택가능

 

LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client

 

#include $(BUILD_PACKAGE)

 

# Use the following include to make our test apk.

#include $(call all-makefiles-under,$(LOCAL_PATH))

 

package.mk파일을 보시면 LOCAL_CERTIFICATE가 설정되지 않으면 testkey가 사용되며, 관련 private certificate /build/target/product/security/폴더에 있는 key값을 사용합니다.

mkkey.sh   => key값을 생성하기 위한 명령어, Samsung Android폰 개발시 고유한 key를 생성해서 출시해야함.

media.pk8

media.x509.pem

platform.pk8

platform.x509.pem

shared.pk8

shared.x509.pem

testkey.pk8

testkey.x509.pem

 

/build/core/package.mk

# Pick a key to sign the package with.  If this package hasn't specified

# an explicit certificate, use the default.

# Secure release builds will have their packages signed after the fact,

# so it's ok for these private keys to be in the clear.

ifeq ($(LOCAL_CERTIFICATE),)

    LOCAL_CERTIFICATE := testkey

endif

# If this is not an absolute certificate, assign it to a generic one.

ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)

    LOCAL_CERTIFICATE := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE)

endif

private_key := $(LOCAL_CERTIFICATE).pk8

certificate := $(LOCAL_CERTIFICATE).x509.pem

 

$(LOCAL_BUILT_MODULE): $(private_key) $(certificate) $(SIGNAPK_JAR)

$(LOCAL_BUILT_MODULE): PRIVATE_PRIVATE_KEY := $(private_key)

$(LOCAL_BUILT_MODULE): PRIVATE_CERTIFICATE := $(certificate)

 

PACKAGES.$(LOCAL_PACKAGE_NAME).PRIVATE_KEY := $(private_key)

PACKAGES.$(LOCAL_PACKAGE_NAME).CERTIFICATE := $(certificate)

 

# Define the rule to build the actual package.

$(LOCAL_BUILT_MODULE): $(AAPT) | $(ZIPALIGN)

$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries)

$(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)

    @echo "target Package: $(PRIVATE_MODULE) ($@)"

    $(create-empty-package)

    $(add-assets-to-package)

ifneq ($(jni_shared_libraries),)

    $(add-jni-shared-libs-to-package)

endif

ifneq ($(full_classes_jar),)

    $(add-dex-to-package)

endif

    $(sign-package)

    @# Alignment must happen after all other zip operations.

    $(align-package)

 

# Save information about this package

PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))

PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources)

 

PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)

 

Posted by 삼스
Android/App개발2009. 7. 23. 19:33
In order to use in on the device (use the attached busybox.tar)
$ tar -xvf busybox.tar 
$ adb shell 
# mkdir /data/busybox
# exit
$ adb push busybox /data/busybox
$ adb shell 
# cd data/busybox
# ./busybox --install
# export PATH=/data/busybox:$PATH

Posted by 삼스
Android/App개발2009. 7. 20. 20:23
Parcelable Object 만들기 (1) Android Life 

2009/07/17 16:24

복사http://blog.naver.com/visualc98/74522627


[Parcel Class?]

 

Android의 핵심 중에서 Binder Driver라는 녀석이 있습니다.
Linux Kernel의 driver로 되어 있고, IPC이긴 하지만 기존의 IPC와는 살짝 다른 녀석 입니다.

 

저도 어떻게 만들었는지는 잘 모릅니다만, 
shared memory를 통하여 오버헤드도 적고 프로세스 사이에 비동기로 호출도 이루어 진다고 합니다.
그리고 Binder는 기존 IPC처럼 데이터만 전달 하는게 아니라,
하나의 프로세스에서 다른 프로세스로 Object를 넘길 수도 있게끔 설계 되어 있습니다.
(물론 Serialize 기술을 사용하면 Object도 주고 받을 순 있지요.)

 

Binder를 통해서 넘기는 메세지 (data 와 object references) 는 
Parcel 클래스에 저장이 되어서 넘어가게 됩니다. Parcel은 메세지 컨테이너인 셈이죠.

Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport.

Parcel 클래스는 고성능 IPC 전송을 가능하게 끔 설계가 되어 있기 때문에,

모든 객체에 대해서 평범하게 serialization하지 않습니다. 
그래서 모든 Object들을 Binder를 통해 주고 받을 수는 없습니다.

 


[Parcelable Interface]

 

Primitive Type과 Primitive Array Type은 기본적으로 parcelable 합니다.

뭐 그냥 일반 데이터인거죠.
그리고 
Parcelable Interface를 implements한 클래스가 (당연히) parcelable 합니다.

 

오늘 우리가 할 일이 바로 이 Parcelable Interface를 사용하여
parcelable Object를 만드는 일 인 것이죠.

사실 parcelable한 type들이 많이 있습니다만, 나머지는 잘 모르겠군요... 어렵습니다.
여튼 오늘은 parcelable Object를 만드는 것만 생각 합시다.

 


[Parcelable Rect]

 

Rect 클래스야 다들 쉽게 만드실 겁니다.
left, top, right, bottom 4개의 필드만 있으면 되죠.


integer든 float이든 상관 없습니다만....
Android에는 Rect 클래스의 float 버전이 RectF 클래스 라고 따로 되어 있기 때문에,

저는 integer로 만들겁니다.


public class Rect {
    public int left;
    public int top;
    public int right;
    public int bottom;
}


뭐 아주 간단 합니다. 그냥 C에서의 구조체 수준이네요.
이것을 parcelable하게 바꾸어 봅시다.

 

Step 1.


public class Rect implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;
    
    public int describeContents() {
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(left);
        dest.writeInt(top);
        dest.writeInt(right);
        dest.writeInt(bottom);
    }
}


Parcelable을 implements하게 되면 꼭 추가해야 한다는 메소드 두 개도 같이 넣었습니다.
내용도 채워 봤어요.

 

describeContents() 메소드는 일단 건너뛰고...
writeToParcel() 메소드는 Parcel에 데이터를 쓰는 부분 입니다.
그냥 무작정 쓰면 됩니다. 전 아무 생각 없이 순서대로 그냥 썼습니다.

 

그럼 이제 에러도 없으니 parcelable한 Rect 클래스가 되었느냐... 라고 한다면 아직 아닙니다.
쓰는건 있는데 읽는건 없네요...

 

Parcel로 부터 값을 읽어 오기 위해서는 Parcelable.Creator Interface 가 필요합니다.

 


[Parcelable.Creator Interface]

 

Parcel 에서 Parcelable 클래스의 인스턴스를 만들 때
CREATOR라는 static field를 찾아서 실행 합니다.
CREATOR는 
Parcelable.Creator<T> type 으로 만들어져야 하는데 
이건 선언과 동시에 반드시 initialize 되어야 합니다.

 

클래스 따로 만들어서 initialize 하기도 쉽지 않습니다.
그냥 익명 클래스로 만들어 버립시다.

 

Step 2.


public class Rect implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;
    
    public int describeContents() {
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(left);
        dest.writeInt(top);
        dest.writeInt(right);
        dest.writeInt(bottom);
    }
    
    public static final Parcelable.Creator<Rect> CREATOR new Creator<Rect>() {
        public Rect createFromParcel(Parcel source) {
            Rect r   = new Rect();
            r.left   = source.readInt();
            r.top    = source.readInt();
            r.right  = source.readInt();
            r.bottom = source.readInt();
            return r;
        }
        public Rect[] newArray(int size) {
            return new Rect[size];
        }
    };
}


Parcelable.Creator<T> 클래스는 createFromParcel() 과 newArray() 메소스가 필요 합니다.

 

newArray() 메소드도 일단 넘어가고...
createFromParcel() 메소드를 보면 리턴이 Rect입니다.
그래서 Parcel에서 값을 읽어 새로운 Rect 인스턴스를 리턴 하는 구조로 만들면 끝입니다.

 

readInt()를 했는데, 이것은 writeToParcel() 메소드에서 썼던 순서대로 읽어 오는 것입니다.
쓸 때는 무작정 썼지만 읽을 때는 조심스럽게 읽어야하죠.

 

이제 비로소 parcelable Rect 클래스를 만들었습니다.
그냥 별거 없군요...

 


[Appendix]

 

위에서 describeContents() 메소드와 newArray() 메소드는 그냥 넘어 갔었습니다.
네... 뭐 사실 잘 모르기도 합니다만, 
그냥 보통 parcelable Object를 만드는데에 크게 중요한 부분은 아니지요. 아하하...

 

describeContents() 에서는 어떤 특별한 객체를 포함하고 있는지에 대한 설명을
리턴값으로 표현 하는 것이라고 보면 됩니다.
bit mask 형식의 integer를 리턴 하며,
값을 체크 할 때 bit mask 체크를 해서 어떤 것들이 들어 있는지 알 수 있습니다.

 

현재 사용하는 플래그는 Parcelable.CONTENTS_FILE_DESCRIPTOR (0x00000001) 
하나 밖에 정의 되어 있지 않습니다.
소스를 다 뒤져 보지 않아서 또 어떤 값들이 쓰이는지는 확인 해보지 못했네요...

 

newArray() 메소드는 그냥 배열로 만들어서 리턴 하는 겁니다.
Parcel.createTypedArray() 메소드에서 newArray() 메소드를 호출 하는 걸 확인 했습니다.
나중에 createTypedArray() 메소드를 사용 할 일이 있다면 newArray()가 호출이 되는 것이지요.

Posted by 삼스