【问题标题】:Android google map crashes安卓谷歌地图崩溃
【发布时间】:2014-01-25 23:51:17
【问题描述】:

我以前在我的应用程序上运行过我的谷歌地图。现在我已经添加了从我的 php 服务器获取的代码,现在它崩溃了,我不知道为什么。我已确保 JSON 是正确的。它应该做的是联系我的服务器,获取位置列表并使用标记在地图上输入它们。我也尝试在异步中执行此操作,但搜索后发现我无法从后台更改 UI。

我的 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;
        }
      }  
}

我的 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

// 编辑后台运行...

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;
         }
      }  
}

// 记录后台运行的猫

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

【问题讨论】:

    标签: android json google-maps


    【解决方案1】:

    如前所述,正确的方法是使用 AsyncTask。 AsyncTask 有 3 个关键组件,您需要其中的两个。第三个是进步,你似乎不需要,因为你只打了一个网络电话。您将使用的两个是:

    • doInBackground- 这是需要很长时间的事情,比如网络操作,应该发生的地方。通常你会从这里找到一些东西传递给主线程,比如位图或字符串,或者甚至可能完全是其他东西。
    • onPostExecute- 这是 UI 的地方。 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");
         }
     }
    

    【讨论】:

      【解决方案2】:
      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。

      【讨论】:

      • 但是当我把它放在 AsyncTask 的背景上时,我也得到了错误。让我在后台运行它并发布日志猫。
      • 那是因为你需要学习如何正确实现AsyncTask
      • doInBackground 中的网络操作,PostExecute 中的 UI。弄清楚两者之间需要传递什么才能使其正常工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多