private void subscribeToEvents() {
    remotePcc.subscribeAudioStatusEvent(
        new IAudioStatusReceiver() {

          @Override
          public void onNewAudioStatus(
              final long estTimestamp,
              final int volume,
              final int totalTrackTime,
              final int currentTrackTime,
              final AudioDeviceCapabilities audioCapabilities,
              final AudioDeviceState audioState,
              final AudioRepeatState repeatState,
              final AudioShuffleState shuffleState) {
            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    tv_estTimestamp.setText(String.valueOf(estTimestamp));

                    tv_volume.setText(String.valueOf(volume));
                    tv_totalTrackTime.setText(String.valueOf(totalTrackTime));
                    tv_currentTrackTime.setText(String.valueOf(currentTrackTime));
                    tv_audioState.setText(audioState.toString());
                    tv_repeatState.setText(repeatState.toString());
                    tv_shuffleState.setText(shuffleState.toString());

                    tv_customRepeatMode.setText(
                        String.valueOf(audioCapabilities.customRepeatModeSupport));
                    tv_customShuffleMode.setText(
                        String.valueOf(audioCapabilities.customShuffleModeSupport));
                  }
                });
          }
        });

    remotePcc.subscribeBatteryStatusEvent(
        new IBatteryStatusReceiver() {

          @Override
          public void onNewBatteryStatus(
              final long estTimestamp,
              EnumSet<EventFlag> eventFlags,
              final long cumulativeOperatingTime,
              final BigDecimal batteryVoltage,
              final BatteryStatus batteryStatus,
              final int cumulativeOperatingTimeResolution,
              int numberOfBatteries,
              int batteryIdentifier) {
            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    tv_estTimestamp.setText(String.valueOf(estTimestamp));

                    tv_cumulativeOperatingTime.setText(String.valueOf(cumulativeOperatingTime));
                    tv_batteryVoltage.setText(batteryVoltage.toPlainString());
                    tv_batteryStatus.setText(batteryStatus.toString());
                    tv_cumulativeOperatingTimeResolution.setText(
                        String.valueOf(cumulativeOperatingTimeResolution));
                  }
                });
          }
        });

    remotePcc.subscribeManufacturerIdentificationEvent(
        new IManufacturerIdentificationReceiver() {

          @Override
          public void onNewManufacturerIdentification(
              final long estTimestamp,
              final EnumSet<EventFlag> eventFlags,
              final int hardwareRevision,
              final int manufacturerID,
              final int modelNumber) {
            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    tv_estTimestamp.setText(String.valueOf(estTimestamp));

                    tv_hardwareRevision.setText(String.valueOf(hardwareRevision));
                    tv_manufacturerID.setText(String.valueOf(manufacturerID));
                    tv_modelNumber.setText(String.valueOf(modelNumber));
                  }
                });
          }
        });

    remotePcc.subscribeProductInformationEvent(
        new IProductInformationReceiver() {

          @Override
          public void onNewProductInformation(
              final long estTimestamp,
              final EnumSet<EventFlag> eventFlags,
              final int softwareRevision,
              final int supplementalSoftwareRevision,
              final long serialNumber) {
            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    tv_estTimestamp.setText(String.valueOf(estTimestamp));

                    tv_softwareRevision.setText(String.valueOf(softwareRevision));
                    tv_serialNumber.setText(String.valueOf(serialNumber));
                  }
                });
          }
        });
  }
        // Handle the result, connecting to events on success or reporting failure to user.
        @Override
        public void onResultReceived(
            AntPlusAudioRemoteControlPcc result,
            RequestAccessResult resultCode,
            DeviceState initialDeviceState) {
          showDataDisplay("Connecting...");
          switch (resultCode) {
            case SUCCESS:
              remotePcc = result;
              tv_status.setText(result.getDeviceName() + ": " + initialDeviceState);
              subscribeToEvents();
              break;
            case CHANNEL_NOT_AVAILABLE:
              Toast.makeText(
                      Activity_AudioRemoteControlSampler.this,
                      "Channel Not Available",
                      Toast.LENGTH_SHORT)
                  .show();
              tv_status.setText("Error. Do Menu->Reset.");
              break;
            case OTHER_FAILURE:
              Toast.makeText(
                      Activity_AudioRemoteControlSampler.this,
                      "RequestAccess failed. See logcat for details.",
                      Toast.LENGTH_SHORT)
                  .show();
              tv_status.setText("Error. Do Menu->Reset.");
              break;
            case DEPENDENCY_NOT_INSTALLED:
              tv_status.setText("Error. Do Menu->Reset.");
              AlertDialog.Builder adlgBldr =
                  new AlertDialog.Builder(Activity_AudioRemoteControlSampler.this);
              adlgBldr.setTitle("Missing Dependency");
              adlgBldr.setMessage(
                  "The required service\n\""
                      + AntPlusAudioRemoteControlPcc.getMissingDependencyName()
                      + "\"\n was not found. You need to install the ANT+ Plugins service or you may need to update your existing version if you already have it. Do you want to launch the Play Store to get it?");
              adlgBldr.setCancelable(true);
              adlgBldr.setPositiveButton(
                  "Go to Store",
                  new OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                      Intent startStore = null;
                      startStore =
                          new Intent(
                              Intent.ACTION_VIEW,
                              Uri.parse(
                                  "market://details?id="
                                      + AntPlusAudioRemoteControlPcc
                                          .getMissingDependencyPackageName()));
                      startStore.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                      Activity_AudioRemoteControlSampler.this.startActivity(startStore);
                    }
                  });
              adlgBldr.setNegativeButton(
                  "Cancel",
                  new OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                      dialog.dismiss();
                    }
                  });

              final AlertDialog waitDialog = adlgBldr.create();
              waitDialog.show();
              break;
            case USER_CANCELLED:
              tv_status.setText("Cancelled. Do Menu->Reset.");
              break;
            case UNRECOGNIZED:
              // TODO This flag indicates that an unrecognized value was sent by the service, an
              // upgrade of your PCC may be required to handle this new value.
              Toast.makeText(
                      Activity_AudioRemoteControlSampler.this,
                      "Failed: UNRECOGNIZED. Upgrade Required?",
                      Toast.LENGTH_SHORT)
                  .show();
              tv_status.setText("Error. Do Menu->Reset.");
              break;
            default:
              Toast.makeText(
                      Activity_AudioRemoteControlSampler.this,
                      "Unrecognized result: " + resultCode,
                      Toast.LENGTH_SHORT)
                  .show();
              tv_status.setText("Error. Do Menu->Reset.");
              break;
          }
        }
  private void handleReset() {
    // Release the old access if it exists
    if (remoteReleaseHandle != null) {
      remoteReleaseHandle.close();
      remoteReleaseHandle = null;
    }
    if (audioRemoteScanController != null) {
      audioRemoteScanController.closeScanController();
      audioRemoteScanController = null;
    }

    EnumSet<ControlsMode> requestModes = EnumSet.of(ControlsMode.AUDIO_MODE);
    // int desiredDeviceNumber = 4545;
    // AntPlusAudioRemoteControlPcc.requestAccessByDeviceNumber(requestModes, this,
    // desiredDeviceNumber, 0, IPluginAccessResultReceiver, IDeviceStateChangeReceiver);

    // Async scan
    audioRemoteScanController =
        AntPlusAudioRemoteControlPcc.requestRemoteControlAsyncScanController(
            requestModes,
            this,
            0,
            new IRemoteControlAsyncScanResultReceiver() {

              @Override
              public void onSearchStopped(RequestAccessResult reasonStopped) {
                // The triggers calling this function use the same codes and require the same
                // actions as those received by the standard access result receiver
                IPluginAccessResultReceiver.onResultReceived(null, reasonStopped, DeviceState.DEAD);
              }

              @Override
              public void onSearchResult(final RemoteControlAsyncScanResultDeviceInfo deviceFound) {
                for (RemoteControlAsyncScanResultDeviceInfo i : mScannedDeviceInfos) {
                  // The current implementation of the async scan will reset it's ignore list every
                  // 30s,
                  // So we have to handle checking for duplicates in our list if we run longer than
                  // that
                  if (i.resultInfo.getAntDeviceNumber()
                      == deviceFound.resultInfo.getAntDeviceNumber()) {
                    // Found already connected device, ignore
                    return;
                  }
                }

                // We split up devices already connected to the plugin from un-connected devices to
                // make this information more visible to the user,
                // since the user most likely wants to be aware of which device they are already
                // using in another app
                if (deviceFound.resultInfo.isAlreadyConnected()) {
                  mAlreadyConnectedDeviceInfos.add(deviceFound);
                  runOnUiThread(
                      new Runnable() {
                        @Override
                        public void run() {
                          if (adapter_connDevNameList
                              .isEmpty()) // connected device category is invisible unless there are
                          // some present
                          {
                            findViewById(R.id.listView_AlreadyConnectedDevices)
                                .setVisibility(View.VISIBLE);
                            findViewById(R.id.textView_AlreadyConnectedTitle)
                                .setVisibility(View.VISIBLE);
                          }
                          adapter_connDevNameList.add(
                              deviceFound.resultInfo.getDeviceDisplayName());
                          adapter_connDevNameList.notifyDataSetChanged();
                        }
                      });
                } else {
                  mScannedDeviceInfos.add(deviceFound);
                  runOnUiThread(
                      new Runnable() {
                        @Override
                        public void run() {
                          adapter_devNameList.add(deviceFound.resultInfo.getDeviceDisplayName());
                          adapter_devNameList.notifyDataSetChanged();
                        }
                      });
                }
              }
            });
    initScanDisplay();
  }