androidx.annotation.RequiresApi Java Examples

The following examples show how to use androidx.annotation.RequiresApi. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AddBeaconChoicePreferenceDummy.java    From PresencePublisher with MIT License 6 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public AddBeaconChoicePreferenceDummy(Context context, Fragment fragment) {
    super(context);
    setKey(DUMMY);
    setIcon(android.R.drawable.ic_menu_add);
    setTitle(R.string.add_beacon_title);
    setSummary(R.string.add_beacon_summary);
    setOnPreferenceClickListener(prefs -> {
        BluetoothManager bluetoothManager = (BluetoothManager) getContext().getSystemService(Context.BLUETOOTH_SERVICE);
        if (bluetoothManager == null) {
            HyperLog.w(TAG, "Unable to get bluetooth manager");
        } else {
            BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
            if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                fragment.startActivityForResult(enableBtIntent, ON_DEMAND_BLUETOOTH_REQUEST_CODE);
                return true;
            }
        }
        BeaconScanDialogFragment instance = getInstance(getContext(), this::onScanResult,
                getSharedPreferences().getStringSet(BEACON_LIST, Collections.emptySet()));
        instance.show(fragment.requireFragmentManager(), null);
        return true;
    });
}
 
Example #2
Source File: DoNotDisturbUtil.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(23)
private static boolean handlePriority(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Recipient recipient) {
  if (Build.VERSION.SDK_INT < 28 && !notificationManager.isNotificationPolicyAccessGranted()) {
    Log.w(TAG, "Notification Policy is not granted");
    return true;
  }

  final NotificationManager.Policy policy                = notificationManager.getNotificationPolicy();
  final boolean                    areCallsPrioritized   = (policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) != 0;
  final boolean                    isRepeatCallerEnabled = (policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) != 0;

  if (!areCallsPrioritized && !isRepeatCallerEnabled) {
    return false;
  }

  if (areCallsPrioritized && !isRepeatCallerEnabled) {
    return isContactPriority(context, recipient, policy.priorityCallSenders);
  }

  if (!areCallsPrioritized) {
    return isRepeatCaller(context, recipient);
  }

  return isContactPriority(context, recipient, policy.priorityCallSenders) || isRepeatCaller(context, recipient);
}
 
Example #3
Source File: AttachmentDatabase.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(23)
public @Nullable MediaDataSource mediaDataSourceFor(@NonNull AttachmentId attachmentId) {
  DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA);

  if (dataInfo == null) {
    Log.w(TAG, "No data file found for video attachment...");
    return null;
  }

  return EncryptedMediaDataSource.createFor(attachmentSecret, dataInfo.file, dataInfo.random, dataInfo.length);
}
 
Example #4
Source File: KeyStoreHelper.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.M)
public static SealedData seal(@NonNull byte[] input) {
  SecretKey secretKey = getOrCreateKeyStoreEntry();

  try {
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    byte[] iv   = cipher.getIV();
    byte[] data = cipher.doFinal(input);

    return new SealedData(iv, data);
  } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
    throw new AssertionError(e);
  }
}
 
Example #5
Source File: StreamActivity.java    From Twire with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private TransitionSet constructTransitions() {
    int[] slideTargets = {R.id.ChatRecyclerView, R.id.chat_input, R.id.chat_input_divider};

    Transition slideTransition = new Slide(Gravity.BOTTOM);
    Transition fadeTransition = new Fade();

    for (int slideTarget : slideTargets) {
        slideTransition.addTarget(slideTarget);
        fadeTransition.excludeTarget(slideTarget, true);
    }

    TransitionSet set = new TransitionSet();
    set.addTransition(slideTransition);
    set.addTransition(fadeTransition);
    return set;
}
 
Example #6
Source File: KeyStoreHelper.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.M)
private static SecretKey getKeyStoreEntry() {
  KeyStore keyStore = getKeyStore();

  try {
    // Attempt 1
    return getSecretKey(keyStore);
  } catch (UnrecoverableKeyException e) {
    try {
      // Attempt 2
      return getSecretKey(keyStore);
    } catch (UnrecoverableKeyException e2) {
      throw new AssertionError(e2);
    }
  }
}
 
Example #7
Source File: CameraXUtil.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(21)
public static int getLowestSupportedHardwareLevel(@NonNull Context context) {
  @SuppressLint("RestrictedApi") CameraManager cameraManager = CameraManagerCompat.from(context).unwrap();

  try {
    int supported = maxHardwareLevel();

    for (String cameraId : cameraManager.getCameraIdList()) {
      CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
      Integer               hwLevel         = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

      if (hwLevel == null || hwLevel == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
        return CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
      }

      supported = smallerHardwareLevel(supported, hwLevel);
    }

    return supported;
  } catch (CameraAccessException e) {
    Log.w(TAG, "Failed to enumerate cameras", e);

    return CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
  }
}
 
