如何实现Android Open Accessory模式即服务?

发布于 2024-12-13 07:06:24 字数 2409 浏览 1 评论 0原文

我一直在研究 Android 开放配件开发套件。通过遵循Google 提供的 DemoKit 示例,我没有遇到任何问题使解决方案适应我的应用程序。我可以很好地检测、通信和拆卸配件。

但是,我需要将整个事情作为服务来运行。我有一个由 USB_ACCESSORY_ATTACHED 意图(即连接附件时)启动的基本活动,并且工作正常。但是,一旦我启动服务并在其中运行与常规活动中的工作解决方案相同的代码,每当我尝试执行以下操作时,我都会收到 IOException (“没有这样的设备”)与配件通信(监控arduino端显示USB连接成功)。即使我在服务中指定了正确的 BroadcastReceiver、在 onStartCommand 回调方法中注册它并使用 openAccessory() 设置通信端点,也会发生这种情况。相关代码如下。

@Override
public void onCreate() {
    Log.d(TAG, "ONCREATE");

    manager = UsbManager.getInstance(this);
    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
            ACTION_USB_PERMISSION), 0);

    // Register broadcastreceiver for filtering accessory events
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
    registerReceiver(mUsbReceiver,filter);
    super.onCreate();
}

public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "ONSTARTCOMMAND METHOD ACCESSED");

    if (mInputStream != null && mOutputStream != null) {
        return START_NOT_STICKY;
    }

    UsbAccessory[] accessories = manager.getAccessoryList();
    mAccessory = (accessories == null ? null : accessories[0]);

    if (mAccessory != null) {
        if (manager.hasPermission(mAccessory)) {
            openAccessory();
        } else {
            synchronized (mUsbReceiver) {
                if (!mPermissionRequestPending) {
                    manager.requestPermission(mAccessory,
                            mPermissionIntent);
                    mPermissionRequestPending = true;
                }
            }
        }
    } else {
        Log.d(TAG, "mAccessory is null");
    }
    return START_NOT_STICKY;
}

openAccessory 方法:

/**
 * Open the accessory
 */
private void openAccessory() {
    Log.d(TAG, "openAccessory: "+mAccessory);
    mFileDescriptor = manager.openAccessory(mAccessory);
    if (mFileDescriptor != null) {
        FileDescriptor fd = mFileDescriptor.getFileDescriptor();
        mInputStream = new FileInputStream(fd);
        mOutputStream = new FileOutputStream(fd);
        Thread thread = new Thread(null,this,"AccessoryThread");
        thread.start();
    }
}

对于可能的解决方案有什么想法吗?

I've been playing around with the Android Open Accessory Development Kit. By following the DemoKit example provided by Google, I've had no trouble in adapting the solution to my application. I can detect, communicate, and detach the accessory just fine.

However, I would need to run the whole thing as a service. I have a base activity which is launched by the USB_ACCESSORY_ATTACHED intent (that is, when the accessory is connected), and that works fine. But as soon as I start my service and run identical code in it compared to my working solution within a regular activity, I'm receiving an IOException ("no such device") whenever I'm trying to communicate with the accessory (monitoring arduino side shows a successful USB connection). This happens even though I've specified the correct BroadcastReceiver within the service, registered it in the onStartCommand callback method, and set up the communication endpoints with openAccessory(). Relevant code is as follows.

@Override
public void onCreate() {
    Log.d(TAG, "ONCREATE");

    manager = UsbManager.getInstance(this);
    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
            ACTION_USB_PERMISSION), 0);

    // Register broadcastreceiver for filtering accessory events
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
    registerReceiver(mUsbReceiver,filter);
    super.onCreate();
}

public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "ONSTARTCOMMAND METHOD ACCESSED");

    if (mInputStream != null && mOutputStream != null) {
        return START_NOT_STICKY;
    }

    UsbAccessory[] accessories = manager.getAccessoryList();
    mAccessory = (accessories == null ? null : accessories[0]);

    if (mAccessory != null) {
        if (manager.hasPermission(mAccessory)) {
            openAccessory();
        } else {
            synchronized (mUsbReceiver) {
                if (!mPermissionRequestPending) {
                    manager.requestPermission(mAccessory,
                            mPermissionIntent);
                    mPermissionRequestPending = true;
                }
            }
        }
    } else {
        Log.d(TAG, "mAccessory is null");
    }
    return START_NOT_STICKY;
}

openAccessory method:

/**
 * Open the accessory
 */
private void openAccessory() {
    Log.d(TAG, "openAccessory: "+mAccessory);
    mFileDescriptor = manager.openAccessory(mAccessory);
    if (mFileDescriptor != null) {
        FileDescriptor fd = mFileDescriptor.getFileDescriptor();
        mInputStream = new FileInputStream(fd);
        mOutputStream = new FileOutputStream(fd);
        Thread thread = new Thread(null,this,"AccessoryThread");
        thread.start();
    }
}

Any ideas for a possible solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

闻呓 2024-12-20 07:06:25

解决方案很简单。

if (intent.getAction().equals(USB_ACCESSORY_ATTACHED)) {
    Intent i = new Intent(this, YourServiceName.class);
    i.putExtras(intent);
    startService(i);
}

基本上,复制您在启动用于启动服务的活动时收到的意图,因为该意图包含 ADK 实现所需的附件的详细信息。

然后,在服务中继续像以前一样实现 ADK 的其余部分。

The solution was simple.

if (intent.getAction().equals(USB_ACCESSORY_ATTACHED)) {
    Intent i = new Intent(this, YourServiceName.class);
    i.putExtras(intent);
    startService(i);
}

Basically, copy the intent that you received when starting your activity that you use to launch the service, because the intent contains the details of the accessory that the ADK implementation needs.

Then, in the service proceed to implement the rest of ADK exactly as before.

停滞 2024-12-20 07:06:25

目前我无法为您的问题提供匹配的解决方案。但可能是这个
github 示例
向您展示如何解决您的问题:

我将分析 github 上给出的代码以实现与您要做的相同的事情。

At the moment I can't give you a matching solution to your problem. But may be this
github example
shows you how to solve your problem:

I am going to analyse the code given on github to implement just the same thing you're going to do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文