Android谷歌地图崩溃

问题描述:

我有我的谷歌地图在我的应用程序之前工作。现在我已经添加了从我的PHP服务器获取的代码,现在它正在崩溃,我不知道为什么。我确信JSON是正确的。它应该做的是联系我的服务器,获取位置列表并使用标记在地图上输入它们。我也尝试在异步中做到这一点,但在搜索后发现我无法从后台更改UI。Android谷歌地图崩溃

MY MAP.JAVA

public class Map extends FragmentActivity implements OnInfoWindowClickListener 
{  
    private GoogleMap map; 
    private int zoomLevel = 10; 
    static JSONObject object =null; 

// flag for Internet connection status 
    Boolean isInternetPresent = false; 

    // Connection detector class 
    Connection cd; 

public boolean onCreateOptionsMenu(Menu menu) 
{ 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.mapnav, menu); 
     return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) 
{  
    switch (item.getItemId()) 
    { 
    case R.id.action_add: 
     // Single menu item is selected do something 
     // Ex: launching new activity/screen or show alert message 
     Toast.makeText(this, "Add place is Selected", Toast.LENGTH_SHORT).show(); 
     Intent A = new Intent(this, Add.class); 
     startActivity(A); 
     return true; 

    case R.id.action_events: 
     // Single menu item is selected do something 
     // Ex: launching new activity/screen or show alert message 
     Toast.makeText(this, "Events is Selected", Toast.LENGTH_SHORT).show(); 
     Intent E = new Intent(this, Events.class); 
     startActivity(E); 
     return true; 

    case R.id.action_map: 
     Toast.makeText(this, "Map is Selected", Toast.LENGTH_SHORT).show(); 
     Intent M = new Intent(this, Map.class); 
     startActivity(M); 
     return true; 

    case R.id.action_chat: 
     Toast.makeText(this, "Chat is Selected", Toast.LENGTH_SHORT).show(); 
     Intent c = new Intent(this, Chat.class); 
     startActivity(c); 
     return true; 

    case R.id.action_settings: 
     Toast.makeText(this, "Settings is Selected", Toast.LENGTH_SHORT).show(); 
     return true; 

    default: 
     return super.onOptionsItemSelected(item); 
    } 
}  

    protected void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.map_layout); 

    JsonParser jsonParser = new JsonParser(); 
    String json = jsonParser.getJSONFromUrl("http://www.mywebsite.com/test.json"); 

    if (json != null) 
    { 
     try 
     { 
      JSONObject parent = new JSONObject(json); 
      JSONArray eventDetails = parent.getJSONArray("maps"); 

      for(int i=0; i < eventDetails.length(); i++) 
      { 
       object = eventDetails.getJSONObject(i); 

       String getName = object.getString("name"); 
       String getAddy =object.getString("addy"); 
       String getHours = object.getString("hours"); 
       String getDesc = object.getString("desc"); 
       String getLat = object.getString("lat"); 
       String getLong = object.getString("long"); 

       Log.e("JSON", "> " + getName + getAddy + getHours + getDesc + getLat + getLong); 

       // creating connection detector class instance 
       cd = new Connection(getApplicationContext()); 

       try 
       { 
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 

        Criteria criteria = new Criteria(); 

        // Get name of best provider 
        String provider = locationManager.getBestProvider(criteria, true); 

        map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)) 
           .getMap(); 

        if (map!=null) 
        { 
         map.getUiSettings().setCompassEnabled(true); 
         map.setTrafficEnabled(true); 
         map.setMyLocationEnabled(true); 

         // My current location 
         Location myloc = locationManager.getLastKnownLocation(provider); 

         // Get latitude of current location 
         double latitude = myloc.getLatitude(); 
         // Get longitude of current location 
         double longitude = myloc.getLongitude(); 

         double lat = Double.valueOf(getLat); 
         double lng = Double.valueOf(getLong); 

         // create latlng 
         LatLng mylocation = new LatLng(latitude, longitude); 

         // Move the camera instantly to defaultLatLng. 
         map.moveCamera(CameraUpdateFactory.newLatLngZoom(mylocation, zoomLevel)); 

         LatLng location = new LatLng(lat, lng); 

         map.addMarker(new MarkerOptions().position(location) 
           .title(getName) 
           .snippet(getHours) 
           .icon(BitmapDescriptorFactory 
             .fromResource(R.drawable.icon))); 

         // map.setOnInfoWindowClickListener(this); 
        } 
       } 
       catch (NullPointerException e) 
       { 
        e.printStackTrace(); 
       } 
       } 
      } 
     catch (JSONException e) 
     { 
      // TODO Auto-generated catch block 
      Log.e("Json Error", "Error: " + e.toString()); 
       e.printStackTrace(); 
     } 
    } 
    } 

    @SuppressWarnings("deprecation") 
    public void showAlertDialog(Context context, String title, String message, Boolean status) { 
     AlertDialog alertDialog = new AlertDialog.Builder(context).create(); 

     // Setting Dialog Title 
     alertDialog.setTitle(title); 

     // Setting Dialog Message 
     alertDialog.setMessage(message); 

     // Setting alert dialog icon 
     alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail); 

     // Setting OK Button 
     alertDialog.setButton("OK", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) 
      { 
       Intent intent = new Intent(getApplicationContext(), Navigation.class); 

       startActivity(intent); 
      } 
     }); 

     // Showing Alert Message 
     alertDialog.show(); 
    } 

    @Override 
    public void onPause() 
    { 
       if (map != null) 
       { 
           map.setMyLocationEnabled(false); 
           map.setTrafficEnabled(false); 
       } 
       super.onPause(); 
    } 

    @Override 
    public void onInfoWindowClick(Marker marker) 
    { 
       Intent intent = new Intent(this, Map_layout.class); 
       intent.putExtra("snippet", marker.getSnippet()); 
       intent.putExtra("title", marker.getTitle()); 
       intent.putExtra("position", marker.getPosition()); 
       startActivity(intent); 
    } 

    private class PrefetchData extends AsyncTask<Void, Void, Void> 
    { 

     @Override 
     protected void onPreExecute() 
     { 
      super.onPreExecute();  
     } 

     @Override 
     protected Void doInBackground(Void... arg0) 
     { 
      return null; 
     } 
     } 
} 

