18

Próbuję włączyć nowy interfejs API Map Google do systemu Android w wersji 2 do aplikacji przy użyciu biblioteki pomocy systemu Android. Przeszedłem wiele iteracji, aby spróbować dostać się do pracy, a teraz zrezygnowałem i pomyślałem, że powinienem zapytać tutaj.Google Maps Android API v2 wyrzuca GooglePlayServicesNotAvailable wyjątek, nieaktualny, SupportMapFragment.getMap() zwraca null

Poszedłem do konsoli API, utworzyłem projekt, włączyłem Google Maps API v2 dla Androida, utworzyłem klucz debugujący zgodnie z wymaganiami i wkleiłem go do manifestu. Brak problemów z uwierzytelnianiem lub coś podobnego. Jestem pewien, że zrobiłem to dobrze.

W folderze Mój projekt libs wstawiam android-support-v4.jar (przez projekt prawym przyciskiem myszy-> Android-> Dodaj bibliotekę wsparcia ...). W Eclipse zrobiłem File-> Import-> Android-> Existing Android Code Into Workspace i zaimportowałem najnowszą wersję (rev 3) android-sdk/google/google_play_services/libproject/google-play-services_lib. Potem dodaje się go jako biblioteka zależność do mojego projektu (projekt prawym click> Ustawienia-> Android-> Dodaj go jako biblioteka uzależnienia od dołu

w moim manifest mam.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...> 
    <permission 
     android:name="myapp.permission.MAPS_RECEIVE" 
     android:protectionLevel="signature"/> 

    <All the uses-permission required like INTERNET, ACCESS_NETWORK_STATE, WRITE_EXTERNAL_STORAGE, FINE AND COARSE LOCATION, etc> 
    <uses-permission android:name="myapp.permission.MAPS_RECEIVE"/> 
    <uses-feature android:glEsVersion="0x00020000" android:required="true"/> 
    <application ...> 
     ... 
     <uses-library android:name="com.google.android.maps" /> 
     <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AI..."/> 
    </application> 

W moim mainview.xml mam:

<fragment 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/map" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    class="com.google.android.gms.maps.SupportMapFragment" /> 

teraz na MainView.java mam:

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 
import com.google.android.gms.maps.GoogleMap; 
import com.google.android.gms.maps.SupportMapFragment; 

public class MainView extends FragmentActivity ... { 
    private GoogleMap mMap; 

    @Override 
    protected void onResume() { 
     ... 
     Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.map); 
     SupportMapFragment mapFragment = (SupportMapFragment)fragment; 
     mMap = mapFragment.getMap(); 
     //PROBLEM: mMap is null here even though mapFragment is not 
    } 
} 

Potem tho ught pewnie trzeba zainicjować fragmenty więc dodałem w moim onCreate po ustawieniu widoku treści:

//Fragments 
FragmentManager manager = getSupportFragmentManager(); 
FragmentTransaction transaction = manager.beginTransaction(); 
transaction.add(R.id.map, SupportMapFragment.newInstance()); 
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
transaction.commit(); 

Wtedy powiedziałem, może to nie SupportMapFragment ale faktycznie powinna odnosić się do rzeczywistego fragmentu, aw moim onResume I wykonano:

Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.map); 
SupportMapFragment mapFragment = (SupportMapFragment)fragment; 

//Fragments 
FragmentManager manager = getSupportFragmentManager(); 
FragmentTransaction transaction = manager.beginTransaction(); 
transaction.add(R.id.map, mapFragment); 
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
transaction.commit(); 

mMap = mapFragment.getMap(); 

mMap ponownie jest pusty.

Potem zobaczyłem, że jest klasa MapsInitializer, więc pomyślałem, że najpierw powinienem to zrobić.

Więc dodaniu kodu przed uzyskaniem fragmentu w powyższym kodzie:

try { 
    MapsInitializer.initialize(this); 
} catch (GooglePlayServicesNotAvailableException e) { 
    e.printStackTrace(); 
} 

Dzięki tej logcat zgłoszone ostrzeżenie (linia 313 jest MapsInitializer.initialize(this)):

