개발한 앱 중에 잘동작되던 BroadcastReceiver가 다른사람이 소스를 수정 후 1회만 작동하고 동작이 되지 않는 현상이 나타났다.

사용한 형태는 Service에서 registerReceiver()와 unregisterReceiver()를 사용한 동적 리시버 형태이다.

 

원인을 파악한 결과 다음과 같았다.

 

다른 소스에서 해당 서비스를 적당한 인자를 넣은 intent를 포함시켜 startService()로 호출하여

onStartCommand()에서 전달된 intent의 구분자에 따라 registerReceiver() 및 unregisterReceiver()를 하도록한 형태로

서비스내에서 지속적으로 리시버가 동작하지 않고, onStartCommand를 통해 1회만 동작하고 정지되어 버렸다.

 

또한 dumpsys를 통해 해당 앱의 서비스에 등록된 리시버를 분석한 결과 등록한 리시버가 적당한 때에 해제되지 않아 메모리 누수로 이어지는 것을 확인하였다.

 

연구결과 동적 리시버는 서비스(Service) 또는 액티비티(Activity)의 생명주기(Lifecycle)를 같이 하도록 사용하는 것이 좋다는 결론이다.

즉, onCreate()에서 해당 리시버의 registerReceiver()를 호출하여 등록을 하고,

onDestroy()에서 unregisterReceiver()를 호출하여 리시버를 등록해제 하는 것이다.

 

다만 서비스가 강제 종료되면 동적 리시버가 동작하지 않게 되므로 적당한 서비스 감시 또는 재시작 루틴이 필요할 것이다.

아니면 정적 리시버 사용을 고려해야 한다.

Posted by dcmru
,

안드로이드에서 실행가능한 명령어를 컴파일하여 실행 시 다음과 같은 에러가 발생한다.

error: only position independent executables (PIE) are supported.


다음 옵션을 gcc에 붙여준 후 컴파일 한다.

CFLAGS="-fPIE"
CPPLAGS="$CPPFLAGS -fPIE"
CXXLAGS="$CXXFLAGS -fPIE"
LDFLAGS="-fPIE -pie"

Posted by dcmru
,

다음 명령어로 안드로이드 쉘에 접속한다.

$ adb shell


접속된 안드로이드 쉘에서 다음 명령을 실행하면 /system을 rw로 마운트 할 수 있다.

$ su -

# /system/bin/mount -o remount,rw /system

 

다시 read only로 바꾸려면 다음과 같은 명령어를 실행한다.

# /system/bin/mount -o remount,ro /system

Posted by dcmru
,

Android Studio 1.5에서 안드로이드 프로젝트 오픈 시 아래 에러가 발생하였다.


Unable to load class org.gradle.api.publication.maven.internal.DefaultMavenFactory


Caused by: java.lang.NoClassDefFoundError: org/gradle/api/publication/maven/internal/DefaultMavenFactory


Android Studio 1.5는 Gradle 2.4를 기본으로 사용하고, Gradle 2.4는 android-maven-gradle-plugin를 1.3 버전을 사용해야 한다.


root build.gradle 파일을 열어서  아래 내용으로 classpath 선언해 준다.


buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
    }
}


참고: https://github.com/dcendents/android-maven-gradle-plugin

Posted by dcmru
,

우분투 12.04 64bits에 ADT를 설치 후 사용을 하다가 Android Virtual Device Manager에서 AVD 생성 시


"No system images installed for this target"가 표시되며 AVD를 생성할 수 없었다.


해당 API 버전에 ARM EABI v7a System Image는 당연히 설치한 상태이다.



다음 그림에서와 같이 "CPU/ABI"에서 처럼 시스템 이미지를 선택할 수가 없다.



원인은 터미널에서 아래 명령과 같이 Android SDK Manager와 Android Virtual Device Manager를 실행할 수가 있는데, 이 때 경로가 꼬이는 것으로 보인다.

$ android

$ android avd



즉 sdk/system-images/android-19/armeabi-v7a와 같은 경로에 system image가 있어야 하는데


