메뉴 건너뛰기

XEDITION

ANDROID

?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

안드로이드 시스템 서비스란 운영체제가 동작하는 동안 수행할 수 있도록 구성된 어플리케이션 구성요소로 메시지 표시와 같이 시스템의 기본적인 기능들을 제공한다. 이러한 기능들을 활용하여 안드로이드 기기에서 동작하는 서비스를 개발하기 위한 클래스의 집합을 프레임워크라 한다. 본 포스팅은 이러한 시스템서비스를 추가하여 프레임워크의 동작 원리를 이해하는 것을 목표로 한다.

 

 다음은 서비스 레이어의 구조를 나타낸 것이다.

 

 

 상단의 Application에서 시스템서비스를 호출하면 해당 기능을 System Server에서 실행한다. 이 때 각 프로세스 간의 통신이 이루어져야 하는데 이는 IPC 또는 RPC 방식으로 이루어진다. Application과 System Server 사이에 있는 AIDL은 Application이 System Server로부터 해당 기능을 실행하는 프로세스를 호출할 수 있는 Interface를 제공하는 역할을 한다.

 

다음은 예제를 다루어 보도록 한다.

 

1. 시스템 서비스를 추가한다. 아래의 코드를 다음 경로에 생성한다.

frameworks/base/services/java/com/android/server/TestService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*TestService.java */
package com.android.server;
import android.content.Context;
import android.os.Handler;
import android.os.ITestService;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
public class TestService extends ITestService.Stub {
    private static final String TAG = "TestService";
    private TestWorkerThread mWorker;
    private TestWorkerHandler mHandler;
    private Context mContext;
    public TestService(Context context) {
        super();
        mContext = context;
        mWorker = new TestWorkerThread("TestServiceWorker");
        mWorker.start();
        Log.i(TAG, "Spawned worker thread");
    }
 
    public void setValue(int val) {
        Log.i(TAG, "setValue " + val);
        Message msg = Message.obtain();
        msg.what = TestWorkerHandler.MESSAGE_SET;
        msg.arg1 = val;
        mHandler.sendMessage(msg);
    }
 
    private class TestWorkerThread extends Thread {
        public TestWorkerThread(String name) {
            super(name);
        }
        public void run() {
            Looper.prepare();
            mHandler = new TestWorkerHandler();
            Looper.loop();
        }
    }
 
    private class TestWorkerHandler extends Handler {
        private static final int MESSAGE_SET = 0;
        @Override
        public void handleMessage(Message msg) {
            try {
                if (msg.what == MESSAGE_SET) {
                    Log.i(TAG, "set message received: " + msg.arg1);
                }
            } catch (Exception e) {
                // Log, don't crash!
                Log.e(TAG, "Exception in TestWorkerHandler.handleMessage:", e);
            }
        }
    }
}
 
cs

 

2. 추가로 만든 서비스를 등록한다.

frameworks/base/services/java/com/android/server/SystemServer.java

아래 소스코드에서 굵게 표시된 부분을 소스에 추가해주면 되겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
......
 
    if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
        //Added code(363 line)
        try{
            Slog.i(TAG, "Test Service");
            ServiceManager.addService("Test"new TestService(context));
        } catch (Throwable e){
            Slog.e(TAG, "Failure starting TestService Service", e);
        }
 
            //if (!disableNonCoreServices) { // TODO: View depends on these; mock them?
            if (true) {
                try {
                    Slog.i(TAG, "Input Method Service");
                    imm = new InputMethodManagerService(context, wm);
                    ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
                } catch (Throwable e) {
                    reportWtf("starting Input Manager Service", e);
                }
 
                try {
                    Slog.i(TAG, "Accessibility Manager");
                    ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
                            new AccessibilityManagerService(context));
                } catch (Throwable e) {
                    reportWtf("starting Accessibility Manager", e);
                }
            }
        }
......
cs

3. aidl을 추가하여 애플리케이션에서 추가된 서비스에 접근할 수 있는 인터페이스를 만든다.

frameworks/base/core/java/android/os/ITestService.aidl

1
2
3
4
5
6
7
8
9
10
11
/*
* aidl file : frameworks/base/core/java/android/os/ITestService.aidl
* This file contains definitions of functions which are exposed by service
*/
package android.os;
interface ITestService {
/**
* {@hide}
*/
    void setValue(int val);
}
cs

4. 추가한 aidl 파일을 등록한다.

frameworks/base/Android.mk

1
2
3
4
5
6
7
8
/*
 * open frameworks/base/Android.mk and add following line
 */
......
core/java/android/os/IPowerManager.aidl \
core/java/android/os/ITestService.aidl \
core/java/android/os/IRemoteCallback.aidl \
......
cs

 

5. 변경사항을 적용하기 위해 소스코드를 Build 한다. 빌드 방법은 아래 블로그를 참조한다.

http://elecs.tistory.com/59

 

6. Build가 완료되면 새로 수정된 프레임워크 라이브러리를 추출한다. 라이브러리는 다음 경로에서 구할 수 있다.

out/target/common/obj/JAVA_LIBRARIES

자바 라이브러리들을 확인할 수 있다. 우리들이 새로 추가한 시스템 서비스는 framework_intermediate 폴더 내에 있다.

 

 

폴더 내에 classes.jar 파일이 있는데 이 안에 우리들이 만든 서비스가 들어있다. 이를 직접 확인해보면

 

