2013-10-27 45 views
4

我一直在使用Google Maps API v2(版本3.2.25(761454-30))在我的Android應用程序上,有時甚至可以完美運行(有時每次都會更好經常)我得到一個NullPointerException。我對地圖沒有太大的不同,它發生在Nexus 4上,也發生在Nexus S上。我在gmaps-api-issues項目上發現了一個issue,雖然我沒有得到任何幫助那裏。我在這裏輸入問題,然後查看一些細節,看看是否有人已經完成了這項工作。Google Maps API v2上的隨機NullPointerException

正如我所說的,我沒有做任何與他們在API上的建議不同的東西,我認爲我可能做的唯一事情不是每個人都必須做的(這可能會導致一些問題,idk)是:

  • 我在另一個Fragment中使用SupportMapFragment,又名爲嵌套片段。我還使用了ActionBar Sherlock,所以其他片段就是SherlockFragment。
  • 我在我的Fragment的onCreateView上實例化SupportMapFragment(而不是將它放在XML上),然後將其添加到我的佈局的FrameLayout中。
  • 我在地圖上應用了一些Y翻譯(使用nineoldanroids),這樣我可以獲得接近Foursquare應用的效果(雖然我從來沒有在Foursquare上獲得過NPE)。
  • 我創建和應用清除一些標記作爲用戶的進展(應該不會吧,因爲這個錯誤發生在啓動時,在加載framgent)

這是多少呢,我不會把代碼放在這裏,因爲它不像它只是一個不起作用的代碼片段,但我已經列出了很多我正在做的事情。這裏是堆棧跟蹤(它總是幾乎相同):

java.lang.NullPointerException 
at java.nio.ReadWriteDirectByteBuffer.put(ReadWriteDirectByteBuffer.java:137) 
at java.nio.ShortToByteBufferAdapter.put(ShortToByteBufferAdapter.java:163) 
at maps.z.d.d(Unknown Source) 
at maps.z.d.a(Unknown Source) 
at maps.aq.a.a(Unknown Source) 
at maps.aq.ao.b(Unknown Source) 
at maps.aq.ao.a(Unknown Source) 
at maps.v.g.a(Unknown Source) 
at maps.v.g.b(Unknown Source) 
at maps.p.p.l(Unknown Source) 
at maps.p.p.run(Unknown Source) 
+0

僅供參考在Android中沒有谷歌地圖api v3,目前在v2 – tyczj

+0

對不起,認爲它是v3因爲版本名稱。修復。 –

+0

有什麼辦法解決這個異常? –

回答

7

嗯,我設法「解決」這個問題。這實際上並不是一個解決方案,但至少我在引發異常時避免了應用程序的崩潰。我所做的就是重寫默認的未捕獲異常處理程序,並在未捕獲的異常是這個時禁止崩潰應用程序。崩潰是因爲NullPointerException,它總是發生在GLThread上(必須來自Google Maps的繪圖代碼)。因此,我檢查是否所有的先決條件都適用,如果是的話,我會發送一個自定義操作的廣播,這樣我就可以在我使用Google Map的片段上收聽廣播,並在我得到一個時代替我的SupportMapFragment。由於我們遇到了未捕獲的異常,因此GLThread被中斷,並且Google地圖片段的繪圖被暫停,因此我們確實需要替換Google地圖片段以使地圖再次運行。

下面是代碼,我不得不補充:

在我的應用程序的onCreate:

final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread thread, Throwable ex) { 
     if (ex instanceof NullPointerException && thread.getName().startsWith("GLThread")) { 
      for (StackTraceElement stackTraceElement : ex.getStackTrace()) { 
       if (stackTraceElement.getClassName().contains("maps")) { 
        sendBroadcast(new Intent(ACTION_MAPS_NPE)); 
        return; 
       } 
      } 
     } 
     defaultHandler.uncaughtException(thread, ex); 
    } 
}); 

,然後在我的片段,它採用的是谷歌地圖的片段,我註冊這個廣播接收器加入前右SupportMapFragment對onCreateView佈局(和註銷它onDestroyView):

private class GoogleMapsNPEReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Fragment mapFragment = getChildFragmentManager().findFragmentById(R.id.map_fragment_container); 
     if (mapFragment != null) { 
      getChildFragmentManager().beginTransaction() 
        .replace(R.id.map_fragment_container, SupportMapFragment.newInstance()) 
        .commit(); 
      mMapInitialized = false; 
      // We won't have onResume to initialize our map anymore. Try to initialize it after 100ms. 
      final Handler handler = new Handler(); 
      handler.postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        if (getGoogleMap() == null) { 
         handler.postDelayed(this, 100); 
        } 
       } 
      }, 100); 
     } 
    } 
} 

希望這有助於與相同問題的人。如果有人有實際的解決方法,請讓我知道。

+0

這是一個很好的解決方法,因爲我們可以除此之外別無他法。我只會改變它使用事件總線而不是廣播。 –

+1

你是對的,廣播可能是一個矯枉過正的問題,甚至是不適合的。我修改我的代碼以使用本地廣播管理器,以便廣播不會離開我的流程/應用程序。使用事件總線會增加創建註冊/取消註冊方法的開銷,因爲我還沒有將任何事件總線庫包含到我的項目中,還有一些從上下文轉換到我的應用程序類,所以我認爲只需堅持廣播,儘管使用本地的廣播。 –

+0

這適用於我=) –

相關問題