sdk/system-images/android-16/default/armeabi-v7a와 같이 경로 중간에 default가 추가로 들어있다.


해결 방법은 중간의 default를 없애주는 것이다. 아래의 경로가 되도록 디렉터리를 옮겨준다.


sdk/system-images/android-16/default/armeabi-v7a -> sdk/system-images/android-16/armeabi-v7a


아래 그림과 같이 "CPU/ABI"에서 system image를 선택할 수 있게된다.



Posted by dcmru
,

우분투 12.04 64bits에서 adt를 x86_64버전으로 받은 후 아래 에러가 발생하였다.


다운로드 받은 adt가 깨졌는지 md5sum으로 Hash 값을 체크를 해봐도 이상이 없었다.


- adt에서 발생하는 에러

[2014-03-10 15:24:57 - adb] Unexpected exception 'Cannot run program "/home/dckim/android/adt-bundle-linux-x86_64-20131030/sdk/platform-tools/adb": java.io.IOException: error=2, 그런 파일이나 디렉터리가 없습니다' while attempting to get adb version from '/home/dckim/android/adt-bundle-linux-x86_64-20131030/sdk/platform-tools/adb'


- 커맨드 라인에서 발생하는 에러

adt-bundle-linux-x86_64-20131030/sdk/platform-tools/adb: 그런 파일이나 디렉터리가 없습니다


- is32-libs를 설치해주면 해결이 된다.

$ sudo apt-get install ia32-libs

Posted by dcmru
,

Nexus 5의 remount는 다음과 같이 명령을 실행한다.

 

rooting한 후 adb shell에서 su명령어로 root 권한을 얻은 후에 다음과 같이 실행한다.

 

# mount -o remount rw /system

 

mount 명령어로/system에 ro에서 rw로 바뀌었는지 확인해본다. 

Posted by dcmru
,

안드로이드에서 개발을 하는 도중 테스트 버전의 실행파일의 메모리 leak을 체크하고자 valgrind를 사용해보기로 결정하고 방법을 정리해보고자 한다.


valgrind는 우분투 12.04 64bits에서 컴파일을 하였고 안드로이드 NDK가 필요하며 NDK를 안드로이드 developer 사이트에서 다운로드 받아 압축을 풀어 사용한다.


참고로 컴파일에 사용한 NDK 버전은 android-ndk-r9 이고 valgrind를 사용하기 위해서는 rooting이 필요하다.


valgrind의 컴파일은 http://valgrind.org/docs/manual/dist.readme-android.html 를 참고하였다.

위의 사이트에서 실행을 확인한 Android 버전은 다음과 같이 소개하고 있다.


ARM:
  Android 4.0.3 running on a (rooted, AOSP build) Nexus S.
  Android 4.0.3 running on Motorola Xoom.
  Android 4.0.3 running on android arm emulator.
  Android 4.1   running on android emulator.
  Android 2.3.4 on Nexus S worked at some time in the past.

x86:
  Android 4.0.3 running on android x86 emulator.


http://valgrind.org/downloads/ 에서 valgrind 3.9.0 (tar.bz2)를 다운로드 하였다.


순서대로 명령을 실행한다.


$ cd valgrind-3.9.0

$ export NDKROOT=~/android-ndk-r9


하드웨어 종류를 설정하는데 확인된 설정은 다음과 같다.

 

export HWKIND=nexus_s         # Samsung Nexus S; also Xoom (for now)
export HWKIND=generic         # A generic Android device. eg, Pandaboard
export HWKIND=emulator        # Android emulator


$ export HWKIND=emulator

$ export AR=$NDKROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-ar
$ export LD=$NDKROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-ld
$ export CC=$NDKROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc


아래 설정에서 --with-tmpdir=/storage/sdcard는 SD card의 경로로 valgrind 실행 시 임시 파일을 쓰기 위해 필요한 경로이다.

