2011-08-08 13 views
33

प्राप्त नहीं करता है मैंने संलग्न और अलग यूएसबी डिवाइस का पता लगाने के लिए the description and samples for USB host at developer.android.com के माध्यम से काम किया।एंड्रॉइड 3.1 यूएसबी-होस्ट - ब्रॉडकास्ट रिसीवर यूएसबी_DEVICE_ATTACHED

यदि मैं डिवाइस संलग्न होने पर अपना एप्लिकेशन शुरू करने के लिए मैनिफेस्ट फ़ाइल में एक इरादा-फ़िल्टर का उपयोग करता हूं, तो यह पूरी तरह से ठीक काम करता है: प्लग इन, डिवाइस का पता चला है, एंड्रॉइड एप्लिकेशन को शुरू करने की अनुमति मांगता है, डिवाइस की जानकारी प्रदर्शित होती है एक टेबल में

जो एप्लिकेशन मैं विकसित कर रहा हूं उसे केवल तब शुरू नहीं किया जाना चाहिए जब डिवाइस संलग्न/अलग हो (उदा। डेटा प्रबंधन उद्देश्यों)। मैं यह भी नहीं चाहता कि ऐप पहले से चल रहा है तो ओपन-डायलॉग पॉप अप करना चाहता है। इसलिए मैंने डिवाइस को संलग्न होने पर सीधे गतिविधि शुरू नहीं करने का फैसला किया, लेकिन एक ब्रॉडकास्ट रिसीवर पंजीकृत करने के लिए, जो (बाद में) डिवाइस को/अलग करने पर गतिविधि को सूचित करने के लिए माना जाता है। यह रिसीवर अलग-अलग कार्य को पहचानता है, लेकिन अटैचमेंट-एक्शन नहीं।

क्या मुझे अनुमति या डेटा विशेषता या ऐसा कुछ याद आ रहा है? ट्यूटोरियल और नमूने अतिरिक्त आवश्यक विशेषताओं के बारे में कुछ भी नहीं कहते हैं।

<?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> 

और रिसीवर:

यहाँ मैनिफ़ेस्ट फ़ाइल है

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 
} 

मुझे समझ नहीं आता क्यों एक ही मंशा फिल्टर काम करता है, अगर मैं उन पर उपयोग करें एक गतिविधि, लेकिन अगर वे एक रिसीवर पर लागू नहीं होते हैं? यहां तक ​​कि अगर मैं रिसीवर सेट करता हूं और कोड में फ़िल्टर करता हूं, तो अटैचमेंट पहचाने जाते हैं।

मेरे काम के माहौल: आईडीई ग्रहण 3.7 के साथ एंड्रॉयड प्लगइन

डिवाइस: एसर Iconia Tab A500

एंड्रॉयड: 3.1

अग्रिम धन्यवाद

उत्तर

4

भीतर प्रसारण रिसीवर बनाना एप्लिकेशन, और मैनिफेस्ट नहीं, आपके एप्लिकेशन को चलने के दौरान अलग-अलग ईवेंट को संभालने की अनुमति देता है। इस तरह, अलग-अलग घटनाएं केवल उस एप्लिकेशन को भेजी जाती हैं जो वर्तमान में चल रही है और सभी एप्लिकेशन पर प्रसारित नहीं होती है।

34

आह! मैं यह समझ गया। मुझे एक ही समस्या थी।

यह का सार है - अगर आप अपने आवेदन लांच स्वचालित रूप से जब एक डिवाइस में (मैनिफ़ेस्ट फ़ाइल का प्रयोग करके) खामियों को दूर किया जाता है, तो यह एंड्रॉयड प्रणाली ACTION_USB_DEVICE_ATTACHED आशय हो जाता है प्रकट होता है, और तब से यह आपके आवेदन को जानता है उस स्थिति में भागना चाहता है, यह वास्तव में आपके आवेदन को android.intent.action.MAIN इरादा भेजता है। यह आपके आवेदन में ACTION_USB_DEVICE_ATTACHED कार्रवाई कभी नहीं भेजता है क्योंकि ऐसा लगता है कि यह पहले से ही जानता है कि उस स्थिति में आपका एप्लिकेशन क्या करना चाहता है।

मैं अभी समस्या की पहचान की है, और मुझे लगता है कि मैं एक समाधान है, लेकिन मैं आपको बता सकता है कि मैं क्या पाया है:

यहां तक ​​कि अगर अपने अनुप्रयोग चल रहा है और अग्रभूमि में है, जब आप प्लग यूएसबी डिवाइस और एंड्रॉइड सिस्टम में ACTION_USB_DEVICE_ATTACHED इरादा मिलता है, यह आपकी गतिविधि में रेज़्यूम() पर कॉल करेगा।

दुर्भाग्य से, तुम सिर्फ यह नहीं कर सकता:

@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 
    } 
} 

क्योंकि आशय वापस आ जाएगा के रूप में android.intent.action.MAIN, नहीं ACTION_USB_DEVICE_ATTACHED।

