Android/정리2009. 12. 1. 17:56
2009년 11월 배포, framework API가 변경되었으며 사용자와 개발자에게 새로운 feature를 제공한다.
SDK에 다운로드하여 콤포넌트의 설치가 가능하다.

새로운 UI
 * Contacts and accounts
   - Email과 Contacts에 여러개의 계정을 사용할 수 있다(Exchange account포함).
   - 개발자가 Sync adapter를 추가할 수 있다(원하는 포맷의 동기화를 직접 구현할 수 있다).
   - Quick Contact기능은 contact에 대한 정보와 communication mode에 대해 빠른 억세스를 할수 있게 해준다. Photo, Call, SMS, email등의 기능을 바로 실행할 수 있다.
 * Email
   - Exchange 지원
   - 하나의 페이지내에서 다중사용자의 이메일을 보기 위한 이메일박스를 통합하여 보여준다.
 * Messaging
   - 모든 저장된 SMS, MMS message의 검색기능
   - 조건에 따른 오래된 메세지 자동삭제 기능
 * Camera
   - flash 지원
   - Digital zoom
   - Scene mode
   - White balance
   - Color effect
   - Macro focus
 * Andorid Virtual keyboard
   - 문자를 더 정확하게 입력하고 편하도록 keyboard layout개선
   - multitouch 기능의 안정화(두손가락이 빠르게 입력될 때 key press가 사라지지 않도록 함)
   - 더 스마트해진 사전기능.
 * Browser
   - 동작가능한 URL bar로 입력된 주소로 search나 이동이 가능함.
   - webpage thumnail기반의 bookmark
   - double-tab zoom지원
   - HTML5지원
    • Database API support, for client-side databases using SQL.
    • Application cache support, for offline applications.
    • Geolocation API support, to provide location information about the device.
    • <video> tag support in fullscreen mode.
   
* Calendar
   - Agenda view가 무제한 scroll지원
   - 각 초대에 대해 이벤트 감지(?)
   - 이벤트에 새로운 게스트 초대

새로운 플랫폼 기술
* Media Framework
   - graphic 성능 개선
* Bluetooth
   - Bluetooth 2.1
   - New BT profiles : Object Push Profile(OPP) and Phone Book Access Profile(PBAP)

새로운 Framework API
API Level은 5이며 몇가지 새로운 API를 제공한다.

* Bluetooth
  - Turn on/off Bluetooth
  - Device와 Service 검색
  - Connect to a remote device usinng RFCOMM and send/receive data
  - Advertise RFCOMM services and listen for incoming RFCOMM connection
* Sync adapters
  - 임의 데이터의 싱크 지원 가능함.
* Account Manager
  - 보안고려한 통합된 Account manager API지원
* Contacts
  - multi account지원하는 새로운 Contacts API
  - 새로운 Quick Contact framework API제공
* WebView
  - UrlInterceptHandler, Plugin, PluginData, PluginList,UrlInterceptRegistry 제거
* Camera
  - 새로운 파라메터 제공 : color effect, scene mode, flash mode, focus mode, white balance, rotation, etc...
  - Zoom level 변경시 ZoomCallback interface제공
* Media
  - 모든 image는 MediaStore에 저장될 때 thumbnail생성
  - 새로운 Thumnail API제공하여 image와 video thumnail을 검색가능
* Other framework
  - 새로운 System theme제공(R.style) : 현재 system wallpaper상에 최상위에 activity를 표시하거나 이전 activity를 background에 보여지게 할 수 있슴.
  - WallpaperManager가 새롭게 교체됨 
  - 새로운 Service API : service가 수행중 메모리가 모자란 경우등에 대해서 Application에서  Service life-cycle을 정확하게 처리할 수 있는 API가 추가됨 -> Service.setForeground()는 사용되지 않으며 Service.startForeground()사용함.
  - MotionEvent가 multi-touch지원함. 동시에 3개까지 지원
  - KeyEvent가 새로운 dispatch API제공 : action-on-up, long-press, cancel key 메커니즘(viertual key)
  - WindowManager.LayoutParams에 새로운 상수 추가 : 화면에 보여지거나 스크린이 lock되어 있는 상태에서 표시될 때 wake-up시킬수 있는 상수 제공. AlarmClock같은 app에서 쉽게 구현 가능
  - 새로운 Intent API : device의 docking상태를 broadcast하고 Application에서 이때 임의 activity를 실행할 수 있다.

