Случайное исключение NullPointerException в API Google Maps v2

Я работаю с Google Maps API v2 (версия 3.2.25 (761454-30)) в своем приложении для Android, и иногда он отлично работает, хотя иногда (который появляется каждый раз чаще). Я получаю исключение NullPointerException. Я не делаю ничего похожего на карту, и это произошло на некоторых Nexus 4, а также на Nexus S. Я нашел проблему в проекте gmaps-api-issues, хотя я не получаю никакой помощи от там. Затем я задаю вопрос с некоторыми подробностями, чтобы узнать, прошел ли кто-то через это.

Как я уже сказал, я не делаю ничего другого, как то, что они предлагают в API, и единственное, что я думаю, что я могу делать, что не каждый обязательно делает (и это может вызвать некоторые проблемы, idk):

  • Я использую SupportMapFragment внутри другого фрагмента, также как вложенный фрагмент. Я также использую ActionBar Sherlock, так что другой фрагмент – это SherlockFragment, чтобы просто сказать.
  • Я создаю экземпляр SupportMapFragment в onCreateView моего Fragment (вместо того, чтобы помещать его в XML), а затем добавляю его в FrameLayout на мой макет.
  • Я применяю некоторый перевод Y к карте (с девятью ящерами), так что я могу получить эффект, близкий к такому, как в приложении Foursquare (хотя у меня никогда не было NPE на Foursquare).
  • Я создаю и очищаю некоторые маркеры по мере того, как пользователь работает в приложении (это не должно быть, поскольку ошибка возникает при запуске, при загрузке фрейма)

Это много, я не буду вводить код здесь, так как он не похож на просто фрагмент, который не работает, но я перечислил многое из того, что я делаю. Вот трассировка стека (она всегда практически такая же):

java.lang.NullPointerException at java.nio.ReadWriteDirectByteBuffer.put(ReadWriteDirectByteBuffer.java:137) at java.nio.ShortToByteBufferAdapter.put(ShortToByteBufferAdapter.java:163) at maps.zdd(Unknown Source) at maps.zda(Unknown Source) at maps.aq.aa(Unknown Source) at maps.aq.ao.b(Unknown Source) at maps.aq.ao.a(Unknown Source) at maps.vga(Unknown Source) at maps.vgb(Unknown Source) at maps.ppl(Unknown Source) at maps.pprun(Unknown Source) 

Ну, мне удалось «исправить» эту проблему. На самом деле это не исправление, но, по крайней мере, я избегаю аварии в моем приложении, когда это исключение выбрано. Я сделал это, чтобы переопределить обработчик исключенных исключений по умолчанию и подавить сбой приложения, когда это неперехваченное исключение. Авария произошла из-за исключения NullPointerException, и это всегда происходило на GLThread (должно быть из кода чертежа с Карт Google). Поэтому я проверяю, применяются ли все предварительные условия, и если да, я отправляю широковещательную рассылку с настраиваемым действием, чтобы я мог прослушивать эту трансляцию на фрагменте, на котором я использую Google Map, заменяя свой SupportMapFragment, когда я его получаю. Поскольку у нас есть неперехваченное исключение, GLThread прерывается, а чертеж в Фрагмент Карт Google приостановлен, поэтому нам нужно заменить фрагмент Google Maps, чтобы карта снова работала.

Вот код, который я должен был добавить:

В моем приложении 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); } }); 

А затем на моем фрагменте, который использует фрагмент Google Maps, я зарегистрирую этот широковещательный приемник прямо перед добавлением 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); } } } 

Надеюсь, это поможет кому-то с той же проблемой. Если у кого-то есть фактическое исправление, пожалуйста, дайте мне знать.