Example #8
Source File: OpenVPNService.java    From Cake-VPN with GNU General Public License v2.0 6 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void addVpnActionsToNotification(Notification.Builder nbuilder) {
    Intent disconnectVPN = new Intent(this, DisconnectVPNActivity.class);
    disconnectVPN.setAction(DISCONNECT_VPN);
    PendingIntent disconnectPendingIntent = PendingIntent.getActivity(this, 0, disconnectVPN, 0);

    nbuilder.addAction(R.drawable.ic_menu_close_clear_cancel,
            getString(R.string.cancel_connection), disconnectPendingIntent);

    Intent pauseVPN = new Intent(this, OpenVPNService.class);
    if (mDeviceStateReceiver == null || !mDeviceStateReceiver.isUserPaused()) {
        pauseVPN.setAction(PAUSE_VPN);
        PendingIntent pauseVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0);
        nbuilder.addAction(R.drawable.ic_menu_pause,
                getString(R.string.pauseVPN), pauseVPNPending);

    } else {
        pauseVPN.setAction(RESUME_VPN);
        PendingIntent resumeVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0);
        nbuilder.addAction(R.drawable.ic_menu_play,
                getString(R.string.resumevpn), resumeVPNPending);
    }
}
 
Example #9
Source File: VideoTrackConverter.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
@RequiresApi(23)
static @Nullable VideoTrackConverter create(
        final @NonNull MediaInput input,
        final long timeFrom,
        final long timeTo,
        final int videoResolution,
        final int videoBitrate,
        final @NonNull String videoCodec) throws IOException, TranscodingException {

    final MediaExtractor videoExtractor = input.createExtractor();
    final int videoInputTrack = getAndSelectVideoTrackIndex(videoExtractor);
    if (videoInputTrack == -1) {
        videoExtractor.release();
        return null;
    }
    return new VideoTrackConverter(videoExtractor, videoInputTrack, timeFrom, timeTo, videoResolution, videoBitrate, videoCodec);
}
 
Example #10
Source File: AudioFocusManager.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
@RequiresApi(26)
private int requestAudioFocusV26() {
  if (audioFocusRequest == null || rebuildAudioFocusRequest) {
    AudioFocusRequest.Builder builder =
        audioFocusRequest == null
            ? new AudioFocusRequest.Builder(focusGain)
            : new AudioFocusRequest.Builder(audioFocusRequest);

    boolean willPauseWhenDucked = willPauseWhenDucked();
    audioFocusRequest =
        builder
            .setAudioAttributes(Assertions.checkNotNull(audioAttributes).getAudioAttributesV21())
            .setWillPauseWhenDucked(willPauseWhenDucked)
            .setOnAudioFocusChangeListener(focusListener)
            .build();

    rebuildAudioFocusRequest = false;
  }
  return audioManager.requestAudioFocus(audioFocusRequest);
}
 
