2013-10-27 2 views
4

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

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

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

FYI нет карт google api v3 в android, его в настоящее время на v2 – tyczj

+0

Извините, это было v3 из-за названия версии. Починил это. –

+0

любой способ исправить это исключение ?? –

ответ

7

Ну, мне удалось «исправить» эту проблему. На самом деле это не исправление, но, по крайней мере, я избегаю аварии в моем приложении, когда это исключение выбрано. То, что я сделал, это переопределить обработчик исключаемых исключений по умолчанию и подавить сбой приложения, когда это неперехваченное исключение. Авария произошла из-за исключения NullPointerException, и это всегда происходило на GLThread (должно быть из кода чертежа с Карт Google). Поэтому я проверяю, применяются ли все предварительные условия, и если да, я отправляю широковещательную рассылку с настраиваемым действием, чтобы я мог прослушивать эту трансляцию на фрагменте, на котором я использую Карту Google, заменяя свой 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 Fragment, зарегистрировать этот вещательный приемник перед добавив 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

Это работает для меня =) –

Смежные вопросы