2011-08-08 32 views
33

Tôi đã làm việc qua the description and samples for USB host at developer.android.com để phát hiện thiết bị USB được đính kèm và tách rời.Máy chủ lưu trữ USB 3.1 của Android - Trình phát sóng không nhận được USB_DEVICE_ATTACHED

Nếu tôi sử dụng bộ lọc ý định trong tệp kê khai để khởi động ứng dụng khi thiết bị được kết nối, thiết bị hoạt động hoàn toàn tốt: Cắm, phát hiện thiết bị, android yêu cầu quyền khởi động ứng dụng, thông tin thiết bị được hiển thị trong một cái bàn.

Ứng dụng tôi đang phát triển không được bắt đầu/kết thúc chỉ khi thiết bị được gắn/tách rời (ví dụ: mục đích quản lý dữ liệu). Ngoài ra tôi không muốn hộp thoại mở bật lên nếu ứng dụng đang chạy. Vì vậy, tôi quyết định không bắt đầu hoạt động trực tiếp nếu một thiết bị được gắn, nhưng để đăng ký một BroadcastReceiver, đó là (sau này) phải thông báo cho các hoạt động nếu một thiết bị được tại-/tách ra. Người nhận này nhận ra hành động tách rời, nhưng không chấp nhận hành động đính kèm.

Tôi có bị thiếu quyền hoặc thuộc tính dữ liệu hay gì đó tương tự không? Hướng dẫn và các mẫu không nói bất cứ điều gì về các thuộc tính cần thiết bổ sung.

Dưới đây là file manifest:

<?xml version="1.0" encoding="utf-8"?> 
<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    package="de.visira.smartfdr" 
    android:versionCode="1" 
    android:versionName="1.0"> 

<uses-sdk android:minSdkVersion="12" /> 
<uses-feature android:name="android.hardware.usb.host" /> 

<application android:icon="@drawable/icon" android:label="@string/app_name"> 


    <receiver android:name=".usb.Detector"> 
     <intent-filter> 
      <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 
      <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" /> 
     </intent-filter> 

     <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" 
      android:resource="@xml/device_filter" /> 
     <meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" 
      android:resource="@xml/device_filter" /> 
    </receiver> 
</application> 

Và người nhận:

public class FDRDetector extends BroadcastReceiver{ 

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

    Toast.makeText(context, "Action: " + action, 3).show(); 
      // pops up only if action == DETACHED 
} 

Tôi không hiểu tại sao cùng một công trình ý định lọc, nếu tôi sử dụng chúng trên một hoạt động, nhưng không phải nếu chúng được áp dụng cho một người nhận? Ngay cả khi tôi thiết lập bộ thu và bộ lọc trong mã, các phần đính kèm không được nhận dạng.

môi trường My work: IDE: Eclipse 3.7 với Android Plugin

Device: Acer Iconia Tab A500

Android: 3.1

Cảm ơn trước

Trả lời

4

Tạo thu phát sóng trong phạm vi ứng dụng và không phải tệp kê khai, cho phép ứng dụng của bạn chỉ xử lý các sự kiện tách ra trong khi nó đang chạy. Bằng cách này, các sự kiện tách ra chỉ được gửi đến ứng dụng hiện đang chạy và không phát sóng tới tất cả các ứng dụng.

34

Aha! Tôi đã hiểu rồi. Tôi đã có cùng một vấn đề.

Ý chính của nó là - nếu ứng dụng của bạn tự động khởi chạy khi thiết bị được cắm vào (sử dụng tệp kê khai), thì hệ thống Android Android nhận được ý định ACTION_USB_DEVICE_ATTACHED và sau đó nó biết ứng dụng của bạn muốn chạy trong tình huống đó, nó thực sự gửi ứng dụng của bạn theo ý định android.intent.action.MAIN. Nó không bao giờ gửi hành động ACTION_USB_DEVICE_ATTACHED đến ứng dụng của bạn vì nó nghĩ rằng nó đã biết ứng dụng của bạn muốn làm gì trong tình huống đó.

chỉ bây giờ tôi đã xác định được vấn đề, và tôi nghĩ rằng tôi có một giải pháp, nhưng tôi có thể cho bạn biết những gì tôi đã tìm thấy:

Thậm chí nếu ứng dụng của bạn đang chạy và ở mặt trước, khi bạn cắm trong thiết bị USB và hệ thống Android nhận được ý định ACTION_USB_DEVICE_ATTACHED, nó sẽ gọi onResume() trong hoạt động của bạn.

Thật không may, bạn không thể chỉ làm điều này:

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

    Intent intent = getIntent(); 
    Log.d(TAG, "intent: " + intent); 
    String action = intent.getAction(); 

    if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { 
     //do something 
    } 
} 

Bởi vì mục đích sẽ trở lại như android.intent.action.MAIN, KHÔNG ACTION_USB_DEVICE_ATTACHED.

Một cách khó chịu, bạn cũng tải android.intent.action.MAIN nếu bạn chỉ thoát khỏi ứng dụng nhưng không rút phích cắm USB. Tôi tưởng tượng đưa thiết bị vào giấc ngủ và đánh thức nó trở lại sẽ làm điều tương tự. Vì vậy, từ những gì tôi đã tìm thấy, bạn không thể có được ý định trực tiếp, nhưng nó xuất hiện mà bạn có thể dựa vào onResume() được gọi khi thiết bị USB được cắm vào, vì vậy giải pháp là chỉ cần kiểm tra xem nếu USB được kết nối mỗi khi bạn nhận được một onResume. Bạn cũng có thể thiết lập cờ khi USB bị ngắt kết nối, vì tất nhiên ý định ngắt kết nối USB chỉ hoạt động tốt.