com.google.android.gms.common.GooglePlayServicesNotAvailableException 
    at com.google.android.gms.internal.n.c(Unknown Source) 
    at com.google.android.gms.internal.n.a(Unknown Source) 
    at com.google.android.gms.maps.MapsInitializer.initialize(Unknown Source) 
    at myapp.activities.MainView.inflateSelectedViewAndSetData(MainView.java:313) 
    at myapp.activities.MainView.onClick(MainView.java:642) 
    at android.view.View.performClick(View.java:3153) 
    at android.view.View$PerformClick.run(View.java:12148) 
    at android.os.Handler.handleCallback(Handler.java:587) 
    at android.os.Handler.dispatchMessage(Handler.java:92) 
    at android.os.Looper.loop(Looper.java:152) 
    at android.app.ActivityThread.main(ActivityThread.java:4615) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:491) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599) 
    at dalvik.system.NativeStart.main(Native Method) 

Przez moich prób Logcat zgłasza następujące ostrzeżenie:

Google Play services out of date. Requires 2010100 but found 1013 

To może być a/winowajca, ale nie znalazłem rozwiązania.

W tym momencie nie mam pomysłów. Przeczytałem kilka wątków here, here, here, ale żadna z sugestii nie rozwiązała problemu. W tym ostatnim przypadku sugerują, że nie uwzględniają zależności projektu i tylko dołączają plik jar. Cóż, to nie zadziałało, albo używając google-play-services.jar z folderu google-play-services_lib/libs, albo eksportując własny jar z tego projektu.

Przy okazji używam rzeczywistego urządzenia (2.3.5 i tabletu z 3.2), a nie emulatora.

Każda pomoc doceniona z całego serca. :)

UPDATE:

Roztwór poniżej w qubitu.

Jak daleko eksportu zależność biblioteka, zgrabny sposób, aby nie miały do ​​czynienia z tym (co jest uciążliwe gdy ma do czynienia z repozytoriów) jest użycie FatJar i wyeksportować projekt google_play_services_lib (co nie utworzyć lokalną kopię z ponieważ po aktualizacji nie chcę ponownie importować) i dołączyć plik wyjściowy słoika tłuszczu do projektu jako inny plik jar. UWAGA: Wybierając pliki jar, które mają być dołączone do słoika, musiałem wykluczyć plik annotations.jar, ponieważ był on już wstępnie dołączony i powodował błędy podczas duplikowania. Teraz wszystko, co muszę zrobić, to dołączyć google_play_services_rev_3.jar do folderu mojego projektu libs i jestem gotowy do pracy.

+0

Ponieważ nie jest to odpowiedź na Twój problem, dam to tylko jako komentarz: gdy nie chcesz robić więcej niż lokalizacji opartej na GPS/WLAN, pokazywanie map, rysowanie na pokazanych mapach I "Zaleca się używanie klas z http://sourceforge.net/projects/libwlocate/. IMHO są znacznie łatwiejsze w obsłudze i zapewniają wsparcie dla kilku typów map. – Elmi

+0

To "google_play_services_rev_3.jar" powinno być ogólne, tak samo działa dla każdego projektu i konfiguracji, jak przypuszczam?Dzięki za podpowiedź FatJar, mam teraz swój projekt pracujący w Jenkins CI z tą procedurą. – JaakL

+0

@JaakL Tak, jest to ogólne i można go zaimportować do dowolnego projektu. :) – iliask

Odpowiedz

5

Pobierz i zainstaluj najnowszą wersję Google Play services ze Sklepu Play. Z jakiegoś powodu nie mogłem go znaleźć, szukając. Po uruchomieniu przykładowej aplikacji z SDK w folderze /extras/google/google_play_services/samples/maps zostałem poproszony o zainstalowanie aktualizacji i został on zabrany do Sklepu Play, aby to zrobić.

+0

Są instalowane domyślnie. To komercyjny (nierootowany) HTC Flyer i zrootowany HTC Desire S ma zainstalowane gappy (i usługi Google Play tam są). – iliask

+1

Potrzebujesz najnowszej wersji. Wysłany błąd dotyczy domyślnej wersji "zainstalowanej fabrycznie". – qubz

+2

