谷歌地图Android API v2抛出GooglePlayServicesNotAvailableException,过时,SupportMapFragment.getMap()返回null

ili*_*ask 18 android google-maps android-support-library google-play-services google-maps-android-api-2

我正在尝试将新的Google Maps Android API v2合并到使用Android支持库的应用程序中.我已经经历了很多迭代,试图到某个地方工作,现在我已经放弃了,我想我应该在这里问.

我转到API控制台,创建了一个项目,为Android启用了Google Maps API v2,根据需要创建了一个调试KEY并将其粘贴到清单上.没有身份验证问题或类似的事情.很确定我做对了.

在我的项目libs文件夹中,我放置android-support-v4.jar(通过项目右键单击 - > Android->添加支持库...).在Eclipse中,我将File-> Import-> Android-> Existing Android Code To Intospace导入并导入最新的(rev 3)android-sdk/google/google_play_services/libproject/google-play-services_lib.然后我将它作为依赖库添加到我的项目中(项目右键单击 - >属性 - > Android->将其添加为底部的库依赖项.

在我的清单中我有:

<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>
Run Code Online (Sandbox Code Playgroud)

在我的mainview.xml中,我有:

<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" />
Run Code Online (Sandbox Code Playgroud)

现在在MainView.java上我有:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我想我可能需要初始化片段,所以我onCreate在设置内容视图后添加:

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

然后我说,也许不是,SupportMapFragment但我实际上应该参考实际的片段,并在我onResume做了:

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();
Run Code Online (Sandbox Code Playgroud)

mMap 在此之后再次为null.

然后我看到有一MapsInitializer堂课,所以我想也许我应该先打电话.

所以我在上面的代码中获取片段之前添加了代码:

try {
    MapsInitializer.initialize(this);
} catch (GooglePlayServicesNotAvailableException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

用这个Logcat报告了警告(第313行是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)
Run Code Online (Sandbox Code Playgroud)

在我的整个尝试中,Logcat会报告以下警告:

Google Play services out of date.  Requires 2010100 but found 1013
Run Code Online (Sandbox Code Playgroud)

这可能是罪魁祸首,但我没有找到解决办法.

在这一点上,我没有想法.我看了几个线程这里,这里,这里却没有任何的建议,解决了这个问题.对于后者,他们建议不要包括项目依赖项,只包括jar文件.好吧,无论是google-play-services.jargoogle-play-services_lib/libs文件夹使用还是从该项目导出我自己的jar都无效.

顺便说一下,我在实际设备上运行(2.3.5和3.2的平板电脑),而不是模拟器.

任何帮助全心全意地赞赏.:)

更新:

量子比特下面的解决方案.

到目前为止导出库依赖项,一个不必处理它的简洁方法(这在处理存储库时很痛苦)是使用FatJar并导出google_play_services_lib项目(我没有创建本地副本,因为它更新时我不想重新导入),并在项目中包含tha输出fat jar文件作为另一个jar文件.注意:当选择要包含在胖罐中的jar文件时,我必须排除该annotations.jar文件,因为它已经预先包含并导致重复错误.现在我所要做的就是google_play_services_rev_3.jar在我项目的libs文件夹中包含,我很高兴.

gul*_*yuz 15

如该链接底部所述; http://developer.android.com/google/play-services/setup.html

这里有样本代码来正确处理这个问题;

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();
    }
Run Code Online (Sandbox Code Playgroud)


Rom*_*ych 6

我的项目遇到了同样的问题.解决方案非常简单,只需处理((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();可以返回的可能性null.如果您将处理null该buid-in SupportMapFragment将处理Google Play services out of date.错误,并将向您显示地图本地化消息和用于更新Google Play服务的按钮,就像@qubz在示例项目中讲述的那样.

样本代码:

@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"));
}
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

由于文件伤心

只有在加载基础地图系统并且片段中的基础视图存在时,才能使用getMap()获取GoogleMap.该类自动初始化地图系统和视图; 但是,当它准备就绪时,您无法保证,因为这取决于Google Play服务APK的可用性.如果GoogleMap不可用,则getMap()将返回null.SupportMapFragment


qub*_*ubz 5

Google Play services从Play商店下载并安装最新版本.出于某种原因,我无法通过搜索找到它.通过从文件夹中的SDK运行示例应用程序,/extras/google/google_play_services/samples/maps我被提示安装升级并被带到Play商店执行此操作.

  • 我刚看到这里[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)通过将新的MapFragment添加到活动页面将触发更新.如果您已经构建了应用程序,这可能比配置示例应用程序更容易运行. (2认同)
  • 作为访问者的一般参考,本页的后半部分概述了Google Play服务APK安装方案以及如何处理它们.[http://developer.android.com/google/play-services/setup.html](http://developer.android.com/google/play-services/setup.html) (2认同)