[实验3_app]_[2.5_开发Android应用程序来使用硬件访问服务]

回顾

我们首先看一下Android体系结构图:

在第2章,我们从 Linux Device Drivers,到 HAL,External Libraries & Android Runtime,Application Framework 再到 Applications,自底向上实现来一个应用程序控制Freg硬件驱动。

画图:https://www.processon.com/diagraming/674eb1c592740c307cc423ea

2.5,开发Android应用程序来使用硬件访问服务

目标:开发Android应用程序,通过硬件访问服务FregService来访问虚拟硬件设备freg的寄存器val的值。

Freg应用程序的目录结构:

aosp/packages/experimental/Freg
----AndroidManifest.xml
----Android.mk
----src
    ----shy/luo/freg
        ----Freg.java
----res
    ----layout
        ----main.xml
    ----values
        ----strings.xml
    ----drawable
        ----icon.png

Freg应用程序包含一个源代码目录src,一个资源目录res,一个配置文件AndroidManifest.xml和一个编译脚本文件Android.mk。

Freg.java

文件路径:packages/experimental/Freg/src/shy/luo/freg/Freg.java

文件定义了一个Activity组件Freg,它是应用程序Freg的主界面。在Activity组件Freg的界面上,有一个编辑框和三个按钮Read、Write和Clear,其中,编辑框用来显示或者输入虚拟硬件设备freg的寄存器val的值;按钮Read和Write分别用来读写虚拟硬件设备freg的寄存器val,而按钮Clear用来清空编辑框。

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;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // 通过 Service Manager 获得一个名称为"freg"的服务的Binder代理对象接口。
        // 这个服务对应于运行在系统进程System中的硬件访问服务FregService。
        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);
                Log.i(LOG_TAG, "Freg App read val :" + 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);
                Log.i(LOG_TAG, "Freg App write val :" + 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);
        }
    }
}

main.xml

文件路径:packages/experimental/Freg/res/layout/main.xml

这是应用程序Freg的主界面配置文件,在屏幕中显示一个 TextView 空间和三个 Button 控件。

<?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>

strings.xml

文件路径:packages/experimental/Freg/res/values/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>

icon.png

文件路径: packages/experimental/Freg/res/drawable/icon.png

这是应用程序Freg的图标文件,可以根据需要来放置不同的图片文件。

AndroidManifest.xml

文件路径:packages/experimental/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" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Android.mk

文件路径:packages/experimental/Freg/Android.mk

这是应用程序Freg的编译脚本文件,指定程序的名称为"Freg"。

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)

编译