테스트하고자 하는 단말이나 에뮬레이터의 실제 SD card의 경로를 써야 한다. 그렇지 않으면 valgrind 실행 시 에러가 발생한다.


$ CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm -DANDROID_HARDWARE_$HWKIND" \
   CFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm" \
   ./configure --prefix=/data/local/Inst \
   --host=armv7-unknown-linux --target=armv7-unknown-linux \
   --with-tmpdir=/storage/sdcard

 

명령 실행 후 마지막 줄에 아래의 항목이 표시되는지 확인한다.
"Primary -DVGPV string: -DVGPV_arm_linux_android=1"

 

$ make -j2
$ make -j2 install DESTDIR=`pwd`/Inst


adb push로 Inst 디렉터리를 에뮬레이터나 단말의 /data/local/Inst로 업로드 한다.


$ adb push Inst /

$ adb shell

$ /data/local/Inst/bin/valgrind [the usual args etc]


갤럭시 노트3의 안드로이드 4.3 버전에 valgrind를 실행한 결과 아래 에러가 발생하면서 실행이 되지 않았다.


root@hlteskt:/data/local/tmp # /data/local/Inst/bin/valgrind
valgrind: failed to start tool 'memcheck' for platform 'arm-linux': Permission denied

 

/data/local/Inst/lib/valgrind/memcheck-arm-linux 가 연관이 있다고 하는데 해결 방법을 찾을 수는 없었다.

아마도 /data의 마운트 관련된 문제이거나 Knox와 연관이 있지 않을까 하는 추측을 해본다.

그리고 export HWKIND=nexus_s, export HWKIND=generic, export HWKIND=emulator 로 각각 설정을 바꾸어 시도해보았으나 같은 에러가 발생하였다.

할 수 없이 에뮬레이터(Android 4.3)를 구동하여 사용하였다.

 

/data/local/Inst/lib/valgrind/ 내의 라이브러리의 퍼미션을 755로 설정하면 실제 단말에서도 된다.


에뮬레이터(Android 4.3)는 /data/local/Inst/lib/valgrind/ 퍼미션을 설정하지 않아도 구동하여 사용할 수 있었다.

Inst 디렉터리의 사이즈가 대략 150MB이므로 에뮬레이터의 /data 디렉터리의 용량을 충분하게 잡아줘야 한다.

/data 디렉터리의 용량을 늘리는 방법은 http://dcmru.tistory.com/2511037 글을 참고한다.


동적라이브러리까지 체크를 하기 위해서는 아래와 같은 방법으로 한다.

LD_PRELOAD="/path/to/library.so:/path/to/library1.so" valgrind -v --trace-children=yes --leak-check=full prog-and-args


참고

http://valgrind.org/docs/manual/dist.readme-android.html

http://stackoverflow.com/questions/12621418/valgrind-find-memory-leak-in-a-shared-library

http://abipictures.tistory.com/939


Posted by dcmru
,

Android의 emulator에서 /data의 크기를 늘려주는 방법은 다음과 같다.


경로는 Ubuntu를 예로 설명하지만 다른 OS도 설정의 옵션은 같으므로 설정파일의 경로만 바꾸어 적용하면 된다.


"~/.android/avd/<name.avd>/config.ini" 파일을 열어 "disk.dataPartition.size=512"와 같이 크기를 변경해주면 된다.


512는 MiB 단위이고 값을 수정한 후 에뮬레이터를 재시작 해준다.


참고: http://stackoverflow.com/questions/2239330/how-to-increase-storage-for-android-emulator-install-failed-insufficient-stora

Posted by dcmru
,

Ubuntu 12.04 x86_64에 adt-bundle-linux-x86_64-20130729.zip를 설치 후 eclipse를 실행 한 다음

 

Android Virtual Device Manager에서 AVD 생성 시 SD card에 Size를 입력하고, AVD를 생성하였을 때

 

"Failed to create the SD card." 에러가 발생한다면, 다음 패키지를 설치하면 에러가 해결된다.

 

$ sudo apt-get install ia32-libs

 

