1

我正在使用各种手机/平板电脑和 Arduino DUE 对 Android 开放附件协议 (AOA) 进行一些实验。

我需要一些帮助来尝试找到基于 AOA 的简单应用程序的不同行为的原因,该应用程序从模拟输入引脚读取数据并改变 Arduino DUE 的数字输出引脚的状态。

我尝试使用该应用程序的所有手机均未植根,并且我已验证所有手机都具有文件

  1. /system/framework/com.android.future.usb.accessory.jar
  2. /system/etc/permissions/android.hardware.usb.accessory.xml

据我所知,只有这两个请求支持AOA。

命名的应用程序在三星 Galaxy S2(Android 版本 4.1.2,内核 v3.0.31-1211311)和 Galaxy Pocket Neo(Android 版本 4.1.2,内核 v3.0.15-1456085)上运行良好,但只能“部分运行” " 在三星 Galaxy Note 3(Android 版本 4.3,内核 v3.4.0-2019540)上。

更详细地说,当我将配件连接到所有指定的手机(还有 Galaxy Note 3)时,它会被正确识别,并且与 Arduino 草图关联的应用程序会正确控制(所有手机)数字输出引脚的状态,但 Galaxy Note 似乎无法从 Arduino 接收并显示包含模数转换结果的消息(两个字节)。

该应用程序是UDOO开发平台的教程项目之一,原帖在这里:http ://www.udoo.org/ProjectsAndTutorials/android-and-arduino-on-udoo-bidirectional-communication/?portfolioID=1394

这是 MainActivity.java 的代码:

package org.udoo.androidadkdemobidirect;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.udoo.androidadkdemobidirect.R;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class MainActivity extends Activity implements Runnable{

    private static final String TAG = "UDOO_AndroidADKFULL";     
    private static final String ACTION_USB_PERMISSION = "org.udoo.androidadkdemobidirect.action.USB_PERMISSION";

    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent;
    private boolean mPermissionRequestPending;
    private Message m;

    UsbAccessory mAccessory;
    ParcelFileDescriptor mFileDescriptor;
    FileInputStream mInputStream;
    FileOutputStream mOutputStream;

    private static ToggleButton btn_LED = null;
    private static TextView tv_adResult = null;
    private boolean running = false;

    // Receive the USB attached intent 
    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) {
                    UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    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)) {
                UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                if (accessory != null && accessory.equals(mAccessory)) {
                    closeAccessory();
                }
            }
        }
    };

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        registerReceiver(mUsbReceiver, filter);

        if (getLastNonConfigurationInstance() != null) {
            mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
            openAccessory(mAccessory);
        }

        setContentView(R.layout.activity_main);
        btn_LED = (ToggleButton) findViewById(R.id.toggleButtonLED);
        tv_adResult = (TextView) findViewById(R.id.adResult);
    }

    @SuppressWarnings("deprecation")
    @Override
    public Object onRetainNonConfigurationInstance() {
        if (mAccessory != null) {
            return mAccessory;
        } else {
            return super.onRetainNonConfigurationInstance();
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        if (mInputStream != null && mOutputStream != null) {
            running = true;
            return;
        }
        //open the accessory from the accessory list
        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
        UsbAccessory accessory = (accessories == null ? null : accessories[0]);
        if (accessory != null) {
            if (mUsbManager.hasPermission(accessory)) {
                openAccessory(accessory);
            } else {
                synchronized (mUsbReceiver) {
                    if (!mPermissionRequestPending) {
                        mUsbManager.requestPermission(accessory,mPermissionIntent);
                        mPermissionRequestPending = true;
                    }
                }
            }
        } else {
            Log.d(TAG, "mAccessory is null");
        }
    }

    @Override
    public void onPause() {
        running = false;
        super.onPause();    
    }

    @Override
    public void onDestroy() {
        running = false;
        closeAccessory();
        unregisterReceiver(mUsbReceiver);
        super.onDestroy();
    }

    // open the accessory and open the input and output stream from the descriptor
    // start also the thread that reads from Arduino
    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(this, "UDOO_ADK_readfrom");
            running = true;
            thread.start();

            Toast.makeText(getApplicationContext(), "Accessory connected", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "openaccessory");
        } 
        else {
            Toast.makeText(getApplicationContext(), "Accessory not connected", Toast.LENGTH_SHORT).show();
        }
    }

    // close the accessory
    private void closeAccessory() {
        Log.i(TAG, "closeaccessory");
        try {
            if (mFileDescriptor != null) {
                mFileDescriptor.close();
            }
        } catch (IOException e) {
        } finally {
            mFileDescriptor = null;
            mAccessory = null;
            running = false;
        }
    }

    // ToggleButton method - send message to Arduino
    public void writeToAccessory(View v){
        if (mAccessory != null) {
            byte[] message = new byte[1];

            message[0] = (byte) (btn_LED.isChecked()?1:0); 

            if (mOutputStream != null) {
                try {
                    mOutputStream.write(message);
                } catch (IOException e) {
                    Log.e(TAG, "write failed", e);
                }
            }
        }
        else
            Toast.makeText(getApplicationContext(), "Accessory not connected", Toast.LENGTH_SHORT).show();
    }


    // Thread to read data from Arduino
    public void run() {
        int ret = 0;
        byte[] buffer = new byte[4];


        while (running) {
            try {
                ret = mInputStream.read(buffer);
            } catch (IOException e) {
                break;
            }
            m = Message.obtain(mHandler);

            if (ret != 0) {
                m.arg1 = (int) ((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff);
                ret = 0;
            }           
            mHandler.sendMessage(m);        
        }
    }


    static Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            final int temp = msg.arg1;

            tv_adResult.setText(String.format("%4d (= %.2f V)", temp, 3.3/1024*temp));      
        }
    };
}

我还验证了这种奇怪的行为对于基于 AOA 协议的其他应用程序也存在,即:Galaxy Note 3 正确地将输出消息发送到附件,但没有从中读取输入消息。

我找不到问题出在哪里,我会要求 StackOverflow 社区给我一些提示。

任何帮助将不胜感激。

4

1 回答 1

0

我不确定这是否有帮助,但您可以尝试从开发人员选项中禁用 USB 调试。有些手机在调试模式上存在问题。

于 2014-03-26T03:09:54.653 回答