public static SharedWrapper with(@NonNull Context context, @NonNull String name) {
   if (secretSingleton == null || ivSingleton == null) {
     synchronized (SharedWrapper.class) {
       if (secretSingleton == null) {
         secretSingleton =
             Crypt.AES.generateSecret(Digest.SHA256.getRaw(DeviceInfo.getDeviceToken(context)));
       }
       if (ivSingleton == null) {
         ivSingleton = Crypt.AES.generateIV(Digest.MD5.getRaw(DeviceInfo.getDeviceToken(context)));
       }
     }
   }
   return new SharedWrapper(context, name, secretSingleton, ivSingleton);
 }
 private String get(@NonNull String key, @Nullable String defValue) {
   String target = sp.getString(Digest.MD5.getHex(key), null);
   if (target == null) {
     return defValue;
   } else {
     try {
       return new String(
           Crypt.AES.decrypt(secret, iv, Base64.decode(target, Base64.DEFAULT)), CHARSET_UTF_8);
     } catch (Crypt.CryptException e) {
       Log.e(TAG, "value decrypt error at key :" + key, e);
       return defValue;
     }
   }
 }
 private void set(@NonNull String key, @Nullable String value) {
   String target;
   if (value == null) {
     target = null;
   } else {
     try {
       target =
           Base64.encodeToString(
               Crypt.AES.encrypt(secret, iv, value.getBytes(CHARSET_UTF_8)), Base64.DEFAULT);
     } catch (Crypt.CryptException e) {
       Log.e(TAG, "value encrypt error at key :" + key, e);
       target = null;
     }
   }
   sp.edit().putString(Digest.MD5.getHex(key), target).apply();
 }