Android Leaked Window – приложение принимает государство ANR

Я работаю с Android-приложение, которое использует карты Google. Приложение работает лучше всего. Я могу увидеть некоторые ошибки в logcat [ниже].

Logcat

08-28 15:37:36.945: E/WindowManager(21969): Activity com.kod.example.Find_Tab_MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40929cd8 that was originally added here 08-28 15:37:36.945: E/WindowManager(21969): android.view.WindowLeaked: Activity com.kod.example.Find_Tab_MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40929cd8 that was originally added here 08-28 15:37:36.945: E/WindowManager(21969): at android.view.ViewRoot.<init>(ViewRoot.java:263) 08-28 15:37:36.945: E/WindowManager(21969): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:171) 08-28 15:37:36.945: E/WindowManager(21969): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:114) 08-28 15:37:36.945: E/WindowManager(21969): at android.view.Window$LocalWindowManager.addView(Window.java:424) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.Dialog.show(Dialog.java:241) 08-28 15:37:36.945: E/WindowManager(21969): at com.kod.example.MyProgressDialog.show(MyProgressDialog.java:36) 08-28 15:37:36.945: E/WindowManager(21969): at com.kod.example.MyProgressDialog.show(MyProgressDialog.java:19) 08-28 15:37:36.945: E/WindowManager(21969): at com.kod.example.MyProgressDialog.show(MyProgressDialog.java:14) 08-28 15:37:36.945: E/WindowManager(21969): at com.kod.example.Find_Tab_MainActivity$LoadPlaces.onPreExecute(Find_Tab_MainActivity.java:129) 08-28 15:37:36.945: E/WindowManager(21969): at android.os.AsyncTask.execute(AsyncTask.java:391) 08-28 15:37:36.945: E/WindowManager(21969): at com.kod.example.Find_Tab_MainActivity.onCreate(Find_Tab_MainActivity.java:112) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.ActivityThread.access$1500(ActivityThread.java:117) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935) 08-28 15:37:36.945: E/WindowManager(21969): at android.os.Handler.dispatchMessage(Handler.java:99) 08-28 15:37:36.945: E/WindowManager(21969): at android.os.Looper.loop(Looper.java:130) 08-28 15:37:36.945: E/WindowManager(21969): at android.app.ActivityThread.main(ActivityThread.java:3687) 08-28 15:37:36.945: E/WindowManager(21969): at java.lang.reflect.Method.invokeNative(Native Method) 08-28 15:37:36.945: E/WindowManager(21969): at java.lang.reflect.Method.invoke(Method.java:507) 08-28 15:37:36.945: E/WindowManager(21969): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 08-28 15:37:36.945: E/WindowManager(21969): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625) 08-28 15:37:36.945: E/WindowManager(21969): at dalvik.system.NativeStart.main(Native Method) 

Что это за просочившееся окно? Мое приложение работает нормально, но иногда сбой, всегда вызывает эту ошибку.

