검색결과 리스트
글
안드로이드 프레임워크 프로그래밍(4) [시스템서비스 추가하기]
안드로이드 시스템 서비스란 운영체제가 동작하는 동안 수행할 수 있도록 구성된 어플리케이션 구성요소로 메시지 표시와 같이 시스템의 기본적인 기능들을 제공한다. 이러한 기능들을 활용하여 안드로이드 기기에서 동작하는 서비스를 개발하기 위한 클래스의 집합을 프레임워크라 한다. 본 포스팅은 이러한 시스템서비스를 추가하여 프레임워크의 동작 원리를 이해하는 것을 목표로 한다.
다음은 서비스 레이어의 구조를 나타낸 것이다.
상단의 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 한다. 빌드 방법은 아래 블로그를 참조한다.
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에 다음과 같은 결과가 나타나는 것을 확인할 수 있다.
출저 : Android-Adding SystemService
http://processors.wiki.ti.com/index.php/Android-Adding_SystemService
'안드로이드 > 프레임워크' 카테고리의 다른 글
안드로이드 프레임워크 프로그래밍(6) [Wi-Fi 접속 확인 Toast 만들기] (0) | 2015.01.30 |
---|---|
안드로이드 프레임워크 프로그래밍(5) [Toast 구현하기] (0) | 2015.01.25 |
리눅스로 Nexus 기기의 안드로이드 버전 다운그레이드 하기 (0) | 2015.01.22 |
error: neither -p product specified nor ANDROID_PRODUCT_OUT set (0) | 2015.01.21 |
make: *** [out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes.jar] error 41 (0) | 2015.01.20 |