एक परेशान, भी अगर आप ऐप छोड़ते हैं तो एंड्रॉइड.intent.action.MAIN प्राप्त करें, लेकिन यूएसबी अनप्लग न करें। मुझे लगता है कि डिवाइस को सोने के लिए डालना और इसे बैक अप करना वही काम करेगा।

तो जो मैंने पाया है, उससे आप सीधे इरादा नहीं प्राप्त कर सकते हैं, लेकिन ऐसा लगता है कि आप यूएसबी डिवाइस प्लग इन होने पर रेस्यूम() पर भरोसा कर सकते हैं, इसलिए समाधान सिर्फ जांचना है देखें कि हर बार जब आप ऑनस्यूम प्राप्त करते हैं तो यूएसबी कनेक्ट होता है या नहीं। यूएसबी डिस्कनेक्ट होने पर आप ध्वज भी सेट कर सकते हैं, क्योंकि निश्चित रूप से यूएसबी डिस्कनेक्ट इरादा सिर्फ ठीक है।

तो कुल में, अपने प्रसारण रिसीवर इस प्रकार दिखाई देंगे:

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

यह अपने मेनिफ़ेस्ट में गतिविधि टैग के अंदर चला जाता है:

// 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;    
     } 
    } 
}; 

आप onCreate के इस अंदर होगा:

 <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" /> 

आप अपने/res/xml/कि इस तरह दिखता है फ़ोल्डर में एक device_filter.xml फ़ाइल होगा :

<?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> 

और फिर अपने onCreate कुछ इस तरह दिखता (जो विक्रेता आईडी और उत्पाद के आईडी की जरूरत के साथ निश्चित रूप से):

@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 
    } 
} 

मैं जाँच के लिए विशिष्ट कोड नहीं है यह देखने के लिए कि क्या यूएसबी कनेक्ट है क्योंकि वास्तव में मैंने अभी तक इसका समाधान नहीं किया है। मैं एक लाइब्रेरी का उपयोग कर रहा हूं जो सिर्फ यह कनेक्ट कर सकता है, इसलिए मेरे आवेदन के लिए मैं बस उस लूप को शुरू कर सकता हूं और मैं अच्छा हूं।

मैनिफेस्ट में अपनी गतिविधि के लॉन्चमोड को "सिंगल टास्क" में सेट करना भी संभव है, इसे पहले से चलने पर इसे फिर से चलाने से रोकने के लिए, या फिर यूएसबी डिवाइस में प्लगिंग करने से आपके एप्लिकेशन का दूसरा उदाहरण लॉन्च होगा!

तो मेरी प्रकट में मेरी पूरी गतिविधि टैग इस तरह दिखता है: वैसे भी

<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> 

, मुझे आशा है कि यह किसी को मदद करता है! मुझे आश्चर्य हुआ कि मैं इसके लिए पहले से ही समाधान नहीं ढूंढ पाया!

+4

न्यूइन्टेंट() पर ओवरराइड करने का प्रयास करें - जब आप एंड्रॉइड का उपयोग करते हैं तो इसे लॉन्च किया जाता है: launchMode = "singleTop" और शायद आपकी स्थिति को काफी अच्छी तरह से हल करता है। onResume() हमेशा बाद में कहा जाता है। – Gusdor

+0

क्या आप अपना पहला पैराग्राफ समझा सकते हैं "इसका सारांश है"? यह मुझे बहुत उलझन में लग रहा है। –

+0

धन्यवाद, मैं वही बात सोच रहा हूं। यह जानना अच्छा है कि यह कुछ ऐसा नहीं है जो काम नहीं करता है। मुझे एक एंड्रॉइड बग की तरह बदबू आ रही है। – Brian

6

बस @ Gusdor व्यावहारिक टिप्पणी (+1) से पर पालन करने के लिए: मैं onNewIntent() में एक चेक कार्यान्वित के रूप में @Gusdor बताते हैं, जब अपनी गतिविधि launchModesingleTask या singleTop के रूप में सेट किया गया है कहा जाता है कि,। फिर, स्वीकृत उत्तर के रूप में बूलियन झंडे की जांच करने के बजाय, LocalBroadcastManager का उपयोग करके बस अपने यूएसबी प्रसारण रिसीवर के इरादे को पास करें।उदाहरण के लिए,

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

फिर, जहाँ भी आप अपने मौजूदा (प्रणाली) यूएसबी प्रसारण रिसीवर पंजीकृत कर रहे, सिर्फ एक ही रिसीवर एक स्थानीय प्रसारण प्रबंधक उदाहरण के साथ रजिस्टर, यानी,

@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 
} 

आप भेज सकते हैं स्थानीय प्रसारण की बजाए एक और सिस्टम प्रसारित होता है, लेकिन मुझे नहीं लगता कि आप UsbManager.ACTION_USB_ACCESSORY_ATTACHED (सिस्टम को संभावित सुरक्षा जोखिम के रूप में देखेंगे) का उपयोग करने में सक्षम होंगे, इसलिए आपको अपनी खुद की कार्रवाई को परिभाषित करना होगा। कोई बड़ा सौदा नहीं, लेकिन क्यों परेशान है, खासकर जब स्थानीय प्रसारण के साथ कोई आईपीसी ओवरहेड नहीं है।

संबंधित मुद्दे