class 파일이 내부에 있는 것을 확인할 수 있다. 이것이 안드로이드 기기 전원이 ON 상태인 동안 백그라운드에서 기기가 OFF될 때까지 계속 실행된다.

 

7. 이제 이를 활용한 애플리케이션을 제작해 보도록 하자. 새로운 프로젝트를 생성한 후 위에서 찾은 라이브러리를 추가한다.

Eclipse에서 Project -> Properties를 실행한다.

 

Java Build Path -> Libraries에 들어가면 현재 안드로이드 프로젝트 내에 있는 라이브러리들을 볼 수 있다. 위에서 확인하였던 라이브러리를 추가하기 위해 오른쪽 메뉴에 있는 "Add External JARs..."를 클릭한다.

 

 

해당 경로로 이동한 후 Classes.jar 파일을 선택한 후 확인 버튼을 누르면

 

 

위에서 보는 바와 같이 classes.jar이 추가된 것을 확인할 수 있다. OK버튼을 눌러 설정을 적용한다.

 

8. 이제 MainActivity.java에 추가된 서비스를 구동하는 기능을 넣어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.example.test;
 
import android.app.Activity;
import android.os.Bundle;
import android.os.ITestService;
import android.os.ServiceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.util.Log;
 
 
public class MainActivity extends Activity {
    private static final String DTAG = "HelloServer";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        ITestService om = ITestService.Stub.asInterface(ServiceManager.getService("Test"));
        try{
            Log.d(DTAG, "Going to call service");
            om.setValue(20);
            Log.d(DTAG, "Service called successfully");
        }catch(Exception e){
            Log.d(DTAG, "FAILED to call service");
            e.printStackTrace();
        }
        
    }
 
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
cs

 

9. 안드로이드 기기에 어플리케이션을 설치한 후 실행하면 LogCat에 다음과 같은 결과가 나타나는 것을 확인할 수 있다.

 

 
?

List of Articles
번호 제목 글쓴이 날짜 조회 수
64 [슈팅 게임 만들기] 11. 강좌가 늦어져 예제로 대신합니다 엘리후 2017.06.01 93
63 안드로이드 게임 만들기 SpriteAnimation 엘리후 2016.02.29 672
62 [안드로이드 어플 개발] 이동 애니메이션 (Translate Animation) 엘리후 2015.12.24 373
61 Multipart를 이용하여 파일+문자열 한꺼번에 전송하기 엘리후 2015.12.01 3140
60 How do I upload large files (10MB) in Android? 엘리후 2015.11.26 925
59 Upload Video from android to server? 엘리후 2015.11.26 266
58 안드로이드] Fragment 쉽게 사용하기 엘리후 2015.11.24 386
57 안드로이드(android) 다이얼로그(dialog) 종류별 구현 방법 엘리후 2015.11.11 431
56 ActionBar에 메뉴 넣기. 엘리후 2015.11.11 188
55 앱 통계를 내 사이트에서 수집하기 엘리후 2015.10.07 827
54 나인패치 (9patch) 이미지 만드는 방법 엘리후 2015.10.07 350
53 VOLLEY 라이브러리 엘리후 2015.10.02 539
52 안드로이드 나인패치 이미지 만들기 [나인패치 영역선택 및 수정] 엘리후 2015.09.25 879
51 안드로이드 Support Library Setup 엘리후 2015.09.25 444
50 안드로이드 Multipart 업로드 예제 엘리후 2015.09.23 8811
49 이클립스/Eclipse 메모리 Heap 영역 늘리기 엘리후 2015.09.13 263
48 [Android, Hybrid]openFileChooser 킷캣에서 동작하지 않는 문제( openFileChooser Kitkat bug ) 엘리후 2015.08.27 605
47 Android – WebView에서 input태그를 통한 파일 업로드하기 엘리후 2015.08.27 3627
46 WebView 컨트롤 엘리후 2015.08.27 445
45 안드로이드 동영상 파일 업로드 예제 엘리후 2015.08.25 1181
44 안드로이드 채팅 ui 만들기 관련 리스트뷰(ListView)의 layout_weight 옵션을 이용한 채팅 GUI 구현, 카카오 채팅 말풍선 엘리후 2015.08.21 27790
43 Android 간단한 로그인, 회원 가입 폼 만들기 for Mac (PHPMyAdmin 이용) 엘리후 2015.08.21 1962
» 안드로이드 프레임워크 프로그래밍 [시스템서비스 추가하기] 엘리후 2015.08.11 156
41 안드로이드에서 실행 시 발생하는 에러 엘리후 2015.08.10 164
40 안드로이드 ; 스크롤 뷰 엘리후 2015.08.09 1840
39 android Facebook SDK 3.0 로그인 및 포스팅 엘리후 2015.08.07 479
38 [android] 안드로이드 전역 변수 사용하기 android global variable 엘리후 2015.07.30 645
37 [Android] WebView를 사용할때 HttpClient를 이용한 Session 유지 엘리후 2015.07.29 5567
36 [MY_SQL] where절과 having절의 차이 엘리후 2015.07.27 246
35 [안드로이드 개발 강좌] 데이터베이스(DataBase) - DB 생성,저장,수정,삭제 엘리후 2015.07.21 939
Board Pagination Prev 1 2 3 Next
/ 3
위로