寫好底層的庫,接下來就是寫應用程式使用或驗證了。
前面也介紹了,應用程式訪問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