MY logcat的

01-25 18:46:36.142: E/AndroidRuntime(7482): FATAL EXCEPTION: main 
01-25 18:46:36.142: E/AndroidRuntime(7482): Process: com.databasedemo, PID: 7482 
01-25 18:46:36.142: E/AndroidRuntime(7482): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.databasedemo/com.databasedemo.Map}: android.os.NetworkOnMainThreadException 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.ActivityThread.access$800(ActivityThread.java:135) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.os.Handler.dispatchMessage(Handler.java:102) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.os.Looper.loop(Looper.java:136) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.ActivityThread.main(ActivityThread.java:5017) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at java.lang.reflect.Method.invokeNative(Native Method) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at java.lang.reflect.Method.invoke(Method.java:515) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at dalvik.system.NativeStart.main(Native Method) 
01-25 18:46:36.142: E/AndroidRuntime(7482): Caused by: android.os.NetworkOnMainThreadException 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at java.net.InetAddress.lookupHostByName(InetAddress.java:385) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at java.net.InetAddress.getAllByName(InetAddress.java:214) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnec tionOperator.java:137) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at com.databasedemo.JsonParser.getJSONFromUrl(JsonParser.java:35) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at com.databasedemo.Map.onCreate(Map.java:97) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.Activity.performCreate(Activity.java:5231) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159) 
01-25 18:46:36.142: E/AndroidRuntime(7482):  ... 11 more 

// EDIT运行在后台...

public class Map extends FragmentActivity implements OnInfoWindowClickListener 
{  
    private GoogleMap map; 
    private int zoomLevel = 10; 
    static JSONObject object =null; 

// flag for Internet connection status 
    Boolean isInternetPresent = false; 

