android駆動からアプリケーションへ(二)


JAVAアプリケーションはJNIを呼び出してドライバにアクセスする
以下はLedテストプログラムの例であり、ドライバリファレンス(一)
具体的な手順:
  • eclipseでandroidエンジニアリング(TestLed)を作成します.以下はデフォルトで生成されたJAVAコードです.
  • package com.android;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class TestLedActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
    }
    
  • ローカルメソッド
  • をプログラムに追加する
    	//         
    	public native int OpenLed();
    	public native int ControlLed(int led_id, int cmd);
    	//    C/C++       
    	static {
    		System.loadLibrary("yyp_led_lib");
    	}
  • プロジェクトディレクトリにjniフォルダ
  • を作成
    $ cd workspace/TestLed/
    $ mkdir jni
  • javahコマンドでヘッダファイル
  • を生成する.
    プロジェクトホームにコマンドを入力:$javah-classpath bin/classes/-d jni com.android.TestLedActivity
    説明:-classpath bin/classes/:クラスのパスがbin/classesディレクトリにあることを示します.-d jniは.hヘッダファイルの生成経路;com.android.TestLedActivity:package.class組成.
    コマンドが正常に実行されると、jniフォルダでヘッダファイルcomが生成されます.android_TestLedActivity.h
    $ ls jni com_android_TestLedActivity.h
  • C/C++ファイル実装ヘッダファイルインタフェース
  • を作成する.
    eclipseプロジェクトをリフレッシュし、jniディレクトリを右クリックしてyyp_を作成します.led_lib.cファイルを編集します(jni->New->File):
    #include <string.h>
    #include <jni.h>
    #include <fcntl.h>//    
    #include "android/log.h"
    
    static const char *TAG = "yyp_jni";
    
    #define LOG_INFO(fmt,args...)		__android_log_print(ANDROID_LOG_INFO, TAG,fmt, ##args)
    #define LOG_DEBUG(fmt, args...)		__android_log_print(ANDROID_LOG_DEBUG, TAG,fmt, ##args)
    #define LOG_ERROR(fmt, args...) 	__android_log_print(ANDROID_LOG_ERROR, TAG, fmt,##args)
    #define DEVICE_NAME		"/dev/yyp_led"
    
    
    
    int fd;
    
    JNIEXPORT jint JNICALL Java_com_android_ledtest_LedTestActivity_OpenLed
      (JNIEnv *env, jobject this)
    {
    	fd = open(DEVICE_NAME,O_RDWR|O_SYNC);
    	LOG_INFO("fd = %d\r
    ",fd); if(-1 == fd) { LOG_INFO("open led_devices is failed!\r
    "); return -1; } return 0; } JNIEXPORT jint JNICALL Java_com_android_ledtest_LedTestActivity_ControlLed (JNIEnv *ent, jobject this, jint led_id, jint cmd) { if (-1 == fd) { LOG_ERROR("Led Module is not open!\r
    "); return -1; } if(cmd!=0 && cmd!=1) { LOG_ERROR("This conmand is not surport!\r
    "); return -2; } switch (led_id) { case 1: ioctl(fd, cmd, 0); break; case 2: ioctl(fd, cmd, 1); break; case 3: ioctl(fd, cmd, 2); break; case 4: ioctl(fd, cmd, 3); break; case 0: ioctl(fd, cmd, 0); ioctl(fd, cmd, 1); ioctl(fd, cmd, 2); ioctl(fd, cmd, 3); break; default: LOG_ERROR("This led is not exit!\r
    "); break; } return 0; }
  • jniのC/C++ファイルに対応するmakefileファイル
  • を作成する
    jinフォルダにAndroidを作成します.mkファイル($vim jni/Android.mk)を編集します.
    LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS := -llog LOCAL_MODULE := yyp_led_lib LOCAL_SRC_FILES := yyp_led_lib.c include $(BUILD_SHARED_LIBRARY)
  • はndk-buildで生成する.soファイル
  • プロジェクトディレクトリにndk-buildコマンドを入力します.
    $ ndk-build Compile thumb  : yyp_led_lib <= yyp_led_lib.c SharedLibrary  : libyyp_led_lib.so Install        : libyyp_led_lib.so => libs/armeabi/libyyp_led_lib.so
    eclipseプロジェクトをリフレッシュすると、libsディレクトリに多くのことがわかりました.soファイル(libs/armeabi/libyyp_led_lib.so)
  • eclipseエンジニアリングでledコントロールボタンを追加し、JAVAアプリケーションでledをコントロールする効果を達成してTestLedActivityを編集する.JAvaファイル:
    package com.android;
    
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    public class TestLedActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            //   Led  
            OpenLed();
    		Button key_led1_on = (Button) findViewById(R.id.led1_on);
    		key_led1_on.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				ControlLed(1, 1);
    			}
    		});
    
    		Button key_led2_on = (Button) findViewById(R.id.led2_on);
    		key_led2_on.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				ControlLed(2, 1);
    
    			}
    		});
    
    		Button key_led3_on = (Button) findViewById(R.id.led3_on);
    		key_led3_on.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				ControlLed(3, 1);
    			}
    		});
    
    		Button key_led4_on = (Button) findViewById(R.id.led4_on);
    		key_led4_on.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				ControlLed(4, 1);
    			}
    		});
    
    		Button key_led0_on = (Button) findViewById(R.id.led0_on);
    		key_led0_on.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				ControlLed(0, 1);
    			}
    		});
    
    		Button key_led0_off = (Button) findViewById(R.id.led0_off);
    		key_led0_off.setOnClickListener(new View.OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				ControlLed(0, 0);
    			}
    		});
        }
    	//         
    	public native int OpenLed();
    	public native int ControlLed(int led_id, int cmd);
    	//    C/C++       
    	static {
    		System.loadLibrary("yyp_led_lib");
    	}
    }
    それぞれmain.xmlとstrings.xmlは対応するコントロールと文字列を追加します:main.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello" />
        <Button
            android:id="@+id/led1_on"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:text="@string/LEDON1"></Button>
        <Button
            android:id="@+id/led2_on"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:text="@string/LEDON2"></Button>
    	<Button
            android:id="@+id/led3_on"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:text="@string/LEDON3"></Button>
        <Button
            android:id="@+id/led4_on"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:text="@string/LEDON4"></Button>
    	<Button
            android:id="@+id/led0_on"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:text="@string/LEDON0"></Button>
    	<Button
            android:id="@+id/led0_off"
    		android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:text="@string/LEDOFF0"></Button>
    
    </LinearLayout>
    strings.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <string name="hello">This is a led TestApp!</string>
        <string name="app_name">ledtest</string>
        <string name="LEDON1">  1  </string>
        <string name="LEDON2">  2  </string>
        <string name="LEDON3">  3  </string>
        <string name="LEDON4">  4  </string>
        <string name="LEDON0">     </string>
        <string name="LEDOFF0">     </string>
    
    </resources>
    apkにコンパイルし、テストを実行し、ok!