现在的位置: 首页 > 综合 > 正文

android分层学习笔记(三)

2013年10月06日 ⁄ 综合 ⁄ 共 6063字 ⁄ 字号 评论关闭

对于应用程序访问jni库,是可以直接访问,即写个active,然后调用System.load函数,jni库加载进来,然后直接调用其中的api函数,从而实现操作硬件功能。但这不是android所规范的作法。
一般来说在framework写一些中间东西,我们称之为服务service。
关于android中的服务概念在android应用程序编写教程中,都会提及到,其中都提到服务的生命周期,此处不详细展开。

接下就着重点放在这个服务的实现上。

1 gpio serviced
  在service目录下创建framework/service/java/com/ask/serviced/目录,即
  cd framework
  mkdir -p service/java/com/ask/serviced
 
  再创建serviced.java文件,文件名应该就是类名。
 内容如下:
package com.ask.server;          //生成的包名为com.ask.server
import android.util.Config;
import android.util.Log;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
public final class serviced
{
    static
    {
        System.load("/system/lib/libaskgpio.so");  //加载jni库文件
    }

    public serviced()
    {
        Log.i("GpioService", "Go to get Gpio Stub...");
        _gpio_init();
    }

    /*
     * Ctop Gpio native methods.
     */
    public boolean GpioSet(int gpio)
    {
        Log.i("AskPlatform", "Gpio set");
        return _gpio_set(gpio);
    }

    public boolean GpioClr(int gpio)
    {
        Log.i("AskPlatform", "Gpio clr");
        return _gpio_clr(gpio);
    }

    private static native boolean _gpio_init();
    private static native boolean _gpio_set(int gpio);
    private static native boolean _gpio_clr(int gpio);
}
其中:
     private static native boolean _gpio_init();
    private static native boolean _gpio_set(int gpio);
    private static native boolean _gpio_clr(int gpio);
    是声明libaskgpio.so库中的函数,这样才可以给java程序调用。
Android.mk的编写,内容如下:
LOCAL_PATH := $(call my-dir)
# the library
# =============================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := /
            $(call all-subdir-java-files)

LOCAL_MODULE_TAGS := eng

LOCAL_MODULE := ask

include $(BUILD_JAVA_LIBRARY)

# The JNI component
include $(CLEAR_VARS)
include $(call all-makefiles-under,$(LOCAL_PATH))
保存到framework目录下

在应用程序中,要加入一些permissions才能使用这个java包,这个将在下节的应用程序中说明。

2 gpio service manager
在1中所描述的是service 可供应用程序直接调用,而在android,对于应用程序中,更规范的做法是通过service manager来调用管理service。即应用程序通过mangger访问jni库
这里面会涉及到aidl,aidl,可简单认为是一个接口。在编译过程中,会将aidl文件,编译成java文件,生成一个接口。

首先在在framework目录创建core/java/ask/hardware/目录
 即cd framework目录
   mkdir -p core/java/ask/hardware/
创建GpioManager.java文件和IGpioService.aidl文件
GpioManager.java内容如下:

package ask.hardware;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.util.Log;
import ask.hardware.IGpioService;

/**
 * Class that lets you access the Ctop GpioService.
 */
public class GpioManager
{
    private static final String TAG = "GpioManager";
    private IGpioService mGpioService;

    public GpioManager()
    {
   
        mGpioService = IGpioService.Stub.asInterface(ServiceManager.getService("Gpio"));  //获取gpio的service,

        if (mGpioService != null)
        {
                Log.i(TAG, "The GpioManager object is ready.");
        }
    }

    public boolean GpioSet(int n)
    {
        boolean result = false;

        try
        {
            result = mGpioService.GpioSet(n);
        }
        catch (RemoteException e)
        {
            Log.e(TAG, "RemoteException in GpioManager.Gpio set:", e);
        }
        return result;
    }

    public boolean GpioClr(int n)
    {
        boolean result = false;

        try
        {
            result = mGpioService.GpioClr(n);
        }
        catch (RemoteException e)
        {
            Log.e(TAG, "RemoteException in GpioManager.Gpio clr:", e);
        }
        return result;
    }
}
其中: mGpioService = IGpioService.Stub.asInterface(ServiceManager.getService("Gpio"));是获取gpio的service,这时gpio service不是1中所编写的gpio service内容,要重要编写,稍后给出。

IGpioService.aidl的内容如下:这个比较简单
package ask.hardware;
interface IGpioService
{
    boolean GpioSet(int gpio);
    boolean GpioClr(int gpio);
}
生成ask.hardware与GpioManager生成的包是一致的。

最后缩写gpioservice代码
    这个与1所编写的 gpio serviced,类似。如下:
    在framework/service目录下创建java/com/ask/service/目录,即
    cd framework
    mkdir -p service/java/com/ask/service
    cd service/java/com/ask/service
    在此目录下创建GpioSerivce.java,内容如下
   
 package com.ask.server;
import android.util.Config;
import android.util.Log;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.IBinder;
import ask.hardware.IGpioService;

public final class GpioService extends IGpioService.Stub
{

    static
    {
        System.load("/system/lib/libaskgpio.so");
    }

    public GpioService()
    {
        Log.i("GpioService", "Go to get Gpio Stub...");
        _gpio_init();
    }

    /*
     * Ctop Gpio native methods.
     */
    public boolean GpioSet(int gpio)
    {
        Log.i("CTOPPlatform", "Gpio set");
        return _gpio_set(gpio);
    }

    public boolean GpioClr(int gpio)
    {
        Log.i("CTOPPlatform", "Gpio clr");
        return _gpio_clr(gpio);
    }

    private static native boolean _gpio_init();
    private static native boolean _gpio_set(int gpio);
    private static native boolean _gpio_clr(int gpio);

应该说GpioService类与serviced类是比较相似的,只是GpioService继承于IGpioService.Stub。

Android.mk文件的编写
LOCAL_PATH := $(call my-dir)

# the library
# =============================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := /
            $(call all-subdir-java-files)

LOCAL_MODULE_TAGS := eng

LOCAL_MODULE := ask

# AIDL
LOCAL_SRC_FILES += /
            core/java/ask/hardware/IGpioService.aidl

include $(BUILD_JAVA_LIBRARY)

# The JNI component
include $(CLEAR_VARS)
include $(call all-makefiles-under,$(LOCAL_PATH))

保存此文件到framework目录下

然后编译。

两种的service目录结构如下:
framework-|
                  |->core->java->ask->hardware-|
                  |                                                  |->GpioManager.java
                  |                                                 |->IGpioService.aid
                  |->service-|
                  |             |->java->com->ask-|
                  |             |                              |->service->GpioService.java
                  |             |                              |->serviced->serviced.java
                  |             |->jni->|
                  |                         |->Android.mk
                  |                         |->com_ask_gpio.cpp
                  |->Android.mk
         
 最后make的时候可以在out/target/product/generic/system/framework目录下看到ask.jar包。
 
 注,以上两种service方式在framework目录下的Android.mk文件是可以一样的。当然独立编译是最好的,因为我们没有必要用同时用两种方法来实现一个功能,择其善者而用之。
 
 待续为应用程序编写

抱歉!评论已关闭.