    // Connection detector class 
    Connection cd; 

public boolean onCreateOptionsMenu(Menu menu) 
{ 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.mapnav, menu); 
     return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) 
{  
    switch (item.getItemId()) 
    { 
    case R.id.action_add: 
     // Single menu item is selected do something 
     // Ex: launching new activity/screen or show alert message 
     Toast.makeText(this, "Add place is Selected", Toast.LENGTH_SHORT).show(); 
     Intent A = new Intent(this, Add.class); 
     startActivity(A); 
     return true; 

    case R.id.action_events: 
     // Single menu item is selected do something 
     // Ex: launching new activity/screen or show alert message 
     Toast.makeText(this, "Events is Selected", Toast.LENGTH_SHORT).show(); 
     Intent E = new Intent(this, Events.class); 
     startActivity(E); 
     return true; 

    case R.id.action_map: 
     Toast.makeText(this, "Map is Selected", Toast.LENGTH_SHORT).show(); 
     Intent M = new Intent(this, Map.class); 
     startActivity(M); 
     return true; 

    case R.id.action_chat: 
     Toast.makeText(this, "Chat is Selected", Toast.LENGTH_SHORT).show(); 
     Intent c = new Intent(this, Chat.class); 
     startActivity(c); 
     return true; 

    case R.id.action_settings: 
     Toast.makeText(this, "Settings is Selected", Toast.LENGTH_SHORT).show(); 
     return true; 

    default: 
     return super.onOptionsItemSelected(item); 
    } 
}  

    protected void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.map_layout); 
    new PrefetchData().execute(); 
    } 

    @SuppressWarnings("deprecation") 
    public void showAlertDialog(Context context, String title, String message, Boolean status) { 
     AlertDialog alertDialog = new AlertDialog.Builder(context).create(); 

     // Setting Dialog Title 
     alertDialog.setTitle(title); 

     // Setting Dialog Message 
     alertDialog.setMessage(message); 

     // Setting alert dialog icon 
     alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail); 

     // Setting OK Button 
     alertDialog.setButton("OK", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) 
      { 
       Intent intent = new Intent(getApplicationContext(), Navigation.class); 

       startActivity(intent); 
      } 
     }); 

     // Showing Alert Message 
     alertDialog.show(); 
    } 

    @Override 
    public void onPause() 
    { 
       if (map != null) 
       { 
           map.setMyLocationEnabled(false); 
           map.setTrafficEnabled(false); 
       } 
       super.onPause(); 
    } 

    @Override 
    public void onInfoWindowClick(Marker marker) 
    { 
       Intent intent = new Intent(this, Map_layout.class); 
       intent.putExtra("snippet", marker.getSnippet()); 
       intent.putExtra("title", marker.getTitle()); 
       intent.putExtra("position", marker.getPosition()); 
       startActivity(intent); 
    } 

    private class PrefetchData extends AsyncTask<Void, Void, Void> 
    { 

     @Override 
     protected void onPreExecute() 
     { 
      super.onPreExecute();  
     } 

     @Override 
     protected Void doInBackground(Void... arg0) 
     { 
      JsonParser jsonParser = new JsonParser(); 
      String json = jsonParser.getJSONFromUrl("http://www.mywebsite.com/test.json"); 

      if (json != null) 
      { 
       try 
       { 
        JSONObject parent = new JSONObject(json); 
        JSONArray eventDetails = parent.getJSONArray("maps"); 

        for(int i=0; i < eventDetails.length(); i++) 
        { 
         object = eventDetails.getJSONObject(i); 

         String getName = object.getString("name"); 
         String getAddy =object.getString("addy"); 
         String getHours = object.getString("hours"); 
         String getDesc = object.getString("desc"); 
         String getLat = object.getString("lat"); 
         String getLong = object.getString("long"); 

         Log.e("JSON", "> " + getName + getAddy + getHours + getDesc + getLat + getLong); 

         // creating connection detector class instance 
         cd = new Connection(getApplicationContext()); 

         try 
         { 
          LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 

          Criteria criteria = new Criteria(); 

          // Get name of best provider 
          String provider = locationManager.getBestProvider(criteria, true); 

          map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)) 
             .getMap(); 

          if (map!=null) 
          { 
           map.getUiSettings().setCompassEnabled(true); 
           map.setTrafficEnabled(true); 
           map.setMyLocationEnabled(true); 

           // My current location 
           Location myloc = locationManager.getLastKnownLocation(provider); 

           // Get latitude of current location 
           double latitude = myloc.getLatitude(); 
           // Get longitude of current location 
           double longitude = myloc.getLongitude(); 

           double lat = Double.valueOf(getLat); 
           double lng = Double.valueOf(getLong); 

           // create latlng 
           LatLng mylocation = new LatLng(latitude, longitude); 

           // Move the camera instantly to defaultLatLng. 
           map.moveCamera(CameraUpdateFactory.newLatLngZoom(mylocation, zoomLevel)); 

           LatLng location = new LatLng(lat, lng); 

           map.addMarker(new MarkerOptions().position(location) 
             .title(getName) 
             .snippet(getHours) 
             .icon(BitmapDescriptorFactory 
               .fromResource(R.drawable.icon))); 

           // map.setOnInfoWindowClickListener(this); 
          } 
         } 
         catch (NullPointerException e) 
         { 
          e.printStackTrace(); 
         } 
         } 
        } 
       catch (JSONException e) 
       { 
        // TODO Auto-generated catch block 
        Log.e("Json Error", "Error: " + e.toString()); 
         e.printStackTrace(); 
       } 
      } 
      return null; 
     } 
     } 
} 