** Key-up 이벤트 
  - 2.0은 HOE, MENU, BACK, SEARCH키에 기반하여 동작하도록 설계되었다. 최적의 UX를 위해서 key-down보가 key-down, key-up 쌍으로 수행되도록 개선되었다. 이 로써 잘못된 버튼 이벤트를 방지할 수 있고 사용자가 버튼을 누른상태에서 아무 이벤트발생시키지 않으면서 drag out 할 수 있다.
  - 이 수정사항은 button 이벤트를 가로채서 key-down action을 얻어낼 때 유효하다. Application에서 BACK key를 가로채고 싶다면 App에서 key event 속성을 처리해야 한다.
  - 일반적으로 App에서 BACK key의 가로채기는 권장사항이 아니다. 하지만 그렇게 해야 하고 key-up보가 key-down이벤트를 처리해야 한다면 코드를 수정해야 한다.
  - Activity나 Dialog에서 BACK key를 가로채고 싶다면 onBackPressed()만 구현하면 된다.

  - If you are intercepting the BACK key in a view, you should track the key event on key-down (through the new startTracking() method), then invoke the action at key up. Here's a pattern you can use:

        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK
                    && event.getRepeatCount() == 0) {
                event.startTracking();
                return true;
            }
            return super.onKeyDown(keyCode, event);
        }
    
        public boolean onKeyUp(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                    && !event.isCanceled()) {
                // *** DO ACTION HERE ***
                return true;
            }
            return super.onKeyUp(keyCode, event);
        }

If you want to update a legacy application so that its handling of the BACK key works properly for both Android 2.0 and older platform versions, you can use an approach similar to that shown above. Your code can catch the target button event on key-down, set a flag to track the key event, and then also catch the event on key-up, executing the desired action if the tracking flag is set. You'll also want to watch for focus changes and clear the tracking flag when gaining/losing focus.


  

API differences report

For a detailed view of API changes in Android 2.0 (API Level 5), as compared to the previous version, see the API Differences Report.







Posted by 삼스
Android/App개발2009. 11. 6. 16:21

[Intro]

 

Android에서 사용하는 이미지는 Bitmap이라는 클래스에서 다~ 알아서 해줍니다.
그리고 이런 Bitmap Object를 쉽게 만들 수 있도록 도와주는 
BitmapFactory 클래스 라는 것도 있습니다.

 

BitmapFactory는 여러가지 소스로 부터 Bitmap Object를 만들어 주는 일을 하는데,
전부 static이며 decodeXXX 라는 이름을 가진 메소드들로 이루어져 있습니다.

XXX에는 어떤 것으로 부터 decode를 하여 
Bitmap Object를 만들어 낼지에 대한 말들이 들어 가겠죠.

 


[Decoding Methods]

 

BitmapFactory.decodeByteArray() 메소드는 Camera.PictureCallback 으로 부터 받은
Jpeg 사진 데이터를 가지고 Bitmap으로 만들어 줄 때 많이 사용 합니다.
Camera.PictureCallback에서 들어오는 데이터가 byte[] 형식이기 때문에
저 메소드를 사용 해야 하는 것이죠.

 

BitmapFactory.decodeFile() 메소드는 파일을 그대로 읽어 옵니다.
내부적으로는 파일 경로를 가지고 FileInputStream을 만들어서 decodeStream을 합니다.
그냥 파일 경로만 쓰면 다 해주는게 편리 한 것이죠.

 

BitmapFactory.decodeResource() 메소드는 Resource로 부터 Bitmap을 만들어 내며
BitmapFactory.decodeStream() 메소드는 InputStream으로 부터 Bitmap을 만들어 냅니다.
뭐 그냥 이름만 봐도 알 수 있는 것들이지요.

 


[OutOfMemoryError??]

 

