public MapView(Context ctx, boolean allowNetAccess, int mode) {
    super(ctx);

    Display display;

    this.allowNetAccess = allowNetAccess;

    geoUtils = new GeoUtils(mode);

    setBackgroundColor(0xFF555570);
    display = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    scrWidth = display.getWidth();
    scrHeight = display.getHeight();
    setMinimumHeight(scrWidth);
    setMinimumWidth(scrHeight);
    tileWidth = (int) Math.ceil(scrWidth / 256.0) + 1;
    tileHeight = (int) Math.ceil(scrHeight / 256.0) + 1;
    gestureDetector = new GestureDetector(ctx, new GestureListener());

    zoomOutButton = new Button(ctx);
    zoomOutButton.setText("  -  ");
    zoomOutButton.setOnClickListener(this);

    zoomInButton = new Button(ctx);
    zoomInButton.setText("  +  ");
    zoomInButton.setOnClickListener(this);

    updateUI(true);
    addView(zoomOutButton);
    addView(zoomInButton);
  }
  private void updateLoader() {
    if (NavigineApp.Navigation == null) return;

    // Log.d(TAG, String.format(Locale.ENGLISH, "Update loader: %d", mLoader));

    long timeNow = DateTimeUtils.currentTimeMillis();
    if (mLoader < 0) return;

    int status = LocationLoader.checkLocationLoader(mLoader);
    if (status < 100) {
      if ((Math.abs(timeNow - mLoaderTime) > LOADER_TIMEOUT / 3 && status == 0)
          || (Math.abs(timeNow - mLoaderTime) > LOADER_TIMEOUT)) {
        mListView.setVisibility(View.GONE);
        mStatusLabel.setVisibility(View.VISIBLE);
        mStatusLabel.setText("Loading timeout!\nPlease, check your internet connection!");
        Log.d(TAG, String.format(Locale.ENGLISH, "Load stopped on timeout!"));
        LocationLoader.stopLocationLoader(mLoader);
        mLoader = -1;
      } else {
        mListView.setVisibility(View.GONE);
        mStatusLabel.setVisibility(View.VISIBLE);
        mStatusLabel.setText(String.format(Locale.ENGLISH, "Loading content (%d%%)", status));
      }
    } else {
      Log.d(TAG, String.format(Locale.ENGLISH, "Load finished with result: %d", status));
      LocationLoader.stopLocationLoader(mLoader);
      mLoader = -1;

      if (status == 100) {
        parseMapsXml();
        if (mInfoList.isEmpty()) {
          mListView.setVisibility(View.GONE);
          mStatusLabel.setVisibility(View.VISIBLE);
          mStatusLabel.setText("No locations available");
        } else {
          mListView.setVisibility(View.VISIBLE);
          mStatusLabel.setVisibility(View.GONE);
        }
      } else {
        mListView.setVisibility(View.GONE);
        mStatusLabel.setVisibility(View.VISIBLE);
        mStatusLabel.setText("Error loading!\nPlease, check your ID!");
      }
    }
  }
        public void run() {
          if (NavigineApp.Navigation == null) return;

          long timeNow = DateTimeUtils.currentTimeMillis();

          String userHash = NavigineApp.Settings.getString("user_hash", "");
          if (userHash.length() == 0) return;

          if (mLoader >= 0) updateLoader();

          if (Math.abs(timeNow - mUpdateLocationLoadersTime) > 1000) updateLocationLoaders();
        }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    measureChildren(widthMeasureSpec, heightMeasureSpec);
    int specModeW = MeasureSpec.getMode(widthMeasureSpec);
    int specSizeW = MeasureSpec.getSize(widthMeasureSpec);

    int specModeH = MeasureSpec.getMode(heightMeasureSpec);
    int specSizeH = MeasureSpec.getSize(heightMeasureSpec);
    int maxWidth = specSizeW;
    int maxHeight = specSizeH;
    int maxChildHeight = 0;
    int totalWidth = mOffsetLeft;

    for (int i = 0; i < getChildCount(); i++) {
      View child = getChildAt(i);
      final ViewGroup.MarginLayoutParams lp =
          (ViewGroup.MarginLayoutParams) child.getLayoutParams();

      int vHeight = child.getMeasuredHeight() + lp.bottomMargin + lp.topMargin;
      int vWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
      maxChildHeight = Math.max(maxChildHeight, vHeight);
      totalWidth += vWidth;
    }

    ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
    totalWidth += lp.leftMargin + lp.rightMargin;

    maxChildHeight += lp.topMargin + lp.bottomMargin;

    if (specModeH == MeasureSpec.UNSPECIFIED) {
      maxHeight = maxChildHeight;
    } else if (specModeH == MeasureSpec.AT_MOST) {
      maxHeight = Math.min(maxHeight, maxChildHeight);
    }

    maxWidth = Math.max(specSizeW, totalWidth);
    setMeasuredDimension(maxWidth, maxHeight);
  }
  private void updateLocationLoaders() {
    if (NavigineApp.Navigation == null) return;

    long timeNow = DateTimeUtils.currentTimeMillis();
    mUpdateLocationLoadersTime = timeNow;

    synchronized (mLoaderMap) {
      Iterator<Map.Entry<String, LoaderState>> iter = mLoaderMap.entrySet().iterator();
      while (iter.hasNext()) {
        Map.Entry<String, LoaderState> entry = iter.next();

        LoaderState loader = entry.getValue();
        if (loader.state < 100) {
          loader.timeLabel = timeNow;
          if (loader.type == DOWNLOAD) loader.state = LocationLoader.checkLocationLoader(loader.id);
          if (loader.type == UPLOAD) loader.state = LocationLoader.checkLocationUploader(loader.id);
        } else if (loader.state == 100) {
          String archivePath = NavigineApp.Navigation.getArchivePath();
          String locationFile =
              LocationLoader.getLocationFile(NavigineApp.AppContext, loader.location);
          if (archivePath != null && archivePath.equals(locationFile)) {
            Log.d(TAG, "Reloading archive " + archivePath);
            if (NavigineApp.Navigation.loadArchive(archivePath)) {
              SharedPreferences.Editor editor = NavigineApp.Settings.edit();
              editor.putString("map_file", archivePath);
              editor.commit();
            }
          }
          if (loader.type == DOWNLOAD) LocationLoader.stopLocationLoader(loader.id);
          if (loader.type == UPLOAD) LocationLoader.stopLocationUploader(loader.id);
          iter.remove();
        } else {
          // Load failed
          if (Math.abs(timeNow - loader.timeLabel) > 5000) {
            if (loader.type == DOWNLOAD) LocationLoader.stopLocationLoader(loader.id);
            if (loader.type == UPLOAD) LocationLoader.stopLocationUploader(loader.id);
            iter.remove();
          }
        }
      }
    }
    updateLocalVersions();
    mAdapter.updateList();
  }