Vì vậy, trong tổng số, máy thu phát sóng của bạn có thể trông như thế này:

// BroadcastReceiver when remove the device USB plug from a USB port 
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { 
    public void onReceive(Context context, Intent intent) { 
     String action = intent.getAction(); 
     if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {     
     usbConnected=false;    
     } 
    } 
}; 

Bạn sẽ phải bên này onCreate:

// listen for new devices 
IntentFilter filter = new IntentFilter(); 
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 
registerReceiver(mUsbReceiver, filter); 

này đi bên trong thẻ hoạt động trong biểu hiện của bạn:

 <intent-filter> 
      <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 
     </intent-filter> 

     <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" 
      android:resource="@xml/device_filter" /> 

Bạn sẽ có tệp device_filter.xml trong thư mục/res/xml/trông giống như sau :

<?xml version="1.0" encoding="utf-8"?> 

<resources> 
    <usb-device vendor-id="1027" product-id="24577" /> 
    <usb-device vendor-id="1118" product-id="688" /> 
</resources> 

(tất nhiên với bất cứ nhà cung cấp ID và ID sản phẩm bạn cần)

Và sau đó onCreate của bạn trông giống như sau:

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

    Intent intent = getIntent(); 
    Log.d(TAG, "intent: " + intent); 
    String action = intent.getAction(); 


    if (usbConnected==false) { 
     //check to see if USB is now connected 
    } 
} 

Tôi không có mã cụ thể để kiểm tra để xem liệu USB có được kết nối như tôi thực sự chưa được khắc phục vào đó hay không. Tôi đang sử dụng một thư viện mà sẽ chỉ kết nối nếu nó có thể, vì vậy cho ứng dụng của tôi tôi chỉ có thể bắt đầu vòng lặp đó và tôi là tốt. Nó cũng có thể quan trọng để thiết lập launchmode của hoạt động của bạn trong manifest thành "singleTask" để ngăn chặn nó chạy lại khi nó đang chạy, hoặc người nào khác cắm vào một thiết bị USB sẽ chỉ khởi chạy một thể hiện thứ hai của ứng dụng của bạn!

Vì vậy, toàn bộ thẻ hoạt động của tôi trong manifest của tôi trông như thế này:

<activity 
     android:label="@string/app_name" 
     android:name="com.awitness.common.TorqueTablet" 
     android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" 
     android:screenOrientation="landscape" 
     android:configChanges="orientation|keyboardHidden" 
     android:launchMode="singleTask" 
     > 
     <intent-filter > 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.HOME"/> 
     <category android:name="android.intent.category.DEFAULT" /> 
     <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 

     <intent-filter> 
      <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 
     </intent-filter> 

     <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" 
      android:resource="@xml/device_filter" /> 

    </activity> 

Dù sao, tôi hy vọng điều này sẽ giúp người! Tôi đã rất ngạc nhiên khi tôi không thể tìm ra giải pháp cho điều này!

+4

Hãy thử ghi đè trênNewIntent() - nó được gọi khi bạn sử dụng android: launchMode = "singleTop" và có thể giải quyết tình huống của bạn khá độc đáo. onResume() luôn được gọi sau đó. – Gusdor

+0

Bạn có thể giải thích đoạn đầu tiên của bạn "Ý chính của nó là" không? Nó trông rất bối rối với tôi. –

+0

Cảm ơn, tôi đã tự hỏi điều tương tự. Tốt để biết đó là một cái gì đó mà không hoạt động. Mùi như một lỗi Android cho tôi. – Brian

6

Chỉ cần làm theo trên từ @ bình luận sâu sắc Gusdor của (1): Tôi thực hiện một kiểm tra trong onNewIntent() rằng, như @Gusdor chỉ ra, được gọi là khi hoạt động của bạn launchMode được thiết lập như singleTask hoặc singleTop. Sau đó, thay vì kiểm tra các cờ boolean như câu trả lời được chấp nhận cho thấy, chỉ cần chuyển mục đích đến bộ thu phát sóng USB của bạn bằng cách sử dụng LocalBroadcastManager.Ví dụ,

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 
    if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction())) { 
     LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 
    } 
} 

Sau đó, bất cứ nơi nào bạn đăng ký (hệ thống) phát sóng USB thu hiện tại của bạn, chỉ cần đăng ký người nhận cùng với một trường hợp quản lý phát thanh địa phương, ví dụ,

@Override 
protected void onResume() { 
    super.onResume(); 
    myContext.registerReceiver(myUsbBroadcastReceiver, myIntent); // system receiver 
    LocalBroadcastManager.getInstance(myContext).registerReceiver(myUsbBroadcastReceiver, intent); // local receiver 
} 

@Override 
protected void onPause() { 
    super.onResume(); 
    myContext.unregisterReceiver(myUsbBroadcastReceiver); // system receiver 
    LocalBroadcastManager.getInstance(myContext).unregisterReceiver(myUsbBroadcastReceiver); // local receiver 
} 

Bạn có thể gửi một hệ thống khác phát sóng thay vì phát sóng cục bộ, nhưng tôi không nghĩ rằng bạn có thể sử dụng hành động UsbManager.ACTION_USB_ACCESSORY_ATTACHED (hệ thống sẽ xem đó là nguy cơ bảo mật tiềm ẩn), vì vậy bạn phải xác định hành động của riêng mình. Không có vấn đề lớn, nhưng tại sao bận tâm, đặc biệt là không có chi phí IPC với các chương trình phát sóng địa phương.

Các vấn đề liên quan