보통 이미지 파일을 읽어서 Resizing을 해야 할 때가 있는데, 
그럴때는 BitmapFactory로 읽어서 Bitmap.createScaledBitmap() 메소드를 사용하여 줄이면

간단하게 처리 할 수 있습니다.

 

그런데 BitmapFactory를 사용할 때 주의해야 할 점이 있습니다.
아래의 예를 한번 보시죠.

Bitmap src = BitmapFactory.decodeFile("/sdcard/image.jpg");
Bitmap resized = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true);

이미지 파일로부터 Bitmap을 만든 다음에

다시 dstWidth, dstHeight 만큼 줄여서 resized 라는 Bitmap을 만들어 냈습니다.
보통이라면 저렇게 하는게 맞습니다.

 

읽어서, 줄인다.

 

그런데 만약 이미지 파일의 크기가 아주 크다면 어떻게 될까요?
지금 Dev Phone에서 카메라로 촬영하면
기본적으로 2048 x 1536 크기의 Jpeg 이미지가 촬영된 데이터로 넘어옵니다.
이것을 decode 하려면 3MB 정도의 메모리가 필요 할 텐데,

과연 어떤 모바일 디바이스에서 얼마나 처리 할 수 있을까요?

 

실제로 촬영된 Jpeg 이미지를 여러번 decoding 하다보면

아래와 같은 황당한 메세지를 발견 할 수 있습니다.

java.lang.OutOfMemoryError: bitmap size exceeds VM budget

네... OutOfMemory 입니다.
더 이상 무슨 말이 필요 하겠습니까...
메모리가 딸려서 처리를 제대로 못합니다.

 

이것이 실제로 decoding 후 메모리 해제가 제대로 되지 않아서 그런 것인지, 
하더라도 어디서 Leak이 발생 하는지에 대한 정확한 원인은 알 수 없습니다.
이것은 엔지니어들이 해결해야 할 문제 겠죠...

 

하지만 메모리 에러를 피할 수 있는 방법이 있습니다.

 


[BitmapFactory.Options.inSampleSize]

 

BitmapFactory.decodeXXX 시리즈는 똑같은 메소드가 두 개씩 오버로딩 되어 있습니다.
같은 이름이지만 Signature가 다른 메소드의 차이점은
BitmapFactory.Options를 파라메터로 받느냐 안받느냐의 차이죠.

BitmapFactory.Options를 사용하게 되면 decode 할 때 여러가지 옵션을 줄 수 있습니다.


여러가지 많지만 저희가 지금 사용할 것은 inSampleSize 옵션 입니다.

 

inSampleSize 옵션은,
애초에 decode를 할 때 얼마만큼 줄여서 decoding을 할 지 정하는 옵션 입니다.

 

inSampleSize 옵션은 1보다 작은 값일때는 무조건 1로 세팅이 되며,
1보다 큰 값, N일때는 1/N 만큼 이미지를 줄여서 decoding 하게 됩니다.
즉 inSampleSize가 4라면 1/4 만큼 이미지를 줄여서 decoding 해서 Bitmap으로 만들게 되는 것이죠.

 

2의 지수만큼 비례할 때 가장 빠르다고 합니다.
2, 4, 8, 16... 정도 되겠죠?

 

그래서 만약 내가 줄이고자 하는 이미지가 1/4보다는 작고 1/8보다는 클 때,
inSampleSize 옵션에 4를 주어서 decoding 한 다음에,

Bitmap.createScaledBitmap() 메소드를 사용하여 한번 더 줄이면 됩니다.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap src = BitmapFactory.decodeFile("/sdcard/image.jpg", options);
Bitmap resized = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true);

당연한 이야기 이겠지만,
내가 원하고자 하는 사이즈가 딱 1/4 크기라면

Bitmap.createScaledBitmap() 메소드를 쓸 필요가 없지요.

 

inSampleSize 옵션을 잘 활용하면 메모리 부족 현상을 대략적으로 해소 할 수 있습니다.
참고로 제가 저 옵션을 사용한 뒤로는 메모리 에러를 본적이 한~번도 없답니다.

 


[Appendix]

 

