관심거리/Android

AIDL tags

2014. 9. 26. 20:17

@AIDL

oneway

: The keyword means that if that call results in an IPC (i.e. the caller and callee are in different processes) then the calling process will not wait for the called process to handle the IPC.

Client Callback 처리 결과를 기다리지 않겠다는 하나의 callee callback 처리시 오랜 시간을 잡고 있어도 문제가 없다.

Interface IServiceCallback {

oneway void onCallback(…)

 

in

: tag specifies an input-only parameter


out

: tag specifies an output-only parameter

 

inout
: on both in/output

 

'관심거리 > Android' 카테고리의 다른 글

String 표기 팁..  (0) 2014.09.12
Android resource??  (0) 2014.09.06
Google Navigation 실행  (0) 2012.08.21

String 표기 팁..

2014. 9. 12. 16:14

요건 몰랐던 건데..신기해서 일단 킵


@strings.xml

 <resources>

<string name="test">start %3$s, %2$s, %1$s end</string>

</resources>

 

@code

String text = getResources().getString(R.string.test);

String newText = String.format(text, "333", "222", "111");

 

@result

newText = start 111,222,333 end

 

%순서$s : 순서에 해당하는 값으로 출력

'관심거리 > Android' 카테고리의 다른 글

AIDL tags  (0) 2014.09.26
Android resource??  (0) 2014.09.06
Google Navigation 실행  (0) 2012.08.21

Android resource??

2014. 9. 6. 18:45

Android에서의 Resource file 관리

 

1.    res/raw

R.raw.id 형태로 접근 가능

res/raw/ 하위 폴더 임의 생성 불가

e.g) getResources().openRawResource(R.raw.id)

 

2.    asset

R.java에 추가되지 않기 때문에 R class member를 통한 접근 불가

/asset을 상위폴더로 두고, 하위 폴더들도 임의로 생성 가능

Assetmanager를 통해서 list를 받아와서 일반 파일 I/O로 접근

e.g.)

AssetManager asset = appContext.getResources().getAssets();

is = asset.open(“file name in asset”);

byte[] buffer = new byte[1024];

int byteRead = 0;

while ((byteRead = is.read(buffer)) != -1) {

    fo.write(buffer, 0, byteRead); 

}

.....

'관심거리 > Android' 카테고리의 다른 글

String 표기 팁..  (0) 2014.09.12
Google Navigation 실행  (0) 2012.08.21
UI는 UI Thread에게.  (1) 2012.08.20

Google Navigation 실행

2012. 8. 21. 14:21

Google Navigation control 하기 위한 방법은 다음과 같다.