Мой код

 package com.kod.example; import java.util.List; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.location.Address; import android.location.Geocoder; import android.os.AsyncTask; import android.os.Bundle; import android.widget.Button; import com.google.android.maps.MapActivity; public class Find_Tab_MainActivity extends MapActivity { // flag for Internet connection status Boolean isInternetPresent = false; Geocoder geocoder; String status; // Connection detector class ConnectionDetector cd; // Alert Dialog Manager AlertDialogManager alert = new AlertDialogManager(); // Google Places GooglePlaces googlePlaces; // Places List PlacesList nearPlaces; Place reference; // GPS Location GPSTracker gps; double latitude; double longitude; // Button Button loginbtn; Place p; Intent i; // Progress dialog ProgressDialog pDialog; final Context context = this; String type,KEY_KEYWORD,KEY_TAG; // KEY Strings public static String KEY_REFERENCE = "reference"; // id of the place public static String KEY_NAME = "name"; // name of the place public static String KEY_VICINITY = "vicinity"; public static String KEY_NUMBER = "formatted_phone_number"; // Place area name @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); cd = new ConnectionDetector(getApplicationContext()); Intent entent = getIntent(); type = entent.getExtras().getString("KEY_TYPES"); KEY_KEYWORD = entent.getExtras().getString("KEY_KEYWORD"); KEY_TAG = entent.getExtras().getString("KEY_TAG"); // Check if Internet present isInternetPresent = cd.isConnectingToInternet(); if (!isInternetPresent) { // Internet Connection is not present alert.showAlertDialog(Find_Tab_MainActivity.this, "Internet Connection Error", "Please connect to working Internet connection", false); // stop executing code by return return; } // creating GPS Class object gps = new GPSTracker(this); // check if GPS location can get if (gps.canGetLocation()) { } else { // Can't get user's current location alert.showAlertDialog(Find_Tab_MainActivity.this, "GPS Status", "Couldn't get location information. Please enable GPS", false); // stop executing code by return return; } // calling background Async task to load Google Places // After getting places from Google all the data is shown in listview new LoadPlaces().execute(); /** Button click event for shown on map */ } /** * Background Async Task to Load Google places * */ class LoadPlaces extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); MyProgressDialog.show(Find_Tab_MainActivity.this, "", ""); } /** * getting Places JSON * */ protected String doInBackground(String... args) { // creating Places class object googlePlaces = new GooglePlaces(); try { // Separeate your place types by PIPE symbol "|" // If you want all types places make it as null // Check list of types supported by google String types = type; // Listing places only for park // Radius in meters - increase this value if you don't find any places double radius = 10000; // 1000 meters if(KEY_TAG.equalsIgnoreCase("1")||KEY_TAG.equalsIgnoreCase("4")||KEY_TAG.equalsIgnoreCase("5")) { // get nearest places nearPlaces = googlePlaces.search(gps.getLatitude(),gps.getLongitude(), radius, types); } else if(KEY_TAG.equalsIgnoreCase("2")||KEY_TAG.equalsIgnoreCase("3")) { // get nearest places nearPlaces = googlePlaces.StreetGaragesearch(gps.getLatitude(), gps.getLongitude(), radius, types,KEY_KEYWORD); } else if(KEY_TAG.equalsIgnoreCase("6")) { String addressInput = type; geocoder = new Geocoder(Find_Tab_MainActivity.this); List<Address> address; address = geocoder.getFromLocationName(addressInput,1); if (address == null) { alert.showAlertDialog(Find_Tab_MainActivity.this, "Places Error", "Sorry error occured.", false); } else{ Address location = address.get(0); latitude = location.getLatitude(); longitude = location.getLongitude(); nearPlaces = googlePlaces.Keywordsearch(latitude,longitude,radius+40000,"parking",type); } // get nearest places } } catch (Exception e) { e.printStackTrace(); } return null; } /** * After completing background task Dismiss the progress dialoghis * and show the data in UI * Always use runOnUiThread(new Runnable()) to update UI from background * thread, otherwise you will get error * **/ @SuppressWarnings("deprecation") protected void onPostExecute(String file_url) { try{ // Get json response status status = nearPlaces.status; // updating UI from Background Thread runOnUiThread(new Runnable() { public void run() { if(status.equals("OK")){ // Successfully got places details i = new Intent(getApplicationContext(), MyPlacesMapActivity.class); // Sending user current geo location // passing near places to map activity i.putExtra("near_places", nearPlaces); //passing type to placemapactivity to identify the overlay icon i.putExtra("KEY_TAG", KEY_TAG); //passing place reference i.putExtra("place_reference", reference); // staring activity startActivity(i); } else if(status.equals("ZERO_RESULTS")){ // Zero results found final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("No Results"); // Setting Dialog Message alertDialog.setMessage("Sorry no places found. Try to change the location"); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } else if(status.equals("UNKNOWN_ERROR")) { final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("Error"); // Setting Dialog Message alertDialog.setMessage("Sorry unknown error occured."); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } else if(status.equals("OVER_QUERY_LIMIT")) { final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("Error"); // Setting Dialog Message alertDialog.setMessage("Sorry query limit to is reached"); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } else if(status.equals("REQUEST_DENIED")) { final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("Error"); // Setting Dialog Message alertDialog.setMessage("Sorry error occured. Request is denied"); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } else if(status.equals("INVALID_REQUEST")) { final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("Error"); // Setting Dialog Message alertDialog.setMessage("Sorry error occured. Invalid Request"); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } else { final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("Error"); // Setting Dialog Message alertDialog.setMessage("Sorry error occured."); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } } }); }catch(NullPointerException e){ final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle("Error"); // Setting Dialog Message alertDialog.setMessage("Requested place not found."); // Setting alert dialog icon alertDialog.setIcon(R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Find_Tab_MainActivity.this.finish(); } }); // Showing Alert Message alertDialog.show(); } } } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } } 

 What is this leaked window? 

WindowLeaked exception в вашем случае происходит, потому что вы не отклоняете MyProgressDialog до завершения операции. Следовательно, это утечка памяти, связанной с ней.

Общий случай:

WindowLeaked exception обычно происходит, когда у вас есть какая-то асинхронная задача, заканчивающаяся после WindowLeaked exception этой WindowLeaked exception Этот WindowLeaked exception возникает в случае, в основном, для Dialogs окон, где мы не отклоняли диалоговые окна до того, как контекст активности уничтожены.

Поэтому лучше поставить чек перед отображением диалога следующим образом:

 if(getActivity()!= null && !getActivity().isFinishing()){ Dialog.show(); } 

Решение вышеуказанной проблемы заключается в том, чтобы dismiss MyProgressDialog до завершения операции.

Измените свой код следующим образом:

 protected void onPostExecute(String file_url) { // your first line should be this if ( MyProgressDialog!=null && MyProgressDialog.isShowing() ){ MyProgressDialog.dismiss(); } // rest of the code } 

Там где-то есть проблема с Alert Dialog. Вы не отклоняете свой инициированный диалог нигде и не вызываете .dismiss() . Также для информации вам не нужно runOnUiThread внутри onPostExecute поскольку эта функция выполняется в самом потоке пользовательского интерфейса.

Вызовите функцию увольнения () в диалоговом окне, который вы создали, перед выходом из своей деятельности, например, в onPause ()