private void updateViews() {
    if (!mDebugging) {
      mViewDebug.setVisibility(View.GONE);
      mLvDebug.setVisibility(View.GONE);

      if (mIsLoading && !mSharedPrefs.getBoolean("pref_disable_splash", false)) {
        mIitcWebView.setVisibility(View.GONE);
        mImageLoading.setVisibility(View.VISIBLE);
      } else {
        mIitcWebView.setVisibility(View.VISIBLE);
        mImageLoading.setVisibility(View.GONE);
      }
    } else {
      // if the debug container is invisible (and we are about to show it), select the text box
      final boolean select = mViewDebug.getVisibility() != View.VISIBLE;

      mImageLoading.setVisibility(View.GONE); // never show splash screen while debugging
      mViewDebug.setVisibility(View.VISIBLE);

      if (select) {
        mEditCommand.requestFocus();
        mEditCommand.selectAll();
      }

      if (mShowMapInDebug) {
        mBtnToggleMap.setImageResource(R.drawable.ic_action_view_as_list);
        mIitcWebView.setVisibility(View.VISIBLE);
        mLvDebug.setVisibility(View.GONE);
      } else {
        mBtnToggleMap.setImageResource(R.drawable.ic_action_map);
        mIitcWebView.setVisibility(View.GONE);
        mLvDebug.setVisibility(View.VISIBLE);
      }
    }
  }
  private void sendScreenshot() {
    Bitmap bitmap = mIitcWebView.getDrawingCache();
    if (bitmap == null) {
      mIitcWebView.buildDrawingCache();
      bitmap = mIitcWebView.getDrawingCache();
      if (bitmap == null) {
        Log.e("could not get bitmap!");
        return;
      }
      bitmap = Bitmap.createBitmap(bitmap);
      if (!mIitcWebView.isDrawingCacheEnabled()) mIitcWebView.destroyDrawingCache();
    } else {
      bitmap = Bitmap.createBitmap(bitmap);
    }

    try {
      final File cache = getExternalCacheDir();
      final File file = File.createTempFile("IITC screenshot", ".png", cache);
      if (!bitmap.compress(CompressFormat.PNG, 100, new FileOutputStream(file))) {
        // quality is ignored by PNG
        throw new IOException("Could not compress bitmap!");
      }
      startActivityForResult(
          ShareActivity.forFile(this, file, "image/png"),
          new ResponseHandler() {
            @Override
            public void onActivityResult(final int resultCode, final Intent data) {
              file.delete();
            }
          });
    } catch (final IOException e) {
      Log.e("Could not generate screenshot", e);
    }
  }
  @Override
  public void onConfigurationChanged(final Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    mNavigationHelper.onConfigurationChanged(newConfig);

    Log.d("configuration changed...restoring...reset idleTimer");
    mIitcWebView.loadUrl("javascript: window.idleTime = 0");
    mIitcWebView.loadUrl("javascript: window.renderUpdateStatus()");
  }
  // we want a self defined behavior for the back button
  @Override
  public void onBackPressed() {
    // exit fullscreen mode if it is enabled and action bar is disabled or the back stack is empty
    if (mIitcWebView.isInFullscreen() && mBackStack.isEmpty()) {
      mIitcWebView.toggleFullscreen();
      return;
    }

    // close drawer if opened
    if (mNavigationHelper.isDrawerOpened()) {
      mNavigationHelper.closeDrawers();
      return;
    }

    // kill all open iitc dialogs
    if (!mDialogStack.isEmpty()) {
      final String id = mDialogStack.pop();
      mIitcWebView.loadUrl(
          "javascript: "
              + "var selector = $(window.DIALOGS['"
              + id
              + "']); "
              + "selector.dialog('close'); "
              + "selector.remove();");
      return;
    }

    // Pop last item from backstack and pretend the relevant menu item was clicked
    if (!mBackStack.isEmpty()) {
      backStackPop();
      mBackButtonPressed = true;
      return;
    }

    if (mBackButtonPressed || !mSharedPrefs.getBoolean("pref_press_twice_to_exit", false)) {
      super.onBackPressed();
    } else {
      mBackButtonPressed = true;
      Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
      // reset back button after 2 seconds
      new Handler()
          .postDelayed(
              new Runnable() {
                @Override
                public void run() {
                  mBackButtonPressed = false;
                }
              },
              2000);
    }
  }
  @Override
  public void onSharedPreferenceChanged(
      final SharedPreferences sharedPreferences, final String key) {
    if (key.equals("pref_force_desktop")) {
      mDesktopMode = sharedPreferences.getBoolean("pref_force_desktop", false);
      mNavigationHelper.onPrefChanged();
    } else if (key.equals("pref_user_location_mode")) {
      final int mode = Integer.parseInt(mSharedPrefs.getString("pref_user_location_mode", "0"));
      if (mUserLocation.setLocationMode(mode)) mReloadNeeded = true;
      return;
    } else if (key.equals("pref_persistent_zoom")) {
      mPersistentZoom = mSharedPrefs.getBoolean("pref_persistent_zoom", false);
      return;
    } else if (key.equals("pref_fullscreen")) {
      mIitcWebView.updateFullscreenStatus();
      mNavigationHelper.onPrefChanged();
      return;
    } else if (key.equals("pref_android_menu")) {
      final String[] menuDefaults =
          getResources().getStringArray(R.array.pref_android_menu_default);
      mAdvancedMenu =
          mSharedPrefs.getStringSet(
              "pref_android_menu", new HashSet<String>(Arrays.asList(menuDefaults)));
      mNavigationHelper.setDebugMode(mAdvancedMenu.contains(R.string.menu_debug));
      invalidateOptionsMenu();
      // no reload needed
      return;
    } else if (key.equals("pref_fake_user_agent")) {
      mIitcWebView.setUserAgent();
    } else if (key.equals("pref_last_plugin_update")) {
      final Long forceUpdate = sharedPreferences.getLong("pref_last_plugin_update", 0);
      if (forceUpdate == 0) mFileManager.updatePlugins(true);
      return;
    } else if (key.equals("pref_update_plugins_interval")) {
      final int interval =
          Integer.parseInt(mSharedPrefs.getString("pref_update_plugins_interval", "7"));
      mFileManager.setUpdateInterval(interval);
      return;
    } else if (key.equals("pref_press_twice_to_exit")
        || key.equals("pref_share_selected_tab")
        || key.equals("pref_messages")
        || key.equals("pref_secure_updates")
        || key.equals("pref_external_storage")) {
      // no reload needed
      return;
    }

    mReloadNeeded = true;
  }
 @Override
 protected void onStop() {
   super.onStop();
   Log.d("stopping iitcm");
   mIitcWebView.loadUrl("javascript: window.idleSet();");
   mUserLocation.onStop();
 }
 public void reset() {
   mNavigationHelper.reset();
   mMapSettings.reset();
   mUserLocation.reset();
   mIitcWebView.getWebViewClient().reset();
   mBackStack.clear();
   mCurrentPane = Pane.MAP;
 }
  @Override
  protected void onStart() {
    super.onStart();

    if (mReloadNeeded) {
      Log.d("preference had changed...reload needed");
      reloadIITC();
    } else {
      // iitc is not fully booted...timer will be reset by the script itself
      if (findViewById(R.id.imageLoading).getVisibility() == View.GONE) {
        // enough idle...let's do some work
        Log.d("resuming...reset idleTimer");
        mIitcWebView.loadJS("(function(){if(window.idleReset) window.idleReset();})();");
      }
    }

    mUserLocation.onStart();
  }
  public void onBtnRunCodeClick(final View v) {
    final String code = mEditCommand.getText().toString();
    final JSONObject obj = new JSONObject();
    try {
      obj.put("code", code);
    } catch (final JSONException e) {
      Log.w(e);
      return;
    }

    // throwing an exception will be reported by WebView
    final String js =
        "(function(obj){var result;"
            + "console.log('>>> ' + obj.code);"
            + "try{result=eval(obj.code);}catch(e){if(e.stack) console.error(e.stack);throw e;}"
            + "if(result!==undefined) console.log(result.toString());"
            + "})("
            + obj.toString()
            + ");";

    mIitcWebView.loadJS(js);
  }
  private void loadScripts(final IITC_WebView view) {
    final List<String> scripts = new LinkedList<String>();

    // get the plugin preferences
    final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mIitc);
    final TreeMap<String, ?> all_prefs = new TreeMap<String, Object>(sharedPref.getAll());

    // iterate through all plugins
    for (final Map.Entry<String, ?> entry : all_prefs.entrySet()) {
      final String plugin = entry.getKey();
      if (plugin.endsWith(".user.js") && entry.getValue().toString().equals("true")) {
        if (plugin.startsWith(mIitcPath)) {
          scripts.add("user-plugin" + DOMAIN + plugin);
        } else {
          scripts.add("script" + DOMAIN + "/plugins/" + plugin);
        }
      }
    }

    // inject the user location script if enabled in settings
    if (Integer.parseInt(sharedPref.getString("pref_user_location_mode", "0")) != 0) {
      scripts.add("script" + DOMAIN + "/user-location.user.js");
    }

    scripts.add("script" + DOMAIN + "/total-conversion-build.user.js");

    final String js =
        "(function(){['"
            + TextUtils.join("','", scripts)
            + "'].forEach(function(src) {"
            + "var script = document.createElement('script');script.src = '//'+src;"
            + "(document.body || document.head || document.documentElement).appendChild(script);"
            + "});})();";

    view.loadJS(js);
  }
 // inject the iitc-script and load the intel url
 // plugins are injected onPageFinished
 public void loadUrl(String url) {
   reset();
   setLoadingState(true);
   url = addUrlParam(url);
   mIitcWebView.loadUrl(url);
 }
  @Override
  public boolean onOptionsItemSelected(final MenuItem item) {
    if (mNavigationHelper.onOptionsItemSelected(item)) return true;

    // Handle item selection
    final int itemId = item.getItemId();

    switch (itemId) {
      case android.R.id.home:
        switchToPane(Pane.MAP);
        return true;
      case R.id.reload_button:
        reloadIITC();
        return true;
      case R.id.toggle_fullscreen:
        mIitcWebView.toggleFullscreen();
        return true;
      case R.id.layer_chooser:
        mNavigationHelper.openRightDrawer();
        return true;
      case R.id.locate: // get the users current location and focus it on map
        switchToPane(Pane.MAP);

        if (mUserLocation.hasCurrentLocation()) {
          // if gps location is displayed we can use a better location without any costs
          mUserLocation.locate(mPersistentZoom);
        } else {
          // get location from network by default
          mIitcWebView.loadUrl(
              "javascript: window.map.locate({setView : true"
                  + (mPersistentZoom ? ", maxZoom : map.getZoom()" : "")
                  + "});");
        }
        return true;
      case R.id.action_settings: // start settings activity
        final Intent intent = new Intent(this, PreferenceActivity.class);
        try {
          intent.putExtra("iitc_version", mFileManager.getIITCVersion());
        } catch (final IOException e) {
          Log.w(e);
          return true;
        }
        startActivity(intent);
        return true;
      case R.id.menu_clear_cookies:
        final CookieManager cm = CookieManager.getInstance();
        cm.removeAllCookie();
        return true;
      case R.id.menu_send_screenshot:
        sendScreenshot();
        return true;
      case R.id.menu_debug:
        mDebugging = !mDebugging;
        updateViews();
        invalidateOptionsMenu();

        // TODO remove debugging stuff from JS?
        return true;
      default:
        return false;
    }
  }
 public void switchToPane(final Pane pane) {
   if (mDesktopMode) return;
   mIitcWebView.loadUrl("javascript: window.show('" + pane.name + "');");
 }
  @Override
  protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // enable progress bar above action bar
    requestWindowFeature(Window.FEATURE_PROGRESS);

    setContentView(R.layout.activity_main);
    mImageLoading = findViewById(R.id.imageLoading);
    mIitcWebView = (IITC_WebView) findViewById(R.id.iitc_webview);
    mLvDebug = (ListView) findViewById(R.id.lvDebug);
    mViewDebug = findViewById(R.id.viewDebug);
    mBtnToggleMap = (ImageButton) findViewById(R.id.btnToggleMapVisibility);
    mEditCommand = (EditText) findViewById(R.id.editCommand);
    mEditCommand.setOnEditorActionListener(
        new TextView.OnEditorActionListener() {
          @Override
          public boolean onEditorAction(
              final TextView v, final int actionId, final KeyEvent event) {
            if (EditorInfo.IME_ACTION_GO == actionId
                || EditorInfo.IME_ACTION_SEND == actionId
                || EditorInfo.IME_ACTION_DONE == actionId) {
              onBtnRunCodeClick(v);

              final InputMethodManager imm =
                  (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
              imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

              return true;
            }
            return false;
          }
        });

    mLvDebug.setAdapter(new IITC_LogAdapter(this));
    mLvDebug.setOnItemLongClickListener(this);

    // do something if user changed something in the settings
    mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    mSharedPrefs.registerOnSharedPreferenceChangeListener(this);

    // enable/disable mDesktopMode mode on menu create and url load
    mDesktopMode = mSharedPrefs.getBoolean("pref_force_desktop", false);

    // enable/disable advance menu
    final String[] menuDefaults = getResources().getStringArray(R.array.pref_android_menu_default);
    mAdvancedMenu =
        mSharedPrefs.getStringSet(
            "pref_android_menu", new HashSet<String>(Arrays.asList(menuDefaults)));

    mPersistentZoom = mSharedPrefs.getBoolean("pref_persistent_zoom", false);

    // get fullscreen status from settings
    mIitcWebView.updateFullscreenStatus();

    mFileManager = new IITC_FileManager(this);
    mFileManager.setUpdateInterval(
        Integer.parseInt(mSharedPrefs.getString("pref_update_plugins_interval", "7")));

    mUserLocation = new IITC_UserLocation(this);
    mUserLocation.setLocationMode(
        Integer.parseInt(mSharedPrefs.getString("pref_user_location_mode", "0")));

    // pass ActionBar to helper because we deprecated getActionBar
    mNavigationHelper = new IITC_NavigationHelper(this, super.getActionBar());

    mMapSettings = new IITC_MapSettings(this);

    // Clear the back stack
    mBackStack.clear();

    // receive downloadManagers downloadComplete intent
    // afterwards install iitc update
    registerReceiver(
        mBroadcastReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

    final NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
    if (nfc != null) nfc.setNdefPushMessageCallback(this, this);

    handleIntent(getIntent(), true);
  }
 @Override
 protected void onPause() {
   super.onPause();
   mIitcWebView.pauseTimers();
   mIitcWebView.onPause();
 }
 @Override
 protected void onResume() {
   super.onResume();
   mIitcWebView.resumeTimers();
   mIitcWebView.onResume();
 }
  private void handleGeoUri(final Uri uri) throws URISyntaxException {
    final String[] parts = uri.getSchemeSpecificPart().split("\\?", 2);
    Double lat = null, lon = null;
    Integer z = null;
    String search = null;

    // parts[0] may contain an 'uncertainty' parameter, delimited by a semicolon
    final String[] pos = parts[0].split(";", 2)[0].split(",", 2);
    if (pos.length == 2) {
      try {
        lat = Double.valueOf(pos[0]);
        lon = Double.valueOf(pos[1]);
      } catch (final NumberFormatException e) {
        lat = null;
        lon = null;
      }
    }

    if (parts.length > 1) { // query string present
      // search for z=
      for (final String param : parts[1].split("&")) {
        if (param.startsWith("z=")) {
          try {
            z = Integer.valueOf(param.substring(2));
          } catch (final NumberFormatException e) {
          }
        }
        if (param.startsWith("q=")) {
          search = param.substring(2);
          final Pattern pattern =
              Pattern.compile("^(-?\\d+(\\.\\d+)?),(-?\\d+(\\.\\d+)?)\\s*\\(.+\\)");
          final Matcher matcher = pattern.matcher(search);
          if (matcher.matches()) {
            try {
              lat = Double.valueOf(matcher.group(1));
              lon = Double.valueOf(matcher.group(3));
              search = null; // if we have a position, we don't need the search term
            } catch (final NumberFormatException e) {
              lat = null;
              lon = null;
            }
          }
        }
      }
    }

    if (lat != null && lon != null) {
      String url = mIntelUrl + "?ll=" + lat + "," + lon;
      if (z != null) {
        url += "&z=" + z;
      }
      loadUrl(url);
      return;
    }

    if (search != null) {
      if (mIsLoading) {
        mSearchTerm = search;
        loadUrl(mIntelUrl);
      } else {
        switchToPane(Pane.MAP);
        mIitcWebView.loadUrl("javascript:search('" + search + "');");
      }
      return;
    }

    throw new URISyntaxException(uri.toString(), "position could not be parsed");
  }
  // handles ingress intel url intents, search intents, geo intents and javascript file intents
  private void handleIntent(final Intent intent, final boolean onCreate) {
    final String action = intent.getAction();
    if (Intent.ACTION_VIEW.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
      final Uri uri = intent.getData();
      Log.d("intent received url: " + uri.toString());

      if (uri.getScheme().equals("http") || uri.getScheme().equals("https")) {
        if (uri.getHost() != null
            && (uri.getHost().equals("ingress.com") || uri.getHost().endsWith(".ingress.com"))) {
          Log.d("loading url...");
          loadUrl(uri.toString());
          return;
        }
      }

      if (uri.getScheme().equals("geo")) {
        try {
          handleGeoUri(uri);
          return;
        } catch (final URISyntaxException e) {
          Log.w(e);
          new AlertDialog.Builder(this)
              .setTitle(R.string.intent_error)
              .setMessage(e.getReason())
              .setNeutralButton(
                  android.R.string.ok,
                  new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int which) {
                      dialog.dismiss();
                    }
                  })
              .create()
              .show();
        }
      }

      // intent MIME type and uri path may be null
      final String type = intent.getType() == null ? "" : intent.getType();
      final String path = uri.getPath() == null ? "" : uri.getPath();
      if (path.endsWith(".user.js") || type.contains("javascript")) {
        final Intent prefIntent = new Intent(this, PluginPreferenceActivity.class);
        prefIntent.setDataAndType(uri, intent.getType());
        startActivity(prefIntent);
      }
    }

    if (Intent.ACTION_SEARCH.equals(action)) {
      String query = intent.getStringExtra(SearchManager.QUERY);
      query = query.replace("'", "''");
      final SearchView searchView = (SearchView) mSearchMenuItem.getActionView();
      searchView.setQuery(query, false);
      searchView.clearFocus();

      switchToPane(Pane.MAP);
      mIitcWebView.loadUrl("javascript:search('" + query + "');");
      return;
    }

    if (onCreate) {
      loadUrl(mIntelUrl);
    }
  }