@Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    String filePickerResult = "";
    if (data != null && resultCode == RESULT_OK) {
      try {
        ContentResolver cr = getContentResolver();
        Uri uri = data.getData();
        Cursor cursor =
            GeckoApp.mAppContext
                .getContentResolver()
                .query(uri, new String[] {OpenableColumns.DISPLAY_NAME}, null, null, null);
        String name = null;
        if (cursor != null) {
          try {
            if (cursor.moveToNext()) {
              name = cursor.getString(0);
            }
          } finally {
            cursor.close();
          }
        }
        String fileName = "tmp_";
        String fileExt = null;
        int period;
        if (name == null || (period = name.lastIndexOf('.')) == -1) {
          String mimeType = cr.getType(uri);
          fileExt = "." + GeckoAppShell.getExtensionFromMimeType(mimeType);
        } else {
          fileExt = name.substring(period);
          fileName = name.substring(0, period);
        }
        File file = File.createTempFile(fileName, fileExt, sGREDir);

        FileOutputStream fos = new FileOutputStream(file);
        InputStream is = cr.openInputStream(uri);
        byte[] buf = new byte[4096];
        int len = is.read(buf);
        while (len != -1) {
          fos.write(buf, 0, len);
          len = is.read(buf);
        }
        fos.close();
        filePickerResult = file.getAbsolutePath();
      } catch (Exception e) {
        Log.e(LOG_FILE_NAME, "showing file picker", e);
      }
    }
    try {
      mFilePickerResult.put(filePickerResult);
    } catch (InterruptedException e) {
      Log.i(LOG_FILE_NAME, "error returning file picker result", e);
    }
  }
 void removeFiles() throws IOException {
   BufferedReader reader = new BufferedReader(new FileReader(new File(sGREDir, "removed-files")));
   try {
     for (String removedFileName = reader.readLine();
         removedFileName != null;
         removedFileName = reader.readLine()) {
       File removedFile = new File(sGREDir, removedFileName);
       if (removedFile.exists()) removedFile.delete();
     }
   } finally {
     reader.close();
   }
 }
  private boolean unpackFile(ZipFile zip, byte[] buf, ZipEntry fileEntry, String name)
      throws IOException, FileNotFoundException {
    if (fileEntry == null) fileEntry = zip.getEntry(name);
    if (fileEntry == null)
      throw new FileNotFoundException("Can't find " + name + " in " + zip.getName());

    File outFile = new File(sGREDir, name);
    if (outFile.lastModified() == fileEntry.getTime() && outFile.length() == fileEntry.getSize())
      return false;

    File dir = outFile.getParentFile();
    if (!dir.exists()) dir.mkdirs();

    InputStream fileStream;
    fileStream = zip.getInputStream(fileEntry);

    OutputStream outStream = new FileOutputStream(outFile);

    while (fileStream.available() > 0) {
      int read = fileStream.read(buf, 0, buf.length);
      outStream.write(buf, 0, read);
    }

    fileStream.close();
    outStream.close();
    outFile.setLastModified(fileEntry.getTime());
    return true;
  }
  protected void unpackComponents() throws IOException, FileNotFoundException {
    File applicationPackage = new File(getApplication().getPackageResourcePath());
    File componentsDir = new File(sGREDir, "components");
    if (componentsDir.lastModified() == applicationPackage.lastModified()) return;

    componentsDir.mkdir();
    componentsDir.setLastModified(applicationPackage.lastModified());

    GeckoAppShell.killAnyZombies();

    ZipFile zip = new ZipFile(applicationPackage);

    byte[] buf = new byte[32768];
    try {
      if (unpackFile(zip, buf, null, "removed-files")) removeFiles();
    } catch (Exception ex) {
      // This file may not be there, so just log any errors and move on
      Log.w(LOG_FILE_NAME, "error removing files", ex);
    }

    // copy any .xpi file into an extensions/ directory
    Enumeration<? extends ZipEntry> zipEntries = zip.entries();
    while (zipEntries.hasMoreElements()) {
      ZipEntry entry = zipEntries.nextElement();
      if (entry.getName().startsWith("extensions/") && entry.getName().endsWith(".xpi")) {
        Log.i("GeckoAppJava", "installing extension : " + entry.getName());
        unpackFile(zip, buf, entry, entry.getName());
      }
    }
  }
  private void checkAndLaunchUpdate() {
    Log.i(LOG_FILE_NAME, "Checking for an update");

    int statusCode = 8; // UNEXPECTED_ERROR
    File baseUpdateDir = null;
    if (Build.VERSION.SDK_INT >= 8)
      baseUpdateDir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
    else baseUpdateDir = new File(Environment.getExternalStorageDirectory().getPath(), "download");

    File updateDir = new File(new File(baseUpdateDir, "updates"), "0");

    File updateFile = new File(updateDir, "update.apk");
    File statusFile = new File(updateDir, "update.status");

    if (!statusFile.exists() || !readUpdateStatus(statusFile).equals("pending")) return;

    if (!updateFile.exists()) return;

    Log.i(LOG_FILE_NAME, "Update is available!");

    // Launch APK
    File updateFileToRun = new File(updateDir, getPackageName() + "-update.apk");
    try {
      if (updateFile.renameTo(updateFileToRun)) {
        String amCmd =
            "/system/bin/am start -a android.intent.action.VIEW "
                + "-n com.android.packageinstaller/.PackageInstallerActivity -d file://"
                + updateFileToRun.getPath();
        Log.i(LOG_FILE_NAME, amCmd);
        Runtime.getRuntime().exec(amCmd);
        statusCode = 0; // OK
      } else {
        Log.i(LOG_FILE_NAME, "Cannot rename the update file!");
        statusCode = 7; // WRITE_ERROR
      }
    } catch (Exception e) {
      Log.i(LOG_FILE_NAME, "error launching installer to update", e);
    }

    // Update the status file
    String status = statusCode == 0 ? "succeeded\n" : "failed: " + statusCode + "\n";

    OutputStream outStream;
    try {
      byte[] buf = status.getBytes("UTF-8");
      outStream = new FileOutputStream(statusFile);
      outStream.write(buf, 0, buf.length);
      outStream.close();
    } catch (Exception e) {
      Log.i(LOG_FILE_NAME, "error writing status file", e);
    }

    if (statusCode == 0) System.exit(0);
  }
  /** Private constructor for this class. */
  private LibDexLoader() {
    String assetDexName = "jitsi-bundles-dex.jar";
    // Before the dex file can be processed by the DexClassLoader,
    // it has to be first copied from asset resource to a storage location.
    Context ctx = JitsiApplication.getGlobalContext();
    File dexInternalStoragePath = new File(ctx.getDir("dex", Context.MODE_PRIVATE), assetDexName);

    BufferedInputStream bis = null;
    OutputStream dexWriter = null;

    final int BUF_SIZE = 2 * 1024;
    try {
      bis = new BufferedInputStream(ctx.getAssets().open(assetDexName));
      dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath));
      byte[] buf = new byte[BUF_SIZE];
      int len;
      while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
        dexWriter.write(buf, 0, len);
      }
      dexWriter.close();
      bis.close();

      // Internal storage where the DexClassLoader writes
      // the optimized dex file to
      final File optimizedDexOutputPath = ctx.getDir("outdex", Context.MODE_PRIVATE);

      this.dexClassLoader =
          new DexClassLoader(
              dexInternalStoragePath.getAbsolutePath(),
              optimizedDexOutputPath.getAbsolutePath(),
              null,
              getClass().getClassLoader());
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }