💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
在Android应用程序框架层开发硬件访问服务的目的是为了让上层的Android应用程序能够访问对应的硬件设备。在本节中,我们将在Android源代码工程环境中开发一个应用程序Freg,它通过硬件访问服务FregService来访问虚拟硬件设备freg的寄存器val的值。 由于这个应用程序是实验性质的,因此,我们将它放在packages/experimental目录中,对应的工程为Freg。它的目录结构如下: ~~~ ~/Android/packages/experimental/Freg ----AndroidManifest.xml ----Android.mk ----src ----shy/luo/freg ----Freg.java ----res ----layout ----main.xml ----values ----strings.xml ----drawable ----icon.png ~~~ 它包含一个源代码目录src、一个资源目录res、一个配置文件AndroidManifest.xml和一个编译脚本文件Android.mk。下面我们就分别介绍每一个文件的内容。 **Freg.java** ~~~ package shy.luo.freg; import android.app.Activity; import android.os.ServiceManager; import android.os.Bundle; import android.os.IFregService; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class Freg extends Activity implements OnClickListener { private final static String LOG_TAG = "shy.luo.freg.FregActivity"; private IFregService fregService = null; private EditText valueText = null; private Button readButton = null; private Button writeButton = null; private Button clearButton = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); fregService = IFregService.Stub.asInterface( ServiceManager.getService("freg")); valueText = (EditText)findViewById(R.id.edit_value); readButton = (Button)findViewById(R.id.button_read); writeButton = (Button)findViewById(R.id.button_write); clearButton = (Button)findViewById(R.id.button_clear); readButton.setOnClickListener(this); writeButton.setOnClickListener(this); clearButton.setOnClickListener(this); Log.i(LOG_TAG, "Freg Activity Created"); } @Override public void onClick(View v) { if(v.equals(readButton)) { try { int val = fregService.getVal(); String text = String.valueOf(val); valueText.setText(text); } catch (RemoteException e) { Log.e(LOG_TAG, "Remote Exception while reading value from freg service."); } } else if(v.equals(writeButton)) { try { String text = valueText.getText().toString(); int val = Integer.parseInt(text); fregService.setVal(val); } catch (RemoteException e) { Log.e(LOG_TAG, "Remote Exception while writing value to freg service."); } } else if(v.equals(clearButton)) { String text = ""; valueText.setText(text); } } } ~~~ 文件定义了一个Activity组件Freg,它是应用程序Freg的主界面。在Activity组件Freg的界面上,有一个编辑框和三个按钮Read、Write和Clear,其中,编辑框用来显示或者输入虚拟硬件设备freg的寄存器val的值;按钮Read和Write分别用来读写虚拟硬件设备freg的寄存器val,而按钮Clear用来清空编辑框。 在Activity组件Freg的成员函数onCreate中,第30行通过Service Manager获得一个名称为“freg”的服务的Binder代理对象接口。从2.4.4小节的内容可以知道,这个服务就对应于运行在系统进程System中的硬件访问服务FregService。因此,第29行就可以安全地将这个Binder代理对象接口转换为一个FregService代理对象接口,并且保存在Activity组件Freg的成员变量fregService中。有了这个FregService代理对象接口之后,应用程序Freg就可以通过调用它的成员函数setVal和getVal来访问虚拟硬件设备freg的寄存器val的值了,如Activity组件Freg的成员函数onClick所示。 **main.xml** ~~~ <!--?xml version="1.0" encoding="utf-8"?--> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <linearlayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/value"> </textview> <edittext android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/edit_value" android:hint="@string/hint"> </edittext> </linearlayout> <linearlayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <button android:id="@+id/button_read" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/read"> </button> <button android:id="@+id/button_write" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/write"> </button> <button android:id="@+id/button_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clear"> </button> </linearlayout> </linearlayout> ~~~ 这是应用程序Freg的主界面配置文件,在屏幕中显示一个TextView控件和三个Button控件。 **strings.xml** ~~~ <!--?xml version="1.0" encoding="utf-8"?--> <resources> <string name="app_name">Freg</string> <string name="value">Value</string> <string name="hint">Please input a value...</string> <string name="read">Read</string> <string name="write">Write</string> <string name="clear">Clear</string> </resources> ~~~ 这是应用程序Freg的字符串资源文件,定义了在应用程序中使用到的各个字符串。 **icon.png** 这是应用程序Freg的图标文件,可以根据需要来放置不同的图片文件。 **AndroidManifest.xml** ~~~ <!--?xml version="1.0" encoding="utf-8"?--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="shy.luo.freg" android:versioncode="1" android:versionname="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Freg" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN"> </action> <category android:name="android.intent.category.LAUNCHER"> </category> </intent-filter> </activity> </application> </manifest> ~~~ 这是应用程序Freg的配置文件,由于应用程序Freg定义了一个Activity组件Freg,因此,要在这个配置文件中对它进行配置。 **Android.mk** ~~~ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := Freg include $(BUILD_PACKAGE) ~~~ 这是应用程序Freg的编译脚本文件,指定程序的名称为“Freg”。 在应用程序Freg的各个文件都准备好以后,就可以对它进行编译和打包了。 ~~~ USER@MACHINE:~/Android$ mmm ./packages/experimental/Freg/ USER@MACHINE:~/Android$ make snod ~~~ 打包后得到的Android系统镜像文件system.img就包含有应用程序Freg了。 最后,我们使用这个新的Android系统镜像文件system.img来启动Android模拟器。 ~~~ USER@MACHINE:~/Android$ emulator -kernel kernel/goldfish/arch/arm/boot/zImage ~~~ Android模拟器运行起来之后,我们就可以在应用程序启动器中启动应用程序Freg了,它的界面如图2-2所示。 ![应用程序Freg的界面](https://box.kancloud.cn/e6528a503228e46f171aeb34f24ed460_795x565.png =795x565) 应用程序Freg启动起来之后,通过点击Read按钮,就可以通过硬件访问服务FregService来读取虚拟硬件设备freg的寄存器val的内容了,而通过在编辑框中输入一个整数值,并且点击Write按钮,就可以通过硬件访问服务FregService将这个整数值写入到虚拟硬件设备freg的寄存器val中了。