inSampleSize 옵션을 사용하면

SkScaledBitmapSampler Object (Library Level) 를 생성 하게 되는데,
Object를 만들때 정해진 SampleSize 만큼 축소하여 width와 height를 정한 뒤에 만들게 됩니다.
그러니까 애초에 축소된 사이즈로 이미지를 decoding 하는 것이죠.

 


[Outro]

 

Android의 기본 어플리케이션 소스를 분석 하다보면
상당히 테크니컬한 기법들을 많이 얻을 수 있습니다.
어떻게 이런 방법으로 만들었나 싶을 정도로 매우 정교하고 복잡하게 만들어져 있지요.
참 대단한 것 같습니다.

 

아 그리고 왜 dstWidth와 dstHeight 변수 선언이 없냐고 따지시는 분들 설마 없겠죠?


Posted by 삼스
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. 9. 7. 12:54
http://groups.google.com/group/android-ndk/browse_thread/thread/4bc383030ba0a13b/9a77365dd5741d16

Using SWIG in combination with the Android NDK
  메시지 5개 - 모두 접기
Maarten Wijnants  
프로필 보기  
 (1 사용자)  추가옵션 7월6일, 오후11시40분
Hi all, 

I have been experimenting with using native code on the Android 
platform for a few days now, and I am still facing a number of 
problems. 

Let's start with my successes so far. I have tested the sample 
applications included in the Android NDK, and they work perfectly. I 
have also already been able to write a small C library and invoke its 
methods on Android through the NDK build tools and the .mk build 
files. 

My goal however is to access the functionality of an (existing) C++ 
library on the Android platform. The library contains a number of 
classes and I would like to be able to use the library on Android as 
on other platforms (i.e. win32 and unix). Instead of completely 
converting the code to Java, I would like to use it as a native 
library and invoke its functionality through JNI. 

To the best of my knowledge, the most straightforward way to do so 
would be to use SWIG (the Simplified Wrapper and Interface Generator, 
http://www.swig.org/). Please correct me if I am wrong in this 
statement as I am far from an expert in the field of Java programming. 
Using SWIG allows programmers to work with the classes implemented in C 
++ libraries in other languages, including Java. I have tested this on 
win32 and it worked perfectly. 

On Android however, I have up till now not been able to achieve the 
same outcome. It appears to me the problem is that the implementation 
of the native methods cannot be located in the native library. I could 
however be wrong in this assessment. 

Here is my source code. First there is the "native" C++ class, which 
is implemented in files newtestclass.h and newtestclass.cpp as 
follows: 

newtestclass.h 
------------------- 

#ifndef NEWTESTCLASS_H 
#define NEWTESTCLASS_H 

class NewTestClass 

public: 
        NewTestClass(); 
        ~NewTestClass(); 

        void setX(const int x); 
        int getX() const; 
private: 
        int m_x; 

}; 

#endif // NEWTESTCLASS_H 

newtestclass.cpp 
---------------------- 

#include "newtestclass.h" 

NewTestClass::NewTestClass() : m_x(0) 



NewTestClass::~NewTestClass() 



void NewTestClass::setX(const int x) 

        m_x = x; 



int NewTestClass::getX() const 

        return m_x; 



As you can see this is pretty straightforward C++ code, to make sure 
the problems are not being caused by advanced C++ constructs. 

As instructed in the SWIG tutorial, I have written a SWIG interface 
file for this class. The contents is as follows: 

newtestclass.i 
------------------- 

%module newtestclassmodule 
%{ 
#include "newtestclass.h" 
%} 

%include "newtestclass.h" 

Again very simple. On this interface class, I invoke the swig tool as 
follows: 

swig -c++ -o newtestclass_wrap.cpp -package com.example.newtest -java 
newtestclass.i 

which generates the file newtestclass_wrap.cpp. If desired/needed, I 
can provide the contents of this file. Files newtestclass.cpp and 
newtestclass_wrap.cpp are added to the LOCAL_SRC_FILES variable of my 
Android.mk build file. Compiling the native library using the NDK make 
tool succeeds and generates the library libnewtest.so (as the name of 
my NDK module is "newtest"). 

