我们在Android 系统增加硬件服务的目的是为了让应用层的APP 能够通过Java接口来访问硬件服务。那么, APP 如何通过Java
接口来访问ApplicationFrameworks 层提供的硬件服务呢?在这一篇文章中,我们将在Android 系统的应用层增加一个内置的
应用程序,这个内置的应用程序通过ServiceManager接口获取指定的服务,然后通过这个服务来获得硬件服务。
一. 参照在Ubuntu 上为Android系统的Application Frameworks 层增加硬件访问服务
一文,在ApplicationFrameworks 层定义好自己的硬件服务HelloService,并提供IHelloService 接口提供访问服务。
二. 为了方便开发,我们可以在IDE 环境下使用Android SDK 来开发Android应用程序。开发完成后,再把程序源代码移植到
Android 源代码工程目录中。使用Eclipse 的Android插件ADT 创建Android工程很方便,这里不述,可以参考网上其它资料。
工程名称为Hello,下面主例出主要文件:
主程序是src/shy/luo/hello/Hello.java:
1.packageshy.luo.hello;
2.
3.importshy.luo.hello.R;
4.import Android.app.Activity;
5.importAndroid.os.ServiceManager;
6.importAndroid.os.Bundle;
7.importAndroid.os.IHelloService;
8.importAndroid.os.RemoteException;
9.importAndroid.util.Log;
10.importAndroid.view.View;
11.importAndroid.view.View.OnClickListener;
12.import Android.widget.Button;
13.importAndroid.widget.EditText;
14.
15.public class Helloextends Activity implements OnClickListener {
16. private finalstatic String LOG_TAG = "shy.luo.renju.Hello";
17.
18. privateIHelloService helloService = null;
19.
20. private EditTextvalueText = null;
21. private ButtonreadButton = null;
22. private ButtonwriteButton = null;
23. private ButtonclearButton = null;
24.
25. /** Called whenthe activity is first created. */
26. @Override
27. public voidonCreate(Bundle savedInstanceState) {
28.super.onCreate(savedInstanceState);
29.setContentView(R.layout.main);
30.
31. helloService =IHelloService.Stub.asInterface(
32.ServiceManager.getService("hello"));
33.
34. valueText =(EditText)findViewById(R.id.edit_value);
35. readButton =(Button)findViewById(R.id.button_read);
36. writeButton =(Button)findViewById(R.id.button_write);
37. clearButton =(Button)findViewById(R.id.button_clear);
38.
39.readButton.setOnClickListener(this);
40.writeButton.setOnClickListener(this);
41.clearButton.setOnClickListener(this);
42.
43. Log.i(LOG_TAG,"Hello Activity Created");
44. }
45.
46. @Override
47. public voidonClick(View v) {
48.if(v.equals(readButton)) {
49. try {
50. int val =helloService.getVal();
51. String text =String.valueOf(val);
52.valueText.setText(text);
53. } catch(RemoteException e) {
54. Log.e(LOG_TAG,"Remote Exception while reading value from device.");
55. }
56. }
57. elseif(v.equals(writeButton)) {
58. try {
59. String text =valueText.getText().toString();
60. int val =Integer.parseInt(text);
61.helloService.setVal(val);
62. } catch(RemoteException e) {
63. Log.e(LOG_TAG,"Remote Exception while writing value to device.");
64. }
65. }
66. elseif(v.equals(clearButton)) {
67. String text ="";
68. valueText.setText(text);
69. }
70. }
71.}
程序通过ServiceManager.getService("hello")来获得HelloService,接着通过IHelloService.Stub.asInterface 函数转换为IHelloService
接口。其中,服务名字“hello”是系统启动时加载HelloService 时指定的,而IHelloService 接口定义在Android.os.IHelloService
中,具体可以参考在Ubuntu 上为Android 系统的ApplicationFrameworks 层增加硬件访问服务一文。这个程序提供了简单的读
定自定义硬件有寄存器val 的值的功能,通过IHelloService.getVal 和IHelloService.setVal 两个接口实现。
界面布局文件res/layout/main.xml:
1.<?xmlversion="1.0" encoding="utf-8"?>
2. <LinearLayoutxmlns:Android="http://schemas.android.com/apk/res/android"
3.Android:orientation="vertical"
4.Android:layout_width="fill_parent"
5.Android:layout_height="fill_parent">
6. <LinearLayout
7.Android:layout_width="fill_parent"
8.Android:layout_height="wrap_content"
9.Android:orientation="vertical"
10.Android:gravity="center">
11. <TextView
12.Android:layout_width="wrap_content"
13.Android:layout_height="wrap_content"
14.Android:text="@string/value">
15. </TextView>
16. <EditText
17.Android:layout_width="fill_parent"
18.Android:layout_height="wrap_content"
19.Android:id="@+id/edit_value"
20.Android:hint="@string/hint">
21. </EditText>
22.</LinearLayout>
23. <LinearLayout
24.Android:layout_width="fill_parent"
25.Android:layout_height="wrap_content"
26.Android:orientation="horizontal"
27. Android:gravity="center">
28. <Button
29.Android:id="@+id/button_read"
30.Android:layout_width="wrap_content"
31.Android:layout_height="wrap_content"
32.Android:text="@string/read">
33. </Button>
34. <Button
35.Android:id="@+id/button_write"
36. Android:layout_width="wrap_content"
37.Android:layout_height="wrap_content"
38.Android:text="@string/write">
39. </Button>
40. <Button
41.Android:id="@+id/button_clear"
42.Android:layout_width="wrap_content"
43.Android:layout_height="wrap_content"
44. Android:text="@string/clear">
45. </Button>
46.</LinearLayout>
47.</LinearLayout> 字符串文件res/values/strings.xml:
1.<?xmlversion="1.0" encoding="utf-8"?>
2. <resources>
3. <stringname="app_name">Hello</string>
4. <stringname="value">Value</string>
5. <string name="hint">Pleaseinput a value...</string>
6. <stringname="read">Read</string>
7. <stringname="write">Write</string>
8. <stringname="clear">Clear</string>
9. </resources> 程序描述文件AndroidManifest.xml:
1.<?xmlversion="1.0" encoding="utf-8"?>
2. <manifest xmlns:Android="http://schemas.android.com/apk/res/android"
3.package="shy.luo.hello"
4.Android:versionCode="1"
5.Android:versionName="1.0">
6. <applicationAndroid:icon="@drawable/icon"android:label="@string/app_name">
7. <activityAndroid:name=".Hello"
8.Android:label="@string/app_name">
9.<intent-filter>
10. <actionAndroid:name="android.intent.action.MAIN" />
11. <categoryAndroid:name="android.intent.category.LAUNCHER" />
12.</intent-filter>
13. </activity>
14.</application>
15. <uses-sdk
16. Android:minSdkVersion="7"
17.Android:targetSdkVersion="7">
18. </uses-sdk>
19. </manifest>
三. 将Hello 目录拷贝至packages/experimental 目录,新增Android.mk 文件:
linuxidc@www.linuxidc.com:~/Android/packages/experimental$vi Android.mkAndroid.mk 的文件内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS :=optional
LOCAL_SRC_FILES :=$(call all-subdir-java-files)
LOCAL_PACKAGE_NAME :=Hello
include$(BUILD_PACKAGE)
四. 编译:
linuxidc@www.linuxidc.com:~/Android$mmm packages/experimental/Hello
编译成功后,便可以在out/target/product/generic/system/app目录下看到Hello.apk 文件了。
五. 重新打包系统镜像文件system.img:
linuxidc@www.linuxidc.com:~/Android$make snod
重新打包后的system.img文件就内置了Hello.apk 文件了。
六. 运行Android 模拟器:
linuxidc@www.linuxidc.com:~/Android$emulator -kernel kernel/common/arch/arm/boot/zImage &
在HomeScreen 中可以看到Hello 应用程序:
打开Hello 应用程序:
点击Read 按钮,可以从HelloService 中读取硬件寄存器val 的值;点击Clear 按钮,可以清空文本框的值;在文本框中输入一
个数值,再点击Write 按钮,便可以将这个值写入到硬件寄存器val 中去,可以再次点击Read 按钮来验证是否正确写入了值。
至此,我们就完整地学习了在Android的Linux 内核空间添加硬件驱动程序、在Android 的硬件抽象层添加硬件接口、在Android
的ApplicationFrameworks 层提供硬件服务以及在Android 的应用层调用硬件服务的整个过程了,希望能为读者进入Android
系统提供入门帮助。重新学习整个过程,请参考Android 硬件抽象层(HAL)概要介绍和学习计划。
本篇文章来源于Linux 公社网站,原文链接:http://www.linuxidc.com/Linux/2011-07/38980.htm__