// LOG CAT运行在后台

01-25 18:58:20.042: E/AndroidRuntime(7593): FATAL EXCEPTION: AsyncTask #1 
01-25 18:58:20.042: E/AndroidRuntime(7593): Process: com.databasedemo, PID: 7593 
01-25 18:58:20.042: E/AndroidRuntime(7593): java.lang.RuntimeException: An error occured while executing doInBackground() 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at android.os.AsyncTask$3.done(AsyncTask.java:300) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.lang.Thread.run(Thread.java:841) 
01-25 18:58:20.042: E/AndroidRuntime(7593): Caused by: java.lang.IllegalStateException: Not on the main thread 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at maps.aq.o.b(Unknown Source) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at maps.ak.g.b(Unknown Source) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at maps.af.al.k(Unknown Source) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at clz.onTransact(SourceFile:304) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at android.os.Binder.transact(Binder.java:361) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a.getUiSettings(Unknown Source) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at com.google.android.gms.maps.GoogleMap.getUiSettings(Unknown Source) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at com.databasedemo.Map$PrefetchData.doInBackground(Map.java:198) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at com.databasedemo.Map$PrefetchData.doInBackground(Map.java:1) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at android.os.AsyncTask$2.call(AsyncTask.java:288) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
01-25 18:58:20.042: E/AndroidRuntime(7593):  ... 4 more 

如上所述,正确的方法是使用AsyncTask。 AsyncTask有3个关键组件,你需要两个。第三个是进展,这看起来并不像你需要的那样,因为你只做一个网络电话。您将使用这两个是:

  • doInBackground - 这是东西,需要很长的时间,如网络运营,应该发生。通常你会从这里找到一些东西传递给主线程,比如位图或字符串,或者甚至完全是其他东西。
  • onPostExecute - 这是用户界面的东西去的地方。 Android只允许一个线程访问UI,所有其他线程必须将内容传递给UI线程才能工作,或者在UI上进行操作。事实证明onPostExecute总是在UI线程上运行。

你需要做的就是弄清楚哪一块是网络连接,哪一块是UI操作,以及需要在它们之间流动以使其工作。 Android API docs展示了如何完成这项工作的一个例子。

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { 
    protected Long doInBackground(URL... urls) { 
     int count = urls.length; 
     long totalSize = 0; 
     for (int i = 0; i < count; i++) { 
      totalSize += Downloader.downloadFile(urls[i]); 
      publishProgress((int) ((i/(float) count) * 100)); 
      // Escape early if cancel() is called 
      if (isCancelled()) break; 
     } 
     return totalSize; 
    } 

    protected void onProgressUpdate(Integer... progress) { 
     setProgressPercent(progress[0]); 
    } 

    protected void onPostExecute(Long result) { 
     showDialog("Downloaded " + result + " bytes"); 
    } 
} 

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.databasedemo/com.databasedemo.Map}: android.os.NetworkOnMainThreadException 

您正在UI Thread上运行网络操作。由于API 11,您不能再在UI Thread上执行长时间运行的任务。你确实有一个AsyncTask,但你没有使用它。

在您更新的问题中,您使用的是AsyncTask,但您试图从背景Thread操纵UI元素。您应该使用AsyncTaskonPostExecute()来更新UI。

+0

但是,当我把它放在AsyncTask的背景上时,我也会得到错误。让我在后台运行它并发布该日志猫。 – Jayce

+1

这是因为你需要学习如何正确实现'AsyncTask'。 – Emmanuel

+0

看看我更新的答案。 – Emmanuel