Besides the newtestclass_wrap.cpp file, the swig tool also generates a 
number of .java files which contain the Java implementation of the 
NewTestClass class. As is expected, each memberfunction of this Java 
class simply invokes its corresponding native method. This 
implementation seems correct to me. 

Finally, I attempt to use the Java NewTestClass inside the onCreate 
method of an Android activity class as follows: 

public class RunMe extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 

        System.loadLibrary("newtest"); 

        NewTestClass ntc = new NewTestClass(); 

        TextView tv = new TextView(this); 
        tv.setText("Returned value = " + ntc.getX()); 
        setContentView(tv); 
    } 



I compile and run the Android activity class using the Eclipse ADT 
plug-in. When executing the Android application, LogCat output 
suggests the libnewtest.so library is loaded successfully. However I 
do get some warnings: 

D/dalvikvm( 2027): Trying to load lib /data/data/com.example.newtest/ 
lib/libnewtest.so 0x43597078 
D/dalvikvm( 2027): Added shared lib /data/data/com.example.newtest/lib/ 
libnewtest.so 0x43597078 
D/dalvikvm( 2027): No JNI_OnLoad found in /data/data/ 
com.example.newtest/lib/libnewtest.so 0x43597078 
D/dalvikvm( 2027): +++ not scanning '/system/lib/libwebcore.so' for 
'new_NewTestClass' (wrong CL) 
D/dalvikvm( 2027): +++ not scanning '/system/lib/libmedia_jni.so' for 
'new_NewTestClass' (wrong CL) 
D/dalvikvm( 2027): +++ not scanning '/system/lib/libwebcore.so' for 
'NewTestClass_getX' (wrong CL) 
D/dalvikvm( 2027): +++ not scanning '/system/lib/libmedia_jni.so' for 
'NewTestClass_getX' (wrong CL) 

As soon as the application tries to instantiate a NewTestClass object 
in the onCreate method, the application terminates and I get the 
following LogCat dump: 

I/DEBUG   (  539): *** *** *** *** *** *** *** *** *** *** *** *** *** 
*** *** *** 
I/DEBUG   (  539): Build fingerprint: 'generic/sdk/generic/:1.5/ 
CUPCAKE/148875:eng/test-keys' 
I/DEBUG   (  539): pid: 2027, tid: 2027  >>> com.example.newtest <<< 
I/DEBUG   (  539): signal 7 (SIGBUS), fault addr 00000000 
I/DEBUG   (  539):  r0 42382b49  r1 4359d428  r2 00000000  r3 00000000 
I/DEBUG   (  539):  r4 be9a4540  r5 00000004  r6 804005f0  r7 41049d10 
I/DEBUG   (  539):  r8 be9a451c  r9 41049d04  10 41049cf4  fp 00000000 
I/DEBUG   (  539):  ip 804005f0  sp be9a4508  lr 80400604  pc 
804005e8  cpsr 80000010 
I/DEBUG   (  539):          #00  pc 000005e8  /data/data/ 
com.example.newtest/lib/libnewtest.so 
I/DEBUG   (  539):          #01  pc 00000600  /data/data/ 
com.example.newtest/lib/libnewtest.so 
I/DEBUG   (  539):          #02  pc 0000e3b4  /system/lib/libdvm.so 
I/DEBUG   (  539): stack: 
I/DEBUG   (  539):     be9a44c8  000000da 
I/DEBUG   (  539):     be9a44cc  000001b8 
I/DEBUG   (  539):     be9a44d0  00003071 
I/DEBUG   (  539):     be9a44d4  afe0af93  /system/lib/libc.so 
I/DEBUG   (  539):     be9a44d8  804005f0  /data/data/ 
com.example.newtest/lib/libnewtest.so 
I/DEBUG   (  539):     be9a44dc  00000006 
I/DEBUG   (  539):     be9a44e0  afe3c980 
I/DEBUG   (  539):     be9a44e4  afe39dd0 
I/DEBUG   (  539):     be9a44e8  0000a000  [heap] 
I/DEBUG   (  539):     be9a44ec  00000088 
I/DEBUG   (  539):     be9a44f0  42382b49 
I/DEBUG   (  539):     be9a44f4  00000000 
I/DEBUG   (  539):     be9a44f8  0018cbe8  [heap] 
I/DEBUG   (  539):     be9a44fc  000e1940  [heap] 
I/DEBUG   (  539):     be9a4500  df002777 
I/DEBUG   (  539):     be9a4504  e3a070ad 
I/DEBUG   (  539): #01 be9a4508  00000000 
I/DEBUG   (  539):     be9a450c  00000000 
I/DEBUG   (  539):     be9a4510  00000002 
I/DEBUG   (  539):     be9a4514  ad00e3b8  /system/lib/libdvm.so 
I/ActivityManager(  570): Process com.example.newtest (pid 2027) has 
died. 
D/Zygote  (  541): Process 2027 terminated by signal (7) 