Właśnie przeczytałem tutaj [http://code.google.com/p/gmaps-api-issues/issues/detail?id=4627#c1](http://code.google.com/p/gmaps- api-issues/issues/detail? id = 4627 # c1), że dodanie nowego programu MapFragment do aktywnej strony uruchomi aktualizację. Może to być łatwiejsze niż skonfigurowanie przykładowej aplikacji do uruchomienia, jeśli masz już zbudowaną aplikację. – qubz

15

zgodnie z opisem na dole tego linku; http://developer.android.com/google/play-services/setup.html

i tutaj jest przykładowy kod, aby obsłużyć to poprawnie;

int checkGooglePlayServices = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext); 
    if (checkGooglePlayServices != ConnectionResult.SUCCESS) { 
    // google play services is missing!!!! 
    /* Returns status code indicating whether there was an error. 
    Can be one of following in ConnectionResult: SUCCESS, SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, SERVICE_DISABLED, SERVICE_INVALID. 
    */ 
     GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, mActivity, 1122).show(); 
    } 
6

Miałem ten sam problem w moim projekcie. Rozwiązanie jest bardzo proste po prostu obsłużyć możliwość, że ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); może zwrócić null. Jeśli poradzisz sobie z null, buid-in SupportMapFragment będzie obsługiwać błąd Google Play services out of date. i pokaże Ci informację o zlokalizowanej lokalizacji i przycisku aktualizacji serwisu Google Play, tak jak to, o czym @qubz mówi w przykładowym projekcie.

Kod z próbką:

@Override 
protected void onResume() { 
    super.onResume(); 
    setUpMapIfNeeded(); 
} 

/** 
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly 
* installed) and the map has not already been instantiated.. This will ensure that we only ever 
* call {@link #setUpMap()} once when {@link #mMap} is not null. 
* <p> 
* If it isn't installed {@link SupportMapFragment} (and 
* {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to 
* install/update the Google Play services APK on their device. 
* <p> 
* A user can return to this FragmentActivity after following the prompt and correctly 
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not have been 
* completely destroyed during this process (it is likely that it would only be stopped or 
* paused), {@link #onCreate(Bundle)} may not be called again so we should call this method in 
* {@link #onResume()} to guarantee that it will be called. 
*/ 
private void setUpMapIfNeeded() { 
    // Do a null check to confirm that we have not already instantiated the map. 
    if (mMap == null) { 
     // Try to obtain the map from the SupportMapFragment. 
     mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) 
       .getMap(); 
     // Check if we were successful in obtaining the map. 
     if (mMap != null) { 
      setUpMap(); 
     } 
    } 
} 

/** 
* This is where we can add markers or lines, add listeners or move the camera. In this case, we 
* just add a marker near Africa. 
* <p> 
* This should only be called once and when we are sure that {@link #mMap} is not null. 
*/ 
private void setUpMap() { 
    mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker")); 
} 

I wynik:

enter image description here

jako dokumentacja smutnym

GoogleMap można nabyć jedynie za pomocą GetMap(), gdy mapy bazowe system jest załadowany i istnieje ukryty widok w fragmencie. Ta klasa automatycznie inicjuje system map i widok; nie można jednak zagwarantować, kiedy będzie gotowa, ponieważ zależy to od dostępności pakietu APK usług Google Play. Jeśli GoogleMap nie jest dostępny, getMap() zwróci wartość null. SupportMapFragment

+0

trochę mylić, jak zadzwonić do aktualizacji dla aplikacji mapy, jak wspomniałeś o wywołaniu "Uzyskaj Google Play Service" –

+0

@AbdulWahab, jeśli będziesz obsługiwać możliwość ((SupportMapFragment) getSupportFragmentManager(). findFragmentById (R.id.map)). getMap(); może zwrócić null biblioteka usługi Google Play pokaże ekran aktualizacji insted z MapFragment – Lemberg

+0

hmmm, mam to, ekran aktualizacji jest natywnym wywołaniem z usługi Google Play Libraya, myślałem, że getMap() zwróci null następnie na niestandardową aktualizację przycisk jaki intent muszę przeanalizować, aby przejść do strony aktualizacji, jak to mamy: Intent viewIntent = new Intent ("android.intent.action.VIEW", Uri.parse ("http://www.stackoverflow.com/ ")); startActivity (viewIntent); –

Powiązane problemy