Galaxy Note 3上的Android开放附件

时间:2014-02-27 16:47:15

标签: android samsung-mobile android-open-accessory

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

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

我正在尝试该应用的所有手机都没有根,我已经确认所有手机都有文件

  1. /system/framework/com.android.future.usb.accessory.jar
  2. /system/etc/permissions/android.hardware.usb.accessory.xml
  3. ,只要我知道,只有两个人要求支持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,内核版本3.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社区给我一些提示。

    任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

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