2011-10-31 11 views
6

Widzę mojego wątku wywoływania zawiesza się w macierzystym kodu podczas wywoływania WifiManager.enableNetwork(). Do tej pory udało mi się odtworzyć to zawieszenie na tablecie Motorola Xoom z systemem Android 3.2.1. Testowałem na kilku innych telefonach i tabletach (wszystkie działające na Froyo lub Gingerbread) i nie widziałem problemu. Xoom jest jedynym dwurdzeniowym urządzeniem, które muszę przetestować (i odtworzyłem problem w 2 różnych Xoomach), więc mam wrażenie, że natknąłem się na bardzo subtelne wymagania dotyczące wątków w systemie Android, gdy współpracuję z WifiManager. Ślad stosu gdzie moje powołanie wątek wisi to:Wątek powiesić na WifiManager.enableNetwork()

BinderProxy.transact(int, Parcel, Parcel, int) line: not available [native method] 
    IWifiManager$Stub$Proxy.enableNetwork(int, boolean) line: 513 
    WifiManager.enableNetwork(int, boolean) line: 587 

Moja aplikacja próbuje połączyć się znanym punktem dostępowym WiFi, wykonać kilka testów, a następnie ponownie podłączyć urządzenie do swojego pierwotnego punktu dostępowego (jeśli był uprzednio połączony). Przed nawiązaniem połączenia sprawdziliśmy już, czy jest włączona sieć Wi-Fi i wykonaliśmy skanowanie w celu sprawdzenia, czy znaleziono identyfikator SSID punktu dostępowego. Ten kod, aby nawiązać połączenie działa w AsyncTask i wygląda mniej więcej tak:

... 
private WifiManager mWifiManager; 
private List<WifiConfiguration> mConfiguredNets = new ArrayList<WifiConfiguration>(); 
private Object mConnectMonitor = new Object(); 
private NetworkInfo.State mNetworkState = State.UNKNOWN; 

private final BroadcastReceiver mConnectionStateReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context inContext, final Intent inIntent) { 
     final String action = inIntent.getAction(); 
     if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { 
      NetworkInfo ni = 
       (NetworkInfo)inIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 
      State state = ni.getState(); 
      if (state == State.CONNECTED) { 
       synchronized (mConnectMonitor) { 
        mNetworkState = state; 
        mConnectMonitor.notify(); 
       } 
      } 
     } 
    } 
}; 

public void runninInAsyncTask(Context activityContext, int networkID) { 

    mWifiManager = (WifiManager)activityContext.getSystemService(Context.WIFI_SERVICE); 

    // Register our broadcast receiver to get network state change events 
    IntentFilter ifilter = new IntentFilter(); 
    ifilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 
    activityContext.registerReceiver(mConnectionStateReceiver, ifilter); 

    // Get a list of our currently configured networks so we can re-enable 
    // them after connecting to the desired network 
    mConfiguredNets = mWifiManager.getConfiguredNetworks(); 

    // Enable our network and disable all others 
    mWifiManager.enableNetwork(networkId, true); 

    // Start the reconnection process to connect to our desired network 
    synchronized (mConnectMonitor) { 
     mWifiManager.reconnect(); 
     mConnectMonitor.wait(60000); 
     if (mNetworkState != State.CONNECTED) { 
      Log.e(TAG, "Problems connecting to desired network!"); 
     } 
     else { 
      Log.e(TAG, "Successfully connected to desired network!"); 
     } 
    }    

    // Re-enable all of our previously configured networks 
    for (WifiConfiguration wifiConfig : mConfiguredNets) 
    {    
     if (wifiConfig.status != Status.ENABLED) { 
      mWifiManager.enableNetwork(wifiConfig.networkId, false); 
     } 
    }    
} 
... 

Kod ten został oparty na kodzie menu ustawień Wi-Fi w kodzie open source Android Gingerbread. Czy jest coś na temat wywoływania WifiManager.enableNetwork(), którego mi brakuje? Czy musi być uruchamiany w określonym wątku? Próbowałem upewnić się, że funkcja enableNetwork() jest wywoływana w wątku UI (przenosząc logikę do odbiornika transmisji). To wydawało się trochę pomóc, ale wciąż byłem w stanie odtworzyć powieszenie. Może to jest coś charakterystycznego dla Honeycomb? Obecnie te 2 Xoomy są jedynymi urządzeniami Honeycomb, które mam do przetestowania, więc są to jedyne punkty danych, które mam.

G

+0

Czy to szczęście? Mam ten sam problem. Po prostu znalazłem informację, że być może zamiast tego powinienem użyć connectNetwork, ale nie ma jeszcze oficjalnego AIDL, więc musiałbyś to zhakować :( – pprzemek

+0

Tak, musiałem to zrobić. Użyłem refleksji aby uzyskać dostęp do "ukrytego" "API (tylko dla Honeycomb i późniejszych) i nigdy nie miałem problemu od. –

+0

Podniosłem [zgłoszenie błędu] (http://code.google.com/p/android/issues/detail?id=34070). –

Odpowiedz

1

To jest rzeczywiście problem firmware specyficzne 3. * (wydaje się).

Widziałem to na Asus Transformer TF101 i Sony Tablet S (oba z 3. *, które było jakiś czas temu).

Począwszy od wersji 3.0, dostępne są nowe interfejsy API do łączenia się z siecią Wi-Fi, które nie wymagają używania partycji enableNetwork (aby włączyć wszystkie sieci, ale bieżącą).

Więcej na tych interfejsów API, co mogę zebrać z kodu źródłowego 4.0:

  • Są one oznaczone „@hide”
  • Są one wykorzystywane przez aplikację Ustawienia
  • Są one nadal nie udokumentowano jak 4,1
  • Zmieniono nieco pomiędzy 3. i 4. * * wykonywania

Moja rada jest taka, aby spróbować i korzystanie z tych interfejsów API poprzez odbicie. Ponieważ są używane przez aplikację Ustawienia, działają.

+0

Nie jestem pewien, czy jest to problem z oprogramowaniem układowym, ponieważ z tego, co wiem, dzieje się w HTC Jetsream, Samsung Galaxy Tab 10.1, Asus RF101, Sony Tablet S i Motorola Xoom. Wygląda to na ogólny błąd w Honeycomb - Znalazłem wiele raportów w kwestiach Androida db wokół synchronizacji metody wifiManager.Wygląda na to, że Honeycomb nie może zsynchronizować usuwania, dodawania, włączania i zapisywania z wielu wątków. Zobacz [wydanie] (http://code.google.com/p/android/issues/detail?id=34070) –

Powiązane problemy