Example #11
Source File: ImmersionBar.java    From a with GNU General Public License v3.0 6 votes vote down vote up
/**
 * 初始化android 5.0以上状态栏和导航栏
 *
 * @param uiFlags the ui flags
 * @return the int
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private int initBarAboveLOLLIPOP(int uiFlags) {
    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;  //Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态栏遮住。
    if (mBarParams.fullScreen && mBarParams.navigationBarEnable) {
        uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; //Activity全屏显示,但导航栏不会被隐藏覆盖,导航栏依然可见,Activity底部布局部分会被导航栏遮住。
    }
    mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    if (mConfig.hasNavigtionBar()) {  //判断是否存在导航栏
        mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
    mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);  //需要设置这个才能设置状态栏颜色
    if (mBarParams.statusBarFlag)
        mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));  //设置状态栏颜色
    else
        mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                Color.TRANSPARENT, mBarParams.statusBarAlpha));  //设置状态栏颜色
    if (mBarParams.navigationBarEnable) {
        mWindow.setNavigationBarColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
                mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha));  //设置导航栏颜色
        if (Build.VERSION.SDK_INT >= 28 && !mBarParams.navigationBarDivider)
                mWindow.setNavigationBarDividerColor(Color.TRANSPARENT);
    }
    return uiFlags;
}
 
Example #12
Source File: StreamActivity.java    From Twire with GNU General Public License v3.0 5 votes vote down vote up
@Override
@RequiresApi(24)
public void onUserLeaveHint() {
       super.onUserLeaveHint();

       if (getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
           mStreamFragment.prePictureInPicture();
           enterPictureInPictureMode();
       }
}
 
Example #13
Source File: SetSecurityActivity.java    From MHViewer with Apache License 2.0 5 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.M)
public static boolean hasEnrolledFingerprints(FingerprintManager fingerprintManager) {
    try {
        return fingerprintManager.isHardwareDetected()
            && fingerprintManager.hasEnrolledFingerprints();
    } catch (Throwable e) {
        return false;
    }
}
 
Example #14
Source File: AddBeaconChoicePreferenceDummy.java    From PresencePublisher with MIT License 5 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void onScanResult(@Nullable Beacon beacon) {
    if (beacon == null) {
        return;
    }
    BeaconManager.getInstance().addBeacon(getContext(), beacon);
}
 
Example #15
Source File: BlobProvider.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(23)
public synchronized @NonNull MediaDataSource getMediaDataSource(@NonNull Context context, @NonNull Uri uri) throws IOException {
  return getBlobRepresentation(context,
                               uri,
                               ByteArrayMediaDataSource::new,
                               file -> EncryptedMediaDataSource.createForDiskBlob(getAttachmentSecret(context), file));
}
 
Example #16
Source File: NotificationWrapper.java    From react-native-jw-media-player with MIT License 5 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.O)
private void createNotificationChannel() {
	CharSequence channelNameDisplayedToUser = "Notification Bar Video Controls";
	int importance = NotificationManager.IMPORTANCE_LOW;
	mNotificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
												   channelNameDisplayedToUser,
												   importance);
	mNotificationChannel.setDescription("All notifications");
	mNotificationChannel.setShowBadge(false);
	mNotificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
	mNotificationManager.createNotificationChannel(mNotificationChannel);
}
 
Example #17
Source File: FingerPrint.java    From leafpicrevived with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.M)
public static boolean checkFinger(Context ctx) {

    // Keyguard Manager
    KeyguardManager keyguardManager = (KeyguardManager) ctx.getSystemService(KEYGUARD_SERVICE);
    // Fingerprint Manager
    FingerprintManager fingerprintManager = (FingerprintManager) ctx.getSystemService(FINGERPRINT_SERVICE);

    try {
        // Check if the fingerprint sensor is present
        if (!fingerprintManager.isHardwareDetected()) {
            // Update the UI with a message
            StringUtils.showToast(ctx, ctx.getString(R.string.fp_not_supported));
            return false;
        }

        if (!fingerprintManager.hasEnrolledFingerprints()) {
            StringUtils.showToast(ctx, ctx.getString(R.string.fp_not_configured));
            return false;
        }

        if (!keyguardManager.isKeyguardSecure()) {
            StringUtils.showToast(ctx, ctx.getString(R.string.fp_not_enabled_sls));
            return false;
        }
    } catch (SecurityException se) {
        se.printStackTrace();
    }
    return true;
}
 
Example #18
Source File: KeyStoreHelper.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.M)
private static boolean hasKeyStoreEntry() {
  try {
    KeyStore ks = KeyStore.getInstance(ANDROID_KEY_STORE);
    ks.load(null);

    return ks.containsAlias(KEY_ALIAS) && ks.entryInstanceOf(KEY_ALIAS, KeyStore.SecretKeyEntry.class);
  } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
    throw new AssertionError(e);
  }
}
 
Example #19
Source File: KeyStoreHelper.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.M)
public static SecretKey createKeyStoreEntryHmac() {
  try {
    KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_HMAC_SHA256, ANDROID_KEY_STORE);

    KeyGenParameterSpec.Builder keySpecBuilder = new KeyGenParameterSpec.Builder(KEY_ALIAS_HMAC, KeyProperties.PURPOSE_SIGN);
    KeyGenParameterSpec keyGenParameterSpec = keySpecBuilder.build();

    keyGenerator.init(keyGenParameterSpec);

    return keyGenerator.generateKey();
  } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
    throw new AssertionError(e);
  }
}
 
Example #20
Source File: KeyStoreHelper.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.M)
public static SecretKey getKeyStoreEntryHmac() throws UnrecoverableEntryException {
  try {
    KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
    keyStore.load(null);

    return ((KeyStore.SecretKeyEntry) keyStore.getEntry(KEY_ALIAS_HMAC, null)).getSecretKey();
  } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
    throw new AssertionError(e);
  }
}
 
Example #21
Source File: MainActivity.java    From privatelocation with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
    view.getContext().startActivity(intent);
    return true;
}
 
Example #22
Source File: JobSchedulerScheduler.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(26)
@Override
public void schedule(long delay, @NonNull List<Constraint> constraints) {
  JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(getNextId(), new ComponentName(application, SystemService.class))
                                              .setMinimumLatency(delay)
                                              .setPersisted(true);

  for (Constraint constraint : constraints) {
    constraint.applyToJobInfo(jobInfoBuilder);
  }

  Log.i(TAG, "Scheduling a run in " + delay + " ms.");
  JobScheduler jobScheduler = application.getSystemService(JobScheduler.class);
  jobScheduler.schedule(jobInfoBuilder.build());
}
 
Example #23
Source File: MiddlewareWebViewClient.java    From TemplateAppProject with Apache License 2.0 5 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    String url = request.getUrl().toString().toLowerCase();
    if (!hasAdUrl(url)) {
        //正常加载
        return super.shouldInterceptRequest(view, request);
    } else {
        //含有广告资源屏蔽请求
        return new WebResourceResponse(null, null, null);
    }
}
 
Example #24
Source File: CameraXUtil.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(21)
private static boolean shouldCropImage(@NonNull ImageProxy image) {
  Size sourceSize = new Size(image.getWidth(), image.getHeight());
  Size targetSize = new Size(image.getCropRect().width(), image.getCropRect().height());

  return !targetSize.equals(sourceSize);
}
 
Example #25
Source File: CameraXUtil.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(21)
private static int smallerHardwareLevel(int levelA, int levelB) {

  int[] hardwareInfoOrdering = getHardwareInfoOrdering();
  for (int hwInfo : hardwareInfoOrdering) {
    if (levelA == hwInfo || levelB == hwInfo) return hwInfo;
  }

  return CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
}
 
Example #26
Source File: CameraXModule.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(26)
// End Signal Custom Code Block
public void stopRecording() {
  if (mVideoCapture == null) {
    return;
  }

  mVideoCapture.stopRecording();
}
 
Example #27
Source File: CameraXView.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Takes a video and calls the OnVideoSavedCallback when done.
 *
 * @param file     The destination.
 * @param executor The executor in which the callback methods will be run.
 * @param callback Callback which will receive success or failure.
 */
