검색결과 리스트
글
안드로이드 프레임워크 프로그래밍(5) [Toast 구현하기]
지난 포스팅에서 새로 추가한 System service를 적용하여 Log를 통해 등록한 System service가 제대로 동작하는지에 대해 알아보았습니다. 이번에는 Framework 자체에서 Toast를 구현하는 작업을 해보도록 하겠습니다.
※본 포스팅은 지난 포스팅에서 사용하였던 예제를 수정하여 적용하였습니다. 그러므로 본 포스팅에서는 수정된 코드에 대해서만 다룰 것이며 상세한 코드는 이전 포스팅을 통해 확인해 주시기 바랍니다.
1. System service에 Toast 관련 소스를 입력합니다.
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 58 59 60 61 62 63 64 65 66 67 68 69 | 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; import android.widget.Toast; 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); } public void showToast(int val){ Log.i(TAG, "showToast " + val); Message msg = Message.obtain(); msg.what = 2; 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); } if (msg.what == 2){ Log.i(TAG, "Show toast!!"); Toast.makeText(mContext, "Toast message : "+msg.arg1, Toast.LENGTH_SHORT).show(); } } catch (Exception e) { // Log, don't crash! Log.e(TAG, "Exception in TestWorkerHandler.handleMessage:", e); } } } } | cs |
2. AIDL 또한 변경된 System service 프로그램에 맟게 method를 추가합니다.
frameworks/base/core/java/android/os/ITestService.aidl
1 2 3 4 5 6 7 8 | package android.os; interface ITestService { /** * {@hide} */ void setValue(int val); void showToast(int val); } | cs |
3. 여기까지 진행하셨다면 작성한 소스를 Build 해줍니다.
$ make -j4
4. 애플리케이션 프로젝트를 통해 Framework에서 Toast를 구현하는 프로그램을 작성합니다.
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 | package com.example.test; import android.app.Activity; import android.app.ActivityThread; import android.os.Bundle; import android.os.ITestService; import android.os.ServiceManager; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; 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); om.showToast(30); 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 |
이제 어플리케이션을 실행하면 다음과 같은 결과를 확인하실 수 있습니다.
'안드로이드 > 프레임워크' 카테고리의 다른 글
안드로이드 프레임워크 프로그래밍(7) [NDK 활용을 위한 JNI로 JAVA와 C 상호 호출] (0) | 2015.02.06 |
---|---|
안드로이드 프레임워크 프로그래밍(6) [Wi-Fi 접속 확인 Toast 만들기] (0) | 2015.01.30 |
안드로이드 프레임워크 프로그래밍(4) [시스템서비스 추가하기] (12) | 2015.01.24 |
리눅스로 Nexus 기기의 안드로이드 버전 다운그레이드 하기 (0) | 2015.01.22 |
error: neither -p product specified nor ANDROID_PRODUCT_OUT set (0) | 2015.01.21 |
설정
트랙백
댓글
글
안드로이드 프레임워크 프로그래밍(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 |
설정
트랙백
댓글
글
리눅스로 Nexus 기기의 안드로이드 버전 다운그레이드 하기
안드로이드 프레임워크에 대해 공부하게 되면서 안드로이드의 다양한 버전들을 기기에 설치하면서 동작시켜보는 일을 하고 있습니다. 지금 시점에서 가장 최신 버전인 Lollipop까지 실행을 해보면서 말이지요.
물론 Lollipop를 사용한 프레임워크 작업도 참으로 할 만 하다고 생각합니다만 그래도 아직은 최신버전이다 보니 구글링을 해서 구할 수 있는 정보가 한정되어 있다 보니 바로 이전 버전인 Kitkat을 사용해서 작업을 해보기로 하였습니다. 그런데 여기서 문제가 발생하고 말았습니다.
보시는 바와 같이 Lollipop에서 하위 버전인 Kitkat을 새로 설치해서 실행해보니 이렇게 로딩 화면만 주구장창 뜨기만 하고 다음 다음 화면으로 넘어갈 생각조차 하고 있지 않는 겁니다. 혹시나 해서 다시 이미지를 씌어서 입력해도 전혀 작동이 되지 않더군요. 이거 휴대폰 하나 날려먹는거 아닌가 하고 걱정했는데 다행히도 방법을 알아낼 수 있었습니다.
그렇다면 이제 안드로이드 버전의 다운그레이드 방법에 대해 살펴보도록 하겠습니다.
1. fastboot를 이용해 자신이 설치하고자 하는 버전의 이전 버전을 휴대폰에 설치합니다.
이 과정은 이전에 작성한 포스팅을 참고해 주시기 바랍니다.
위 링크에서 "fastboot flashall" 까지 진행하신 후 돌아오시면 되겠습니다.
2. fastboot 모드에서 Recovery Mode로 진입합니다.
fastboot 모드에 진입하신 후 휴대폰으 음량 버튼을 조작하시면 모드를 선택하실 수 있습니다.
자신이 원하는 모드를 선택하신 후 전원 버튼을 눌러 Recovery mode에 진입합니다.
처음 진입하시면 다음과 같이 안드로이드가 배째고 있는 모습 위에 느낌표가 써진 붉은 삼각형만 덩그러니 보이실 겁니다. 여기서 당황하지 마시고 바로 음량 Up 버튼을 누르시면
보시는 바와 같이 설정 메뉴들이 나타납니다.
여기서 볼륨 Down 버튼을 눌러 "wipe data/factory reset"를 선택한 후 전원 버튼을 누릅니다.
이제 기기가 스스로 공장 초기화에 들어간 후 리셋되는데 다시 다운그레이드된 버전이 정상적으로 동작하는 것을 확인하실 수 있을 겁니다.
'안드로이드 > 프레임워크' 카테고리의 다른 글
안드로이드 프레임워크 프로그래밍(5) [Toast 구현하기] (0) | 2015.01.25 |
---|---|
안드로이드 프레임워크 프로그래밍(4) [시스템서비스 추가하기] (12) | 2015.01.24 |
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 |
make: *** [out/target/common/obj/PACKAGING/checkapi-last-timestamp] error 38 (0) | 2015.01.18 |