@Override
  public void initialize(final CordovaInterface cordova, final CordovaWebView webView) {
    super.initialize(cordova, webView);
    am = (AudioManager) cordova.getActivity().getSystemService(Context.AUDIO_SERVICE);
    reader = new AudioJackReader(am, true);

    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_HEADSET_PLUG);
    cordova
        .getActivity()
        .registerReceiver(
            new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {

                if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {

                  boolean plugged = (intent.getIntExtra("state", 0) == 1);

                  /* Mute the audio output if the reader is unplugged. */
                  reader.setMute(!plugged);
                  mute = !plugged;
                }
              }
            },
            filter);

    final StringBuffer buffer = new StringBuffer();
    final StringBuffer atrBuffer = new StringBuffer();

    reader.setSleepTimeout(30);

    reader.setOnPiccAtrAvailableListener(
        new AudioJackReader.OnPiccAtrAvailableListener() {
          @Override
          public void onPiccAtrAvailable(AudioJackReader audioJackReader, byte[] bytes) {
            Log.w(TAG, bytesToHex(bytes));

            atrBuffer.append(bytesToHex(bytes));
          }
        });

    reader.setOnPiccResponseApduAvailableListener(
        new AudioJackReader.OnPiccResponseApduAvailableListener() {
          @Override
          public void onPiccResponseApduAvailable(AudioJackReader audioJackReader, byte[] bytes) {
            byte[] resultBytes = new byte[bytes.length - 2];
            byte[] statusBytes = new byte[2];

            System.arraycopy(bytes, 0, resultBytes, 0, bytes.length - 2);
            System.arraycopy(bytes, bytes.length - 2, statusBytes, 0, 2);

            Log.w(TAG, bytesToHex(statusBytes));

            buffer.append(bytesToHex(resultBytes));
            buffer.append("");
          }
        });

    reader.setOnStatusAvailableListener(
        new AudioJackReader.OnStatusAvailableListener() {
          @Override
          public void onStatusAvailable(AudioJackReader audioJackReader, final Status status) {
            timer.cancel();

            cordova
                .getActivity()
                .runOnUiThread(
                    new Runnable() {
                      @Override
                      public void run() {
                        JSONArray resultArray = new JSONArray();
                        resultArray.put(Integer.toString(status.getBatteryLevel()));
                        resultArray.put(Integer.toString(status.getSleepTimeout()));

                        PluginResult dataResult =
                            new PluginResult(PluginResult.Status.OK, resultArray);
                        callbackContext.sendPluginResult(dataResult);
                      }
                    });
          }
        });

    reader.setOnDeviceIdAvailableListener(
        new AudioJackReader.OnDeviceIdAvailableListener() {
          @Override
          public void onDeviceIdAvailable(AudioJackReader audioJackReader, final byte[] bytes) {
            // reader.sleep();
            timer.cancel();

            cordova
                .getActivity()
                .runOnUiThread(
                    new Runnable() {
                      @Override
                      public void run() {
                        PluginResult dataResult =
                            new PluginResult(PluginResult.Status.OK, bytesToHex(bytes));
                        callbackContext.sendPluginResult(dataResult);
                      }
                    });
          }
        });

    reader.setOnResultAvailableListener(
        new AudioJackReader.OnResultAvailableListener() {
          @Override
          public void onResultAvailable(AudioJackReader audioJackReader, Result result) {
            // reader.sleep();
            timer.cancel();

            final String stringResult = buffer.toString();
            final String atrResult = atrBuffer.toString();

            Log.i(TAG, "Result Available");
            Log.i(TAG, stringResult);

            cordova
                .getActivity()
                .runOnUiThread(
                    new Runnable() {
                      @Override
                      public void run() {
                        if (timedOut) {
                          PluginResult dataResult =
                              new PluginResult(PluginResult.Status.OK, "TIMEDOUT");
                          callbackContext.sendPluginResult(dataResult);
                        } else {
                          JSONArray resultArray = new JSONArray();
                          resultArray.put(stringResult.replaceAll("\\s", ""));
                          resultArray.put(atrResult.replaceAll("\\s", ""));

                          PluginResult dataResult =
                              new PluginResult(PluginResult.Status.OK, resultArray);
                          callbackContext.sendPluginResult(dataResult);
                        }
                      }
                    });
            buffer.delete(0, buffer.length());
            atrBuffer.delete(0, atrBuffer.length());
          }
        });
  }