/** Receives the result of other activities started with startActivityForResult(...) */
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    Uri uri;

    switch (resultCode) {
      case RESULT_OK:
        switch (requestCode) {
          case REQUEST_CODE_PICK_FILE_TO_OPEN:
            // obtain the filename
            uri = data == null ? null : data.getData();
            if (uri != null) {
              ((EditText) findViewById(R.id.InFileEditText)).setText(uri.getPath());
            }
            break;
          case REQUEST_CODE_PICK_FILE_TO_SAVE:
            // obtain the filename
            uri = data == null ? null : data.getData();
            if (uri != null) {
              ((EditText) findViewById(R.id.OutFileEditText)).setText(uri.getPath());
            }
            break;
          case REQUEST_CODE_PICK_INOUT_FILE:
            // obtain the filename
            uri = data == null ? null : data.getData();
            if (uri != null) {
              String filename = uri.getPath();
              ((EditText) findViewById(R.id.InFileEditText)).setText(filename);
              // auto set output file ... "input.zip" becomes "input-signed.zip"
              int pos = filename.lastIndexOf('.');
              if (pos > 0) {
                filename = filename.substring(0, pos) + "-signed" + filename.substring(pos);
              }
              ((EditText) findViewById(R.id.OutFileEditText)).setText(filename);
            }
            break;
          case REQUEST_CODE_SIGN_FILE:
            logger.info(getResources().getString(R.string.FileSigningSuccess));
            break;
          case REQUEST_CODE_MANAGE_KEYS:
            keyModeSpinnerAdapter.changeData();
            break;
          default:
            logger.error("onActivityResult, RESULT_OK, unknown requestCode " + requestCode);
            break;
        }
        break;
      case RESULT_CANCELED: // signing operation canceled
        switch (requestCode) {
          case REQUEST_CODE_SIGN_FILE:
            logger.info(getResources().getString(R.string.FileSigningCancelled));
            break;
          case REQUEST_CODE_PICK_FILE_TO_OPEN:
            break;
          case REQUEST_CODE_PICK_FILE_TO_SAVE:
            break;
          case REQUEST_CODE_PICK_INOUT_FILE:
            break;
          case REQUEST_CODE_MANAGE_KEYS:
            keyModeSpinnerAdapter.changeData();
            break;
          default:
            logger.error("onActivityResult, RESULT_CANCELED, unknown requestCode " + requestCode);
            break;
        }
        break;
      case RESULT_FIRST_USER: // error during signing operation
        switch (requestCode) {
          case REQUEST_CODE_SIGN_FILE:
            // ZipSignerActivity displays a toast upon exiting with an error, so we probably don't
            // need to do this.
            String errorMessage = data.getStringExtra("errorMessage");
            logger.debug("Error during file signing: " + errorMessage);
            break;
          default:
            logger.error("onActivityResult, RESULT_FIRST_USER, unknown requestCode " + requestCode);
            break;
        }
        break;
      case RESULT_FIRST_USER + 1: // error with auto-key selection
        switch (requestCode) {
          case REQUEST_CODE_SIGN_FILE:
            // TODO display alert dialog?
            // String errorMessage = data.getStringExtra("errorMessage");
            String errorMessage =
                String.format(
                    getResources().getString(R.string.KeySelectionMessage), getInputFilename());
            AlertDialogUtil.alertDialog(
                this, getResources().getString(R.string.KeySelectionError), errorMessage);
            break;
          default:
            logger.error(
                "onActivityResult, RESULT_FIRST_USER+1, unknown requestCode " + requestCode);
            break;
        }
        break;
      default:
        logger.error(
            "onActivityResult, unknown resultCode "
                + resultCode
                + ", requestCode = "
                + requestCode);
    }
  }
  private void invokeZipSignerActivity() {
    try {

      String inputFile = getInputFilename();
      String outputFile = getOutputFilename();

      // Save the input,output file names to preferences
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
      SharedPreferences.Editor editor = prefs.edit();
      editor.putString(PREFERENCE_IN_FILE, inputFile);
      editor.putString(PREFERENCE_OUT_FILE, outputFile);
      editor.commit();

      // Refuse to do anything if the external storage device is not writable (external storage =
      // /sdcard).
      if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState())) {
        logger.error(getResources().getString(R.string.ExtStorageIsReadOnly));
        return;
      }

      // Launch the ZipSignerActivity to perform the signature operation.
      Intent i = new Intent("kellinwood.zipsigner.action.SIGN_FILE");

      // Required parameters - input and output files.  The filenames must be different (e.g.,
      // you can't sign the file and save the output to itself).
      i.putExtra("inputFile", inputFile);
      i.putExtra("outputFile", outputFile);

      // Optional parameters...

      // keyMode defaults to "testkey" if not specified
      KeyEntry keyEntry =
          (KeyEntry) ((Spinner) this.findViewById(R.id.KeyModeSpinner)).getSelectedItem();
      logger.debug(keyEntry.getDisplayName() + ", id=" + keyEntry.getId());
      i.putExtra("keyMode", keyEntry.getDisplayName());

      // If "showProgressItems" is true, then the ZipSignerActivity displays the names of files in
      // the
      // zip as they are generated/copied during the signature process.
      i.putExtra("showProgressItems", "true");

      // Set the result code used to indicate that auto-key selection failed.  This will default to
      // RESULT_FIRST_USER if not set (same code used to signal an error).
      i.putExtra("autoKeyFailRC", RESULT_FIRST_USER + 1);

      // Defaults to "SHA1withRSA" if not specified, and is ignored for the built-in keys
      String signatureAlgorithm =
          (String) ((Spinner) this.findViewById(R.id.CertSignatureAlgorithm)).getSelectedItem();
      i.putExtra("signatureAlgorithm", signatureAlgorithm);

      // If two non-builtin keys have the same name, using the ID ensures that we sign with the one
      // selected.
      i.putExtra("customKeyId", keyEntry.getId());

      // Activity is started and the result is returned via a call to onActivityResult(), below.
      startActivityForResult(i, REQUEST_CODE_SIGN_FILE);

    } catch (Throwable x) {
      logger.error(x.getClass().getName() + ": " + x.getMessage(), x);
    }
  }