android分层学习笔记(四)

写好底层的库,接下来就是写应用程序使用或验证了。
前面也介绍了,应用程序访问jni库,有多种方法,最简单的就是直接调用,其次是用service,再次为service manager
1 直接加载。
    这有点儿像从三楼直接跳下来。其实java本来就有调用原生代码的接口。android开发还包含有ndk开发,这个就是直接用c来做应用程序。

1.1 testjni1.java
在与framwork同层目录下,创建app目录,mkdir app
再在app目录下,创建dirload/src/com/ask/目录,生成testjni1.java,内容如下:

package com.ask.testjni;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class testjni1 extends Activity
{

    static
    {
        //System.load("/system/lib/libaskgpio.so");
        System.load("/system/lib/libaskgpio");
    }
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Call an API on the library.
        _gpio_init();
        _gpio_set(1);
        _gpio_clr(2);
            
        TextView tv = new TextView(this);
        tv.setText("gpio 1 is set to 1. gpio 2 is set to 0.");
        setContentView(tv);
   }
    private static native boolean _gpio_init();
    private static native boolean _gpio_set(int gpio);
    private static native boolean _gpio_clr(int gpio);
}
说明:System.load("/system/lib/libaskgpio");有实际测试中这样加载可能不成功,要定居这样System.load("/system/lib/libaskgpio.so");

1.2 Android.mk编写,保存在dirload目录下

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := user

# This is the target being built.
LOCAL_PACKAGE_NAME := testjni1

# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

# Link against the current Android SDK.
LOCAL_SDK_VERSION := current

include $(BUILD_PACKAGE)


1.3 再写AndroidManifest.xml,保存至dirload目录下
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ask.testjni1">
    <application>   
        <activity android:name="testjni1">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

最后编译,将在out/target/product/generic/system/app/生成testjni1.apk文件。


2 调用service方式
2.1再在app目录下,创建serviceload/src/com/ask/目录,生成serviceload.java,内容如下:
package com.ask.serviceload;
import com.ask.server.serviced;  //注意不是GpioService
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class serviceload extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Call an API on the library.
    serviced sd = new serviced();
    sd.GpioSet(1);
    sd.GpioClr(2);     
        TextView tv = new TextView(this);
        tv.setText("gpio 1 is set. gpio 2 is clr.");
        setContentView(tv);
    }
}
这里new一个serviced,这时将会加载jni的库,然后调用serviced里的api函数GpioSet和GpioClr
2.2 编写Android.mk文件,保存至serviceload目录下
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := user

# This is the target being built.
LOCAL_PACKAGE_NAME := serviceload

# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

# Link against the current Android SDK.
LOCAL_SDK_VERSION := current

# Also link against our own custom library.
LOCAL_JAVA_LIBRARIES := ask

include $(BUILD_PACKAGE)

2.3 再写AndroidManifest.xml,保存至serviceload目录下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ask.GpioClient">
   
    <application>
   
        <!-- This tells the system about the custom library used by the
             application, so that it can be properly loaded and linked
             to the app when the app is initialized. -->
        <uses-library android:name="com.ask.serviced" />
       
        <activity android:name="serviceload">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

最后编译,将在out/target/product/generic/system/app/生成serviceload.apk文件。

2.4 运行此程序由于用到serviceload类,因此还要在/etc/permission下,增加一个permission,如下
    <?xml version="1.0" encoding="utf-8"?>
    <permissions>
        <library name="com.ask.serviced"
                file="/system/framework/ask.jar"/>
    </permissions>
    文件名可为com.ask.serviced.xml


3 通过service manager调用jni
3.1 在app目录下,创建managerload/src/com/ask/目录
3.1.1 生成gpio system service类,文件名GpioSystemServer.java
    这个类的生成主要是供managerload调用,内容如下
package com.ask.GpioSystemServer;

import com.ask.server.GpioService;

import android.os.IBinder;
import android.os.ServiceManager;
import android.util.Log;
import android.app.Service;
import android.content.Context;
import android.content.Intent;

public class GpioSystemServer extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public void onStart(Intent intent, int startId) {
        Log.i("GpioSystemServer", "Start GpioService...");

    /* Please also see SystemServer.java for your interests. */
    GpioService gs = new GpioService();

        try {
            ServiceManager.addService("gpio", gs);
        } catch (RuntimeException e) {
            Log.e("GpioSystemServer", "Start GpioService failed.");
        }
    }
}   
3.1.2 生成managerload.java,内容如下:
package com.ask.managerload;
import ask.hardware.GpioManager;
import com.ask.server.GpioService;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Button;
import android.content.Intent;
import android.view.View;

public class managerload extends Activity implements View.OnClickListener {
    private GpioManager mGpioManager = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Start LedService in a seperated process.
        startService(new Intent("com.ask.systemserver"));

        Button btn = new Button(this);
        btn.setText("Click to turn gpio 1 set 1");
        btn.setOnClickListener(this);

        setContentView(btn);
    }

    public void onClick(View v) {

        // Get LedManager.
        if (mGpioManager == null) {
        Log.i("LedTest", "Creat a new mGpioManager object.");
        mGpioManager = new GpioManager();
        }

        if (mGpioManager != null) {
        Log.i("managerload", "Got GpioManager object.");
    }

      
        mGpioManager.GpioSet(1);
        TextView tv = new TextView(this);
        tv.setText("gpio 1 is set 1.");
        setContentView(tv);
        }


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

LOCAL_MODULE_TAGS := user

# This is the target being built.
LOCAL_PACKAGE_NAME := managerload

# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

# Link against the current Android SDK.
LOCAL_SDK_VERSION := current

# Also link against our own custom library.
LOCAL_JAVA_LIBRARIES := ask framework

# We need to assign platform key to use ServiceManager.addService.
LOCAL_CERTIFICATE := platform

include $(BUILD_PACKAGE)

3.4 同2.4一样,在/etc/permission下增加一个xml文件。
 运行此程序由于用到serviceload类,因此还要在/etc/permission下,增加一个permission,如下
    <?xml version="1.0" encoding="utf-8"?>
    <permissions>
        <library name="com.ask.server"
                file="/system/framework/ask.jar"/>
    </permissions>
    文件名可为com.ask.GpioService.xml

你可能感兴趣的:(android分层学习笔记(四))