I hope my explanation has been sufficiently elaborate. Has anyone any 
experience on using SWIG on the Android platform and could point out 
what is wrong with my approach? 

Many thanks in advance, 
Maarten Wijnants 


    작성자에게 답글    전달  
Maarten Wijnants  
프로필 보기  
 추가옵션 7월9일, 오후8시42분
As I did not find any solution to this strange problem, I tried 
compiling the native library using the agcc build script (http:// 
plausible.org/andy/agcc). Surprisingly, now everything works as 
expected! In other words, I am able to use my native code in Java as I 
would in a C++ environment. 

Unfortunately however, I still have no clue as to why compilation 
using the Android NDK does not work. If anyone could shed some 
insight, that would be greatly appreciated!


    답글    작성자에게 답글    전달  
Sridhar M  
프로필 보기  
 추가 옵션 7월31일, 오후11시32분

Maarten, 

I have used the SWIG framework on Android and it works. 
From your logs it seems that JNI_OnLoad() is not implemented in your native 
library. Be sure to register all the native JNI methods using JNI_OnLoad() ( 
maybe in newtestclass_wrap.cpp ) 

Regards, 
Sridhar 

On Mon, Jul 6, 2009 at 8:10 PM, Maarten Wijnants <maarten.wijna...@gmail.com 

- 원본 텍스트 보기 -


    답글    작성자에게 답글    전달  
Maarten Wijnants  
프로필 보기  
 추가 옵션 8월26일, 오후9시01분
Hello Sridhar, 

Many thanks for your reply! I am sorry I did not respond sooner, I 
only just noticed someone replied on my question. 

On 31 jul, 16:32, Sridhar M <sridhar....@gmail.com> wrote: 

> Maarten, 

> I have used the SWIG framework on Android and it works. 
> From your logs it seems that JNI_OnLoad() is not implemented in your native 
> library. Be sure to register all the native JNI methods using JNI_OnLoad() ( 
> maybe in newtestclass_wrap.cpp ) 

Indeed I did not implement the JNI_OnLoad method. I saw LogCat 
printing a warning about this, but adding the method did not help me. 
Maybe I did something wrong in the JNI_OnLoad implementation, I'm not 
sure. Anyway, using the agcc build script, I was able to successfully 
get SWIG to work, WITHOUT the JNI_OnLoad method. So I am still not 
really sure whether native JNI method registering is absolutely 
necessary. 

> > Regards, 
> Sridhar 

Once more my gratitude for your reply! Maybe in the future I will 
again look into NDK native library building (instead of using the agcc 
build script). When so, I will definitely look into your suggestion of 
registering native methods in the JNI_OnLoad method. 

Greetz, 
Maarten


    답글    작성자에게 답글    전달  
Sridhar M  
프로필 보기  
 추가 옵션 9월3일, 오후9시30분

Hi Maarten, 

You are welcome! 
For me, the JNI interface started working only after adding JNI_OnLoad() 
Here is a good reference of how the function is written 
http://markmail.org/message/daqhat4un5xlbaze 

Hope it helps. 

Regards, 
Sridhar 

On Wed, Aug 26, 2009 at 5:31 PM, Maarten Wijnants < 

- 원본 텍스트 보기 -


    답글    작성자에게 답글    전달  