Intent navigation = new Intent(Intent.ACTION_VIEW, 

Uri.parse(“http://maps.google.com/maps?saddr=42.35892,-71.05781&daddr=40.756054,-73.986951”));

startActivity(navigation);


saddr = latitude and longitude of starting point.

daddr = latitude and longitude of destination point.



아래와 같이 직접 주소를 입력해도 되고,

Intent intent = new Intent(android.content.Intent.ACTION_VIEW, 
      Uri.parse("google.navigation:q=an+1600 Amphitheatre Parkway Mountain View+CA"));
startActivity(intent);

Intent filter에 의해 Map 기능 있는 다른 App choose dialog box가 나온다면 요녀석으로 해결..

intent.setClassName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity");


'관심거리 > Android' 카테고리의 다른 글

Android resource??  (0) 2014.09.06
UI는 UI Thread에게.  (1) 2012.08.20
startManagingCursor()  (2) 2012.02.26

UI는 UI Thread에게.

2012. 8. 20. 22:27

Only the original thread that created a view hierarchy can touch its views.

다른 Thread에서 UI에 access 하려고 하면 위와 같은 에러가 발생한다.

다시 말해 UI Thread에서 UI를 처리하란 소리인데

그 해결책은 여러가지가 있을 수 있겠지만... 

아래의 간단한 방법을 메모한다.


당연하겠지만, 아래 handler는 UI Thread에서 생성이 되어여 UI Thread에 bounding되어 작업할 수 있다.

    // Define the Handler that receives messages from the thread

    final Handler handler = new Handler() {

        public void handleMessage(Message msg) {

            Bundle data = msg.getData();

            String result = data.getString("data");

            tw.setText(result);

        }

    };


아래 함수가 다른 Thread에 의해 호출된 함수이다. 

여기에서 UI Thread에서 작업할 수 있도록 handler를 통해 Message를 보내야 한다.

    public void onChanged(Object data) {

        // TODO Auto-generated method stub

        Bundle b = new Bundle();

        b.putString("data", (String)data);

        Message msg = handler.obtainMessage();

        msg.setData(b);

        handler.sendMessage(msg);

    }

    


'관심거리 > Android' 카테고리의 다른 글

Google Navigation 실행  (0) 2012.08.21
startManagingCursor()  (2) 2012.02.26
아는만큼만 말할 수 있다  (0) 2012.02.26

startManagingCursor()

2012. 2. 26. 19:28
아는만큼만 말할 수 있다. 2탄이다.
Android에서는 Cursor 사용을 잘해야한다.
Cursor는 query 결과물을 담고 있는 녀석으로 필요할 때마다 그 결과값을 손쉽게 가져올 수 있는 유용한 객체이다.

메모리를 사용했으면 해제해주는 것이 당연하듯,
Cursor 역시 사용후에는 꼭 close를 해줘야 한다. 그게 안되면 cursor가 담고 있는 데이터만큼 memory leak이 발생하게 된다.
지난번 규모있는 프로젝트 진행 중 빈번하게 memory leak이 발생했고 그 원인이 Cursor를 제대로 닫아주지 않아서 발생한 것이었다.

막바지에 이런 이슈가 나오게 되면 close되지 않은 cursor를 일일이 찾아내어 수정하기도 어렵다.
이 때 하나의 해결책이 될 수 있는 것이 startManagingCursor (cursor) 의 사용이다.
Activity life cycle에 따라 Framework단에서 release시켜주기 때문에 App단에서 close를 못 시킨 녀석이 있더라도 해제가 될 수 있다.

하지만 이 녀석도 문제는 있었다.
일단 ICS부터는 deprecated API 가 되었으니 사용을 안하는 것이 맞고 새롭게 제공되는 CursorLoader class를 이용해야 한다.

public void startManagingCursor (Cursor c)

Since: API Level 1

This method is deprecated.
Use the new CursorLoader class with LoaderManager instead; this is also available on older platforms through the Android compatibility package.

This method allows the activity to take care of managing the given Cursor's lifecycle for you based on the activity's lifecycle. That is, when the activity is stopped it will automatically call deactivate() on the given Cursor, and when it is later restarted it will call requery() for you. When the activity is destroyed, all managed Cursors will be closed automatically. If you are targeting HONEYCOMB or later, consider instead using LoaderManager instead, available viagetLoaderManager().

Warning: Do not call close() on cursor obtained from managedQuery(Uri, String[], String, String[], String), because the activity will do that for you at the appropriate time. However, if you call stopManagingCursor(Cursor)on a cursor from a managed query, the system will not automatically close the cursor and, in that case, you must call close().

Parameters
c The Cursor to be managed.


이번에 내가 힘들게 삽질을 한 경우를 정리해보자면

Provider와 해당 Provider를 사용하는 Activity가 한 Process에서 돌때는 이상없던 코드가
Provider를 다른 Process로 분리하고 나서 부터
android.database.StaleDataException: Attempted to access a cursor after it has been closed.를 던지는 것으로 시작되었다.

이미 닫힌 cursor에 또 access했다 머 이런 의미인 것 같은데

결론부터 말하자면 startManagingCursor의 사용때문이었다.

Provider가 다른 Process에서 돌고 있는 경우에 remote access를 해야하기 때문에
ContentProviderNative.ContentProviderProxy 를 통해서 query등을 진행하게 되고

그 결과값을 local process에서 사용할 수 있도록 BulkCursorToCursorAdaptor로 wrapping 후에 cursor값을 돌려준다.
여기까지는 전혀 문제가 없는데
Activity가 onResume될때 ManagingCursor의 경우 Activity의 life cycle에 따라서 자동으로 requery가 진행된다.
그런데 이때 Cursor가 이미 close된 경우에 문제가 발생한 다.

requery() 를 살펴보면, BulkCursor를 사용하는 Remote Provider인 경우에는 아래 함수를 통해서 StaleDataExcetpion을 던져버리고
    public boolean requery() {
        throwIfCursorIsClosed();

    private void throwIfCursorIsClosed() {
        if (mBulkCursor == null) {
            throw new StaleDataException("Attempted to access a cursor after it has been closed.");
        }
    }

기존 SQLiteCursor의 경우에는 이미 close인 경우라면 false를 return하도록 되어 있다.

    public boolean requery() {
        if (isClosed()) {
            return false;
        }


App단에서 할 수 있는 일은 startManagingCursor를 통하여 Activity Manager에 Cursor관리를 위임하지 않는 것이다.
자기가 만들었으면 자기가 닫아주는 게 제일 속 편하다는 것을 이번 삽질을 통해 알수 있었다. ㅡㅜ

'관심거리 > Android' 카테고리의 다른 글

UI는 UI Thread에게.  (1) 2012.08.20
아는만큼만 말할 수 있다  (0) 2012.02.26
android - Resource string읽어오기  (1) 2011.11.29
전산쟁이들은 끊임없이 공부를 해야한다. 
일한 경력만큼 실력이 쌓이는, 그래서 연차가 많은 사람들의 노하우를 따라 잡을 수 없는 타직종과 달리 
전산쟁이들은 경력에 의해 늘어나는 내공과 더불어 신기술을 계속 익히고 습득해야 살아 남을 수 있다.

최근에 타팀과의 협업을 위한 회의가 있었다.
양쪽 다 안드로이드의 깊은 곳까지는 모르는 상태에서 회의를 진행하다보니
한 안건에 대해 목소리 큰 사람이 진리인냥 되어버렸다.
내심 찜찜하면서도 뭐라고 반박할 밑천이 없다보니 좀 더 검토합시다라는 지키지 못할 약속을 남긴채 끝을 냈다.

하나의 Process에서 돌고 있는 Service와 UI를 두 개의 process로 분리합시다 라는 안건에
Video sharing같이 초당 수십 frame을 전송해야 하는 경우, process를 분리해서 그 대용량 데이터를 어떻게 전달할 것인가?
안돼! 였다.


물론 해결책은 있었다.
Ashmem (Anonymous shared memory)
간략한 설명은 다음과 같다.
다른 Process간 메모리 공유를 위함이고
해당 공유메모리를 access 하고 있는 process를 counting하고 있기 때문에, reference count가 valid하다면 memory를 해제하지 않으며,
A process에서 memory create 한 후 return 되는 file description을 remote process에서 넘겨주고
전달받은 B process에서는 fd를 이용하여 해당 memory에 접근할 수 있는 원리로 동작한다.
참고 reference.
http://www.androidenea.com/2010/03/share-memory-using-ashmem-and-binder-in.html 

Android API중 MemoryFile이 Ashmem에 대한 wrapper function을 제공하는 것으로 보이나
소스를 살펴보면, A로부터 전달받은 File description을 이용하여 MemoryFile을 생성하는 생성자와
생성한 Ashmem의 Fd를 받아올 수 있는 getFileDescription함수가 hidden 처리 되어 있기 때문에 실제 동작 여부는 확인이 필요하다.
http://developer.android.com/reference/android/os/MemoryFile.html 

'관심거리 > Android' 카테고리의 다른 글

startManagingCursor()  (2) 2012.02.26
android - Resource string읽어오기  (1) 2011.11.29
CodePro AnalytiX 사용법  (0) 2011.10.19
@strings.xml
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     
<string name="string_id">This is a sample test</string>

@R.java
    public static final class string {
        public static final int string_id=0x7f050007;



"This is a smaple test" 라는 string을 resource로부 읽어오기 위해서는 아래와 같은 코드가 가능하다.

1.

getString(string_id), or
getResource().getString(string_id);

2.
Context
context = this;
context.getString(string_id);

위 두 경우의 차이점은 바로 요 것.

You might need to do like 2 if your code is not in an activity.

Activity가 아닌 class의 경우는 전달받은 context를 이용해서 resource에 접근해야 함.

import android.content.Context 만 했다고
getString을 그냥 사용하게 되면 cannot find symbol error를 만나게 된다.





'관심거리 > Android' 카테고리의 다른 글

startManagingCursor()  (2) 2012.02.26
아는만큼만 말할 수 있다  (0) 2012.02.26
CodePro AnalytiX 사용법  (0) 2011.10.19

CodePro AnalytiX 사용법

2011. 10. 19. 19:20

자바 코드 분석툴이 기가막힌게 있네.
업무용 안드로이드 소스에 적용을 해보니, 미처 찾지 못한 그리고 prevent도 걸러내지 못한 워닝을 잡아준다.
게다가 공짜다.. +_+
이클립스에 플러그인 형태로 제공하기에 설치 및 사용도 너무 편하다.

CodePro AnalytiX

(다운은 여기서)
http://code.google.com/javadevtools/codepro/doc/installation/updatesite_3.5.html#addnew



설치 방법은...


1.
Help > Install New Software...



2. download 주소를 입력하고 CodePro 를 체크하고 Next로 설치


3. 코드 리뷰는 다음과 같이...
 

위 메뉴를 하나씩 클릭해보면 오~~ 이런것 까지 라는 경험을 할 수 있다.
정말 좋은 툴...

'관심거리 > Android' 카테고리의 다른 글

startManagingCursor()  (2) 2012.02.26
아는만큼만 말할 수 있다  (0) 2012.02.26
android - Resource string읽어오기  (1) 2011.11.29

+ Recent posts