dt@ubuntu:~/2.3.1_r1$ export PATH=$PATH:/home/dt/2.3.1_r1/out/host/linux-x86/bin
dt@ubuntu:~/2.3.1_r1$ source build/envsetup.sh 
including device/htc/passion/vendorsetup.sh
including device/samsung/crespo/vendorsetup.sh
dt@ubuntu:~/2.3.1_r1$ mmm ./packages/experimental/Freg/

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.1
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GRH78
============================================
make: Entering directory `/home/dt/2.3.1_r1`
target R.java/Manifest.java: Freg (out/target/common/obj/APPS/Freg_intermediates/src/R.stamp)
Warning: AndroidManifest.xml already defines versionCode (in http://schemas.android.com/apk/res/android); using existing value in manifest.
Warning: AndroidManifest.xml already defines versionName (in http://schemas.android.com/apk/res/android); using existing value in manifest.
target Java: Freg (out/target/common/obj/APPS/Freg_intermediates/classes)
Copying: out/target/common/obj/APPS/Freg_intermediates/classes-jarjar.jar
Copying: out/target/common/obj/APPS/Freg_intermediates/emma_out/lib/classes-jarjar.jar
Copying: out/target/common/obj/APPS/Freg_intermediates/classes.jar
Copying: out/target/common/obj/APPS/Freg_intermediates/noproguard.classes.jar
target Dex: Freg
Copying: out/target/common/obj/APPS/Freg_intermediates/noproguard.classes.dex
target Package: Freg (out/target/product/generic/obj/APPS/Freg_intermediates/package.apk)
Warning: AndroidManifest.xml already defines versionCode (in http://schemas.android.com/apk/res/android); using existing value in manifest.
Warning: AndroidManifest.xml already defines versionName (in http://schemas.android.com/apk/res/android); using existing value in manifest.
 'out/target/common/obj/APPS/Freg_intermediates//classes.dex' as 'classes.dex'...
Install: out/target/product/generic/system/app/Freg.apk
make: Leaving directory `/home/dt/2.3.1_r1`

dt@ubuntu:~/2.3.1_r1$ make snod

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.1
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GRH78
============================================
find: `frameworks/base/frameworks/base/docs/html': No such file or directory
find: `out/target/common/docs/gen': No such file or directory
find: `frameworks/base/frameworks/base/docs/html': No such file or directory
find: `out/target/common/docs/gen': No such file or directory
find: `frameworks/base/frameworks/base/docs/html': No such file or directory
find: `out/target/common/docs/gen': No such file or directory
find: `frameworks/base/frameworks/base/docs/html': No such file or directory
find: `out/target/common/docs/gen': No such file or directory
find: `frameworks/base/frameworks/base/docs/html': No such file or directory
find: `out/target/common/docs/gen': No such file or directory
Install: out/host/linux-x86/bin/mkyaffs2image
make snod: ignoring dependencies
Target system fs image: out/target/product/generic/system.img

打包后,得到的 Android 系统镜像文件 system.img 就包含有应用程序 Freg 了,下面我们启动模拟器看看:

运行

dt@ubuntu:~/goldfish$ cp out/target/product/generic/system.img /mnt/hgfs/AndroidEmulator/images/system.img
dt@ubuntu:~/goldfish$ cp out/target/product/generic/ramdisk.img /mnt/hgfs/AndroidEmulator/images/ramdisk.img


[win]> pushd d:\AndroidEmulator
[win]> start /b emulator.exe -sysdir d:\AndroidEmulator -system images\system.img -data images\userdata.img -ramdisk images\ramdisk.img -kernel images\zImage -skindir d:\AndroidEmulator\skins -skin HVGA

[win]> adb logcat | grep freg
I/FregServiceJNI(   66): Initializing HAL stub freg......
I/FregServiceJNI(   66): Device freg found.
I/FregHALStub(   66): Open device file /dev/freg successfully.
I/FregServiceJNI(   66): Device freg is open.
I/ActivityManager(   66): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=shy.luo.freg/.Freg } from pid 131
I/ActivityManager(   66): Start proc shy.luo.freg for activity shy.luo.freg/.Freg: pid=351 uid=10029 gids={}
I/shy.luo.freg.FregActivity(  351): Freg Activity Created
I/ActivityManager(   66): Displayed shy.luo.freg/.Freg: +1s853ms
I/FregHALStub(   66): Get value 0 from device file /dev/freg.
I/FregServiceJNI(   66): Get value 0 from device freg.
I/shy.luo.freg.FregActivity(  351): Freg App read val :0
I/FregServiceJNI(   66): Set value 68 to device freg.
I/FregHALStub(   66): Set value 68 to device file /dev/freg.
I/shy.luo.freg.FregActivity(  351): Freg App write val :68
I/FregHALStub(   66): Get value 68 from device file /dev/freg.
I/FregServiceJNI(   66): Get value 68 from device freg.
I/shy.luo.freg.FregActivity(  351): Freg App read val :68
I/FregServiceJNI(   66): Set value 6 to device freg.
I/FregHALStub(   66): Set value 6 to device file /dev/freg.
I/shy.luo.freg.FregActivity(  351): Freg App write val :6
I/FregHALStub(   66): Get value 6 from device file /dev/freg.
I/FregServiceJNI(   66): Get value 6 from device freg.
I/shy.luo.freg.FregActivity(  351): Freg App read val :6

Android模拟器运行起来之后,我们就可以在应用程序启动器中启动应用程序 Freg 了,打开 Freg 输入68,点击【Write】按钮写入值,然后点击【Read】按钮,读取值。