// Begin Signal Custom Code Block
@RequiresApi(26)
// End Signal Custom Code Block
public void startRecording(// Begin Signal Custom Code Block
                           @NonNull FileDescriptor file,
                           // End Signal Custom Code Block
                           @NonNull Executor executor,
                           @NonNull VideoCapture.OnVideoSavedCallback callback) {
  mCameraModule.startRecording(file, executor, callback);
}
 
Example #28
Source File: CameraXView.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
/** Stops an in progress video. */
// Begin Signal Custom Code Block
@RequiresApi(26)
// End Signal Custom Code Block
public void stopRecording() {
  mCameraModule.stopRecording();
}
 
Example #29
Source File: FcmJobService.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
@RequiresApi(26)
public static void schedule(@NonNull Context context) {
  JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(ID, new ComponentName(context, FcmJobService.class))
                                              .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                                              .setBackoffCriteria(0, JobInfo.BACKOFF_POLICY_LINEAR)
                                              .setPersisted(true);

  ServiceUtil.getJobScheduler(context).schedule(jobInfoBuilder.build());
}
 
Example #30
Source File: X509Utils.java    From Cake-VPN with GNU General Public License v2.0 5 votes vote down vote up
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static String getCertificateFriendlyName(X509Certificate cert) {
    X500Principal principal = cert.getSubjectX500Principal();
    byte[] encodedSubject = principal.getEncoded();
    String friendlyName = null;
    /* Hack so we do not have to ship a whole Spongy/bouncycastle */
    Exception exp = null;
    try {
        Class X509NameClass = Class.forName("com.android.org.bouncycastle.asn1.x509.X509Name");
        Method getInstance = X509NameClass.getMethod("getInstance", Object.class);
        Hashtable defaultSymbols = (Hashtable) X509NameClass.getField("DefaultSymbols").get(X509NameClass);
        if (!defaultSymbols.containsKey("1.2.840.113549.1.9.1")) defaultSymbols.put("1.2.840.113549.1.9.1", "eMail");
        Object subjectName = getInstance.invoke(X509NameClass, encodedSubject);
        Method toString = X509NameClass.getMethod("toString", boolean.class, Hashtable.class);
        friendlyName = (String) toString.invoke(subjectName, true, defaultSymbols);
    } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | NoSuchFieldException e) {
        exp = e;
    }
    if (exp != null) VpnStatus.logException("Getting X509 Name from certificate", exp);
    /* Fallback if the reflection method did not work */
    if (friendlyName == null) friendlyName = principal.getName();
    // Really evil hack to decode email address
    // See: http://code.google.com/p/android/issues/detail?id=21531
    String[] parts = friendlyName.split(",");
    for (int i = 0; i < parts.length; i++) {
        String part = parts[i];
        if (part.startsWith("1.2.840.113549.1.9.1=#16")) {
            parts[i] = "email=" + ia5decode(part.replace("1.2.840.113549.1.9.1=#16", ""));
        }
    }
    friendlyName = TextUtils.join(",", parts);
    return friendlyName;
}