title: AlertDialog show() giving WindowManager BadTokenException
body: <p>I'm getting a lot of reports of that exception on Google Play developer console, and I can't understand why, because I can't reproduce the error, it works perfectly on all my devices.</p>
  <p>This is the source code of my custom AlertDialog and the line of the crash is on the <code>show()</code> call at the end of the method. What is wrong?</p>
  <p>I checked some questions related here in Stack Overflow but I'm actually using <code>final</code> when declaring the dialog, which is the solution of other questions, and I'm still having the exception reports.</p>
  <pre><code>public static void showPoliciesDialog(final Activity activity, final Runnable runnable) {
      int sw = App.getInstance().getSmallSideSize();
      final int LIGHT_GRAY = 0xFFc7c7c7;
  
      final AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(activity, R.style.PolicyStyle));
      builder.setCancelable(false);
  
      LinearLayout ll = new LinearLayout(activity);
      ll.setPadding((int)(sw*0.025), 0, (int)(sw*0.025), 0);
      ll.setOrientation(LinearLayout.VERTICAL);
  
      final TextView title = new TextView(activity);
      LinearLayout.LayoutParams titleLP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT );
      titleLP.setMargins( Util.dpToPx(activity, 15), Util.dpToPx(activity, 15), Util.dpToPx(activity, 15), Util.dpToPx(activity, 15) );
      title.setLayoutParams(titleLP );
      title.setTextSize(18);
      title.setText(R.string.POLICY_TITLE);
      title.setTextColor(0xFF307282); // Blue color
      ll.addView(title);
  
      final CheckBox acceptCheckbox = new CheckBox(activity);
      acceptCheckbox.setTextColor(LIGHT_GRAY);
      acceptCheckbox.setText(R.string.I_WANT_DATA_COLLECT);
      acceptCheckbox.setLayoutParams( new ViewGroup.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) );
      acceptCheckbox.setVisibility(View.GONE);
      acceptCheckbox.setChecked(App.getInstance().retrieveBooleanValue(Constants.SEND_DATA_CHECKBOX, ConfigManager.getInstance().defaultStorable()));
      acceptCheckbox.setOnCheckedChangeListener(
          new CompoundButton.OnCheckedChangeListener() {
              @Override
              public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                  App.getInstance().storeBooleanValue(Constants.SEND_DATA_CHECKBOX, isChecked);
              }
          }
      );
      acceptCheckbox.setPadding(5,5,5,5);
  
      // Detects if the end of the web page has been reached &amp; in this case it shows the accept checkbox.
      // Based on http://stackoverflow.com/questions/10956443/android-making-a-button-visible-once-webview-is-done-scrolling
      // And on
      // [1] - http://stackoverflow.com/questions/10794647/detect-if-webview-scroll-reach-the-end
      // [2] - (To avoid use of an deprecated method) http://stackoverflow.com/questions/16079863/how-get-webview-scale-in-android-4
      final WebView policiesWebView = new WebView(activity){
          float currentScale = -1;
          {
              this.setWebViewClient(new WebViewClient(){
                  @Override public void onScaleChanged(WebView view, float oldScale, float newScale) {
                      super.onScaleChanged(view, oldScale, newScale);
                      currentScale = newScale;
                  }
              });
              this.getSettings().setJavaScriptEnabled(true);
          }
          @Override public void onScrollChanged(int l, int t, int oldl, int oldt) {
              // Only called on Android versions where onScaleChanged is not called
              if(currentScale == -1)
                  currentScale = this.getScale();
              int height = (int) Math.floor(this.getContentHeight() * currentScale);
              int webViewHeight = this.getHeight();
              int cutoff = height - webViewHeight - 10; // Don't be too strict on the cutoff point
              if (t &gt;= cutoff) {
                  // We need to know if it's necessary to show the accept checkbox. It should be visible only if it's not the first time that this dialog has been showed, so only
                  // if the policies have been accepted previously. if we have the key stored, then, it's not the first time this dialog is being showed, so we must show the accept checkbox
                  if(App.getInstance().containsKey(Constants.PRIVACY_POLICIES_ACCEPTED)){
                      acceptCheckbox.setVisibility(View.VISIBLE);
                  }
              }
          }
      };
  
      policiesWebView.loadUrl(ConfigManager.getInstance().getPrivacyUrl());
      LinearLayout.LayoutParams policiesWebViewLayoutParams =  new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,0);
      policiesWebViewLayoutParams.weight=1;
      policiesWebView.setLayoutParams(policiesWebViewLayoutParams);
      policiesWebView.setVisibility(View.GONE);
      ll.addView(policiesWebView);
      ll.addView(acceptCheckbox);
  
      final TextView readPolicies = new TextView(activity);
      LinearLayout.LayoutParams readPoliciesLP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
      readPoliciesLP.setMargins( Util.dpToPx(activity, 15), 0, Util.dpToPx(activity, 10), Util.dpToPx(activity, 30) );
      readPolicies.setPadding(0,0,0,Util.dpToPx(activity, 20));
      readPolicies.setTextColor(LIGHT_GRAY);
      readPolicies.setLayoutParams(readPoliciesLP);
      SpannableString content = new SpannableString(activity.getString(R.string.PLEASE_READ_POLICIES));
      content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
      readPolicies.setText(content);
      readPolicies.setTextSize(16);
      readPolicies.setGravity(Gravity.LEFT);
      readPolicies.setOnClickListener(new View.OnClickListener() {
          @Override public void onClick(View view) {
              title.setVisibility(View.GONE);
              policiesWebView.setVisibility(View.VISIBLE);
              readPolicies.setVisibility(View.GONE);
          }
      });
      ll.addView(readPolicies);
  
      // We need to know if we should treat this buttonas an agree button or a back button.
      // Agree mode: If it's the first time this dialog is being showed. Policies has not been accepted previously.
      // Back mode: If it's not the first time. The policies has been accepted previously.
      String buttonText = App.getInstance().containsKey(Constants.PRIVACY_POLICIES_ACCEPTED) == false ? activity.getString(R.string.AGREE) : activity.getString(R.string.BACK);
  
      builder.setPositiveButton(buttonText,
          new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialogInterface, int i) {
                  if(App.getInstance().containsKey(Constants.PRIVACY_POLICIES_ACCEPTED) == false) { //if agree mode
                      App.getInstance().storeBooleanValue(Constants.SEND_DATA_CHECKBOX, true);
                      App.getInstance().storeBooleanValue(Constants.PRIVACY_POLICIES_ACCEPTED, true);
                  }
  
                  dialogInterface.dismiss();
                  if(runnable != null)
                      runnable.run();
              }
          }
      );
  
      // We will show close app button only if it's the first time we show this dialog.
      if(App.getInstance().containsKey(Constants.PRIVACY_POLICIES_ACCEPTED) == false)
          builder.setNegativeButton(R.string.CLOSE_APP,
              new DialogInterface.OnClickListener() {
                  @Override
                  public void onClick(DialogInterface dialogInterface, int i) {
  
                      //launching navigator with non accept policies text
                      Intent intent = new Intent(Intent.ACTION_VIEW);
                      String url = &quot;https://myurl.com/no-terms.php?idApp={appId}&quot;;
                      url=GlobalVariablesManager.getInstance().replaceValues(url, false, false);
                      intent.setData(Uri.parse(URLParser.parse(url)));
                      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                      activity.startActivity(intent);
  
                      //App.getInstance().storeBooleanValue(Constants.PRIVACY_POLICIES_ACCEPTED, false);
                      SectionManager.getInstance().exit(false);
                      App.getInstance().clean();
                      activity.finish();
                  }
              }
          );
  
      builder.setView(ll);
      final AlertDialog dialog = builder.create();
      dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
  
      // This will set the color of negative button to a gray color
      dialog.setOnShowListener(new DialogInterface.OnShowListener() {
          @Override
          public void onShow(DialogInterface arg0) {
              Button buttonNegative = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
              buttonNegative.setTextColor(LIGHT_GRAY);
          }
      });
  
      dialog.show();
  }
  </code></pre>