es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Hilt – Cómo crear un módulo donde un método lance una excepción? Error: Los métodos @Provides solo pueden lanzar excepciones sin chequear.

Estoy intentando implementar Hilt creando una clase Module que proporcione EncryptedSharedPreferences.

Estoy obteniendo el error de tiempo de compilación @Provides methods may only throw unchecked exceptions en mi método Provide.

Esto se debe a que al crear un EncryptedSharedPreferences se requiere

MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) para uno de sus parámetros. Este método arroja dos tipos de excepciones: GeneralSecurityException y IOException.

¿Cómo puedo proporcionar correctamente SharedPreferences en mi módulo?

@Module
@InstallIn(SingletonComponent.class)
public class SharedPrefModule {

@Provides
@Singleton
SharedPreferences provideEncryptedSharedPreferences(@ApplicationContext Context context)
        throws GeneralSecurityException, IOException {
    return EncryptedSharedPreferences.create(
            "secret_shared_prefs",
            MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
            context,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    );
}
}

He intentado mover la cadena de la Master key a un método de proveedor separado dentro de un bloque try-catch, pero el error sigue produciéndose durante el tiempo de compilación.

@Provides
@Singleton
SharedPreferences provideEncryptedSharedPreferences(@ApplicationContext Context context, String masterKey)
        throws Exception{
    return EncryptedSharedPreferences.create(
            "secret_shared_prefs",
            masterKey,
            context,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    );
}

@Provides
String provideMasterKey() throws Exception {
    try {
        return MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
    }catch (Exception e){
        throw new Exception(e);
    }
}

No estoy seguro de qué hacer.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para proporcionar correctamente EncryptedSharedPreferences en tu módulo, puedes usar el soporte de Hilt para excepciones verificadas envolviendo tus excepciones verificadas en una RuntimeException. Aquí tienes un ejemplo de implementación:

    @Module
    @InstallIn(SingletonComponent::class)
    class SharedPrefModule {
    
        @Provides
        @Singleton
        fun provideEncryptedSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
            try {
                return EncryptedSharedPreferences.create(
                    "secret_shared_prefs",
                    MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
                    context,
                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
                )
            } catch (e: GeneralSecurityException) {
                throw RuntimeException(e)
            } catch (e: IOException) {
                throw RuntimeException(e)
            }
        }
    }
    

    Al capturar las excepciones verificadas y envolverlas en un RuntimeException, puedes cumplir con el requisito de Hilt de que los métodos @Provides solo pueden lanzar excepciones no verificadas.

    También puedes usar un método @Provides separado para generar la clave maestra si lo prefieres. Aquí tienes un ejemplo de implementación:

    @Module
    @InstallIn(SingletonComponent::class)
    class SharedPrefModule {
    
        @Provides
        @Singleton
        fun provideEncryptedSharedPreferences(@ApplicationContext context: Context, masterKey: String): SharedPreferences {
            return EncryptedSharedPreferences.create(
                "secret_shared_prefs",
                masterKey,
                context,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            )
        }
    
        @Provides
        @Singleton
        fun provideMasterKey(): String {
            try {
                return MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
            } catch (e: GeneralSecurityException) {
                throw RuntimeException(e)
            } catch (e: IOException) {
                throw RuntimeException(e)
            }
        }
    }
    

    En esta implementación, el método provideMasterKey() captura las excepciones verificadas y las envuelve en un RuntimeException antes de devolver la clave maestra desde el método. Luego, el método provideEncryptedSharedPreferences() recibe la clave maestra como parámetro y la utiliza para crear la instancia de EncryptedSharedPreferences.

Comments are closed.