docs: private void updateEstimate(boolean startJob) {
          try {
              if (cache_east != null &&
                      cache_west != null &&
                      cache_north != null &&
                      cache_south != null &&
                      zoom_max != null &&
                      zoom_min != null &&
                      cache_output!=null) {
                  double n = Double.parseDouble(cache_north.getText().toString());
                  double s = Double.parseDouble(cache_south.getText().toString());
                  double e = Double.parseDouble(cache_east.getText().toString());
                  double w = Double.parseDouble(cache_west.getText().toString());
                  if (startJob) {
                      String outputName = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "osmdroid" + File.separator + cache_output.getText().toString();
                      writer=new SqliteArchiveTileWriter(outputName);
                      try {
                          mgr = new CacheManager(mMapView, writer);
                      } catch (TileSourcePolicyException ex) {
                          Log.e(TAG, ex.getMessage());
                          return;
                      }
                  } else {
                      if (mgr==null) {
                          try {
                              mgr = new CacheManager(mMapView);
                          } catch (TileSourcePolicyException ex) {
                              Log.e(TAG, ex.getMessage());
                              return;
                          }
                      }
                  }
                  int zoommin = zoom_min.getProgress();
                  int zoommax = zoom_max.getProgress();
                  //nesw
                  BoundingBox bb= new BoundingBox(n, e, s, w);
                  int tilecount = mgr.possibleTilesInArea(bb, zoommin, zoommax);
                  cache_estimate.setText(tilecount + " tiles");
                  if (startJob)
                  {
                      if ( downloadPrompt!=null) {
                          downloadPrompt.dismiss();
                          downloadPrompt=null;
                      }
  
                      //this triggers the download
                      mgr.downloadAreaAsync(getActivity(), bb, zoommin, zoommax, new CacheManager.CacheManagerCallback() {
                          @Override
                          public void onTaskComplete() {
                              Toast.makeText(getActivity(), "Download complete!", Toast.LENGTH_LONG).show();
                              if (writer!=null)
                                  writer.onDetach();
                          }
  
                          @Override
                          public void onTaskFailed(int errors) {
                              Toast.makeText(getActivity(), "Download complete with " + errors + " errors", Toast.LENGTH_LONG).show();
                              if (writer!=null)
                                  writer.onDetach();
                          }
  
                          @Override
                          public void updateProgress(int progress, int currentZoomLevel, int zoomMin, int zoomMax) {
                              //NOOP since we are using the build in UI
                          }
  
                          @Override
                          public void downloadStarted() {
                              //NOOP since we are using the build in UI
                          }
  
                          @Override
                          public void setPossibleTilesInArea(int total) {
                              //NOOP since we are using the build in UI
                          }
                      });
                  }
  
              }
          }catch (Exception ex){
              //TODO something better?
              ex.printStackTrace();
          }
      }