2012年1月12日木曜日

イチからつくるADK「AdkLedの作成その4」プライベート&パブリックメソッドの記述

イチからつくるADK「AdkLedの作成その3」の続きです。
前回は、Activityのライフサイクルで必要なオーバーライドメソッドを記述していきました。必要なオーバーライドメソッドを記述した時点で、修正可能なエラーを直していくと、以下の7項目のエラーが残ります。


同じ内容のエラーがありますので、まとめると5種類のエラーになります。
上記5つのエラーは、各々ソースを記述する必要があるため、ひとつづつ概要を説明しソースを記述していきましょう。

4. プライベート・メソッド、パブリックメソッドの記述

エラー「mUsbReceiver cannot be resolved to a variable」
mUsbReceiverはブロードキャストレシーバーになります。
IntentFilterクラスのfilterインスタンスでセットされたUSB接続の2つのアクション(独自インテントとUSB接続取り外し)が起きたときに呼び出される処理です。

4.1. フィールドとonCreateメソッドの間にmUSBReceiverインスタンスフィールドを記述します(下図では40行目)。カーソルを移動させてください。

4.2. BroadcastReceiverクラスのmUsbReceiverのソースは以下の通りです。貼付けてください。
    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    // Intent からアクセサリを取得
                    UsbAccessory accessory = UsbManager.getAccessory(intent);

                    // パーミッションがあるかチェック
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        // 接続を開く
                        openAccessory(accessory);
                    } else {
                        Log.d(TAG, "permission denied for accessory " + accessory);
                    }
                    mPermissionRequestPending = false;
                }
            } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
                // Intent からアクセサリを取得
                UsbAccessory accessory = UsbManager.getAccessory(intent);
                if (accessory != null && accessory.equals(mAccessory)) {
                    // 接続を閉じる
                    closeAccessory();
                }
            }
        }
    };
ファイルを保管します。これで「mUsbReceiver cannot be resolved to a variable」エラーは消えました。

エラー「メソッド openAccessory(UsbAccessory) は型 MainActivity で未定義です」

エラー「メソッド closeAccessory() は型 MainActivity で未定義です」

エラー「メソッド enableControls(boolean) は型 MainActivity で未定義です」
enableControlsメソッドは、プライベートメソッドです。
トグルボタンの状態をTextViewに表示し、使用可能にします。

エラー「メソッド sendCommand(byte, byte) は型 new CompoundButton.OnCheckedChangeListener(){} で未定義です」
sendCommandメソッドは、パブリックメソッドです。
トグルボタンが押されたとき、Arduino側にLEDをオン/オフさせる命令(独自のプロトコル)を送ります。

4.3. 上記4つのエラーについて、各ソースを記述します。onResumeメソッドとrunメソッドの間に記述します。アウトラインで、「run(): void」をクリックしてrunメソッド先頭まで移動します。

4.4. onResumeメソッドとrunメソッドの間に、4つのメソッドのソースを記述してください(上図では154行目になります)。
     private void openAccessory(UsbAccessory accessory) {
        // アクセサリにアクセスするためのファイルディスクリプタを取得
        mFileDescriptor = mUsbManager.openAccessory(accessory);

        if (mFileDescriptor != null) {
            mAccessory = accessory;
            FileDescriptor fd = mFileDescriptor.getFileDescriptor();

            // 入出力用のストリームを確保
            mInputStream = new FileInputStream(fd);
            mOutputStream = new FileOutputStream(fd);

            // この中でアクセサリとやりとりする
            Thread thread = new Thread(null, this, "DemoKit");
            thread.start();
            Log.d(TAG, "accessory opened");

            enableControls(true);
        } else {
            Log.d(TAG, "accessory open fail");
        }
    }

    private void closeAccessory() {
        enableControls(false);

        try {
            if (mFileDescriptor != null) {
                mFileDescriptor.close();
            }
        } catch (IOException e) {
        } finally {
            mFileDescriptor = null;
            mAccessory = null;
        }
    }

    private void enableControls(boolean enable) {
        if (enable) {
            mStatusView.setText("connected");
        } else {
            mStatusView.setText("not connected");
        }
        mToggleButton.setEnabled(enable);
    }
    // アプリ -> アクセサリ
    public void sendCommand(byte command, byte value) {
        byte[] buffer = new byte[2];
       
        if(value != 0x1 && value != 0x0)
            value = 0x0;

        // 2byte の独自プロトコル
        // 0x1 0x0 や 0x1 0x1
        buffer[0] = command;
        buffer[1] = value;
        if (mOutputStream != null) {
            try {
                mOutputStream.write(buffer);
            } catch (IOException e) {
                Log.e(TAG, "write failed", e);
            }
        }
    }
4.5. 上記4つのメソッドを記述して、ファイルを保管してください。エラーは3つのみになります。

これら3つのエラーは、パッケージのインポートで解決しますので、赤×をダブルクリックしてエラー修正を行ってください。

これで赤×はなくなりましたが、スレッドが動作する際に実行されるrunメソッドの中身が記述されていません。

4.6. 再度runメソッドに移動し、以下のJavaソースを記述してください。
    // ここでアクセサリと通信する
    @Override
    public void run() {
        int ret = 0;
        byte[] buffer = new byte[16384];
        int i;

        // アクセサリ -> アプリ
        while (ret >= 0) {
            try {
                ret = mInputStream.read(buffer);
            } catch (IOException e) {
                break;
            }

            i = 0;
            while (i < ret) {
                int len = ret - i;

                switch (buffer[i]) {
                    case 0x1:
                        // 2byte の独自プロトコル
                        // 0x1 0x0 や 0x1 0x1 など
                        if (len >= 2) {
                            Message m = Message.obtain(mHandler, MESSAGE_LED);
                            m.obj = new LedMsg(buffer[i + 1]);
                            mHandler.sendMessage(m);
                        }
                        i += 2;
                        break;

                    default:
                        Log.d(TAG, "unknown msg: " + buffer[i]);
                        i = len;
                        break;
                }
            }

        }
    
4.7. 上記ソースを記述してファイルを保管してください。エラーが6項目でてきます。
 
「Messageを解決できません」をダブルクリックして、Messageクラスのインポートだけ行います。
エラーが4項目に減ったはずです。

次にメッセージキューイングを行うハンドラを記述してMainActivityを完成させましょう。


0 件のコメント:

コメントを投稿