Posted by 삼스
Android/App개발2009. 8. 28. 14:49
// InputMethodService의 참조를 얻음.
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// SoftInput keyboard를 show함.
inputManager.showSoftInput(this.getCurrentFocus(),InputMethodManager.SHOW_IMPLICIT);

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. 8. 14. 14:24
adb shell에서 아래와 같이 입력.

mount -o rw,remount -t yaffs2 /dev/block/mtdblock0 /system
Posted by 삼스
Android/App개발2009. 8. 4. 14:43
=========================================
                 AlarmManager
=========================================

extends Object
java.lang.Object
  -> android.app.AlarmManager

Class Overview
  system alarm service에 대한 접근을 제공함. 이는 미래의 임의시점에 app의 스케쥴을 조정할수 있도록 해준다. 
알람이 발생하면 이전에 등록해둔 Intent가 system에 의해 broadcast된다. target app가 동작중이 아니라면 자동으로 시작해준다. 등록된 alarm은 device가 sleep일때도 유지된다. 하지만 기기가 꺼지고 재시작되면 사라진다.

  AlarmManager는 alarm receiver의 onReceive()가 수행중인 동안에는 CPU의 wake lock을 유지한다. 이는 당신이 broadcast가 처리완료되기 전에는 다시 sleep이 되지 않도록 해준다. onReceive()가 리턴되면 AlarmManager는 wakelock을 해재한다.  

  onReceive()에서 Context.startService()를 호출한다면 해당 service가 launch되기전에 sleep으로 빠질수 있다. 이런 경우를 막기 위해 BroadcastReceiver와 Service에서 서비스가 활성화되기 전에 sleep으로 넘어가지 않도록 각기 wake lock정책을 구현할 필요가 있다.

이 class는 직접 new하지 않고 아래와 같이 사용해야 한다.



---------------------
AlarmClock 예
---------------------
native application 중 AlarmClock의 예를 들어 자세히 설명하겠다.\

AlarmClock.java : main activity
AlarmProvider.java : Alarm등록, 수정 및 해제관련 DB access
AlarmReceiver.java : receive된 Alarm broadcast를 처리(AlarmAlert activity를 start)

...


=========================================
                 PowerManager
=========================================

device의 power state를 제어할수 있게 해준다. device 배터리사용시간은 이 API의 사용에 따라 영향을 받게 된다. 반드시 필요한 경우가 아니라면 Wakelock을 acquire하지 않는것이 좋다. 가능한 낮은 레벨을 사용하고 사용후에는 바로 release하는것이 좋다.

  Context.getSystemService(Context.POWER_SERVICE); 로 인스턴스를 얻을 수 있다.

아주 기초적인 API인 newWakeLock()를 사용할것이다. 이 API는 PowerManager.WakeLock객체를 만든다. device의 powerstate를 제어하기 위해 이 객체의 method를 사용하게 된다.

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
 wl.acquire();
   ..screen will stay on during this section..
 wl.release();
system전원에 영향을 미치는 flag가 아래와 같이 정의되어 있다.

Flag ValueCPUScreenKeyboard
PARTIAL_WAKE_LOCKOn* Off Off
SCREEN_DIM_WAKE_LOCKOn Dim Off
SCREEN_BRIGHT_WAKE_LOCKOn Bright Off
FULL_WAKE_LOCKOn Bright Bright
** partial wakelock을 유지하는 동안 CPU는 계속 run상태로 된다. 어떤 타이머타 사용자가 power button을 누르더라도 상태는 유지가 된다. 나머지 wakelock은 CPU가 run상태가 되지만 사용자가 power button을 눌러서 sleep으로 갈수 있다.

Screen에만 적용되는 2가지 flag가 더 있다. 이 플래그는 PARTIAL_WAKE_LOCK에는 영향을 안준다.

Flag ValueDescription
ACQUIRE_CAUSES_WAKEUPNormal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately.
ON_AFTER_RELEASEIf this flag is set, the user activity timer will be reset when the WakeLock is released, causing the illumination to remain on a bit longer. This can be used to reduce flicker if you are cycling between wake lock conditions.


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 삼스