에러가 발생한 이유는 64bits Ubuntu에는 ia32-libs가 기본적으로 설치되어 있지 않아서이다.

 

참고: http://stackoverflow.com/questions/3878445/ubuntu-error-failed-to-create-the-sd-card

Posted by dcmru
,

안드로이드 SDK와 ADT를 21.1.0에서 22.0.0으로 업데이트한 후 실행이 잘되던 프로젝트를 실행하자 ClassNotFoundException이 발생하였다.

 

해결방법은 해당 프로젝트에서 Project -> Properties -> Java Build Path -> Order & Export 에서

 

Android Private Libraries와 사용자가 추가한 모든 라이브러리를 체크 한 후 프로젝트를 Clean하면 해결이 된다.

 

참고: http://stackoverflow.com/questions/16610190/classnotfoundexception-after-adt-update

Posted by dcmru
,
안드로이드 개발을 위한 이클립스 환경을 새로 구성을 하고,

애플리케이션 배포를 위해 사인을 하니 ProGuard 룰 에러가 발생하면서 사인이 되지 않았다.

에러 내용은 "Proguard returned with error code 1. See console" 이고, 콘솔에 ProGuard 룰 에러가 찍힌다.


해결방법으로는 ProGuard를 업데이트하여 해결하였다.

http://proguard.sourceforge.net/ 에서 V4.7 ProGuard를 다운 받은 후 안드로이드 SDK 내에 tools/proguard/lib 내의

proguard.jar, proguardgui.jar, retrace.jar 파일을 교체해주면 된다.
Posted by dcmru
,
여느 때와 같이 안드로이드 애플리케이션을 이클립스에서 개발하기 위해 이클립스를 실행하자 아래 그림과 같이 X 표시가 나타났다.


보통 이럴 경우 아래의 방법으로 해결이 되었는데, 해결이 되지 않았다.

- 프로젝트 Properties의 encoding을 사용하던 UTF-8로 변경
- 프로젝트 Properties의 안드로이드 빌드 타겟 변경
- 프로젝트 Properties의 Builders와 Java Build Path에 체크 안되어 있는 것이 있나 확인
- 프로젝트 Properties의 컴파일러 버전도 1.6에서 1.5로 변경
- 프로젝트 clean하고 다시 빌드
- Android tools의 Fix Project Properties도 실행
- 프로젝트 내에서 자동으로 생성되는 항목들(R.java, gen, bin, .setting 등) 삭제하고 다시 프로젝트를 생성
- 이클립스 workspace내의 .metadata를 삭제

이틀동안 삽질 끝에 Error Log이외에 Problems가 있는 것을 확인, 이클립스내의 프로젝트의 문제 내용이 표시되는 것을 확인하였다.

 


문제의 원인은 그림에 표시된 것과 같이 Debug Certificate expired로 Debug 사인키의 사용기한이 만료된 것이었다.

보통 이클립스를 처음 실행시 디버그키가 자동적으로 생성되며, 사용기한은 기본적으로 1년이다.

이와 같은 에러가 발생을 하고, 자신의 이클립스 안드로이드 환경을 구성한지 1년이 되었다면, 위의 방법을 통해 문제 발생의 원인을 알 수 있다.

그렇다면, 문제의 해결방법은 디버그 키를 새로 생성하는 것이다.

디버그 키의 저장 경로는 Windows 7과 Vista의 경우 C:\Users\<user>\.android\debug.keystore이고,

Windows XP 이하 C:\Documents and Settings\<user>\.android\debug.keystore이다.

위의 파일을 삭제하고, 프로젝트를 새로 빌드하면, 디버그키는 자동으로 새로 생성된다.

http://developer.android.com/guide/publishing/app-signing.html

위의 링크도 한 번 확인해 보기 바란다.
Posted by dcmru
,

SQLite 암호화 기능을 사용하려고, File Signer을 사용하여 셀프 사인 후 cod 파일을 더블 클릭하면,

Signature Tool이 실행되어 사인 정보를 확인할 수 있다고, 문서에 나와있어 따라해 보았으나 키쌍을 찾을 수 없다는 에러 창이 떴다.

포럼에서 관련 에러를 찾아보니 JDK 1.5 버전을 설치하라고 하여 설치하였던 1.6을 지우고 1.5를 설치하였다.

이클립스를 실행했더니 BlackBerry에 관련된 메뉴가 하나도 안보인다.

하루 삽질을 하고 다음날 BlackBerry 다운로드 페이지를 살펴보니 JDK 1.6과 호환된다고 나와있다.

아마도 플러그인이 업데이트 되면서, 호환되는 JDK 버전도 올라간듯 하다.

그러므로 절대 JDK 1.5 버전을 설치하고, 이클립스에서 BlackBerry 플러그인을 설치하는 일이 없길 바란다.

설치한 플러그인 버전은 1.1.2.201004161203-16 이다.

그리고 앞서 에러가 발생한 Signature Tool은 수동으로 실행하여 cod 파일이 있는 곳을 찾아 열어주면 된다.

http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800901/What_Is_-_Supported_versions_of_Java_for_different_BlackBerry_JDE_versions.html?nodeid=1313614&vernum=0
Posted by dcmru
,

SVN을 사용하여 기존 프로젝트를 새로 정리하고, 새로 올린 프로젝트를 체크아웃하여 이클립스에서 import 하였다.

프로젝트에 빨간 에러가 뜨길래 기존에 했던것 처럼 clean을 해봤지만 에러가 없어지지 않았다.

에러 내용은 "Error!: Invalid class file: Incorrect classfile version" 이다.

blackberryforum에 검색 결과 버그란다. 헤결방법은 컴파일러 버전을 1.4로 바꾸라는 내용이었다.

"프로젝트 속성->Java Compiler->Enable project specific settings 체크->Compiler compliance level: 1.4" 로 변경해주고,

에뮬레이터를 실행해보니 에러가 사라졌다.

이클립스는 3.5 갈릴레오 버전이고, JDK는 1.6.0_23 버전이다.

Posted by dcmru
,

Ubuntu 32bit x86에서 안드로이드 소스 컴파일 시 http://source.android.com/download 에서 확인을 해보면 아래와 같은 패키지가 필요하다.

  • Required Packages:
    • Git 1.5.4 or newer and the GNU Privacy Guard.
    • JDK 5.0, update 12 or higher.  Java 6 is not supported, because of incompatibilities with @Override.
    • flex, bison, gperf, libsdl-dev, libesd0-dev, libwxgtk2.6-dev (optional), build-essential, zip, curl.  
$ sudo apt-get install git-core gnupg sun-java5-jdk flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev
  • You might also want Valgrind, a tool that will help you find memory leaks, stack corruption, array bounds overflows, etc. 
$ sudo apt-get install valgrind
  • Intrepid (8.10) users may need a newer version of libreadline:
$ sudo apt-get install lib32readline5-dev

하지만 기본 설정에서 apt-get install sun-java5-jdk 로는 설치가 되지 않는다. sun-java6-jdk 를 설치하여 make 해보았으나 역시나 Java 6 버전으로는 컴파일이 되지 않는다.

그러므로 apt-get 으로 sun-java5-jdk 설치를 하는 방법은 다음과 같다.

1. vi 로 /etc/apt/sources.list 를 열어 아래 내용을 추가 한다.
deb http://ko.archive.ubuntu.com/ubuntu/ jaunty multiverse
deb http://ko.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse

2. apt-get install sun-java5-jdk

3. update-alternatives --config java 를 실행하여 java-1.5.0-sun 번호를 선택한다.

4. /<HOME>/.bash_profile에서 JAVA_HOME 환경 변수에 /usr/lib/jvm/java-1.5.0-sun 을 설정한다.

5. source /<HOME>/.bash_profile 또는 해당 계정 재로그인 후 make를 하면 에러 없이 컴파일되는 것을 볼 수 있다.
Posted by dcmru
,