En este artículo, se describe cómo personalizar la protección contra manipulaciones de Play para tus apps y juegos. Para usar las funciones de personalización que se describen en esta página, debes tener activada la protección automática contra manipulaciones en Play Console.
Información sobre la protección personalizada contra manipulaciones
La protección personalizada contra manipulaciones te permite identificar métodos específicos de Java y Kotlin dentro de tu app que requieren mayor seguridad. Cuando haces tu lanzamiento en Play, la prioridad de Google Play es la protección mejorada de estos métodos específicos.
Si identificas métodos que requieren una protección mejorada, puedes fortalecer la defensa de tu app contra manipulaciones. Además, la protección de métodos sirve para evitar la filtración de secretos del cliente desde tu archivo binario (por ejemplo, claves o URLs sensibles que deben incluirse en el cliente).
Cómo configurar la protección personalizada contra manipulaciones
Sigue estos pasos para implementar la protección personalizada contra manipulaciones en la base de código de tu app.
Paso 1: Agrega la interfaz de protección automática a tu base de código
Primero, agrega la interfaz de protección a tu app o juego.
Kotlin:
package com.google.android.play.protections.annotations/**
* Describe que un método es candidato para la protección mejorada.
*
* <p>Esta anotación se quitará automáticamente del código dex de tu
* paquete en el momento en que Google Play lo proteja. Solo se usa como
* una anotación a nivel del método. No se admite ningún otro uso (p. ej., acceder a la clase
* de forma reflexiva en el tiempo de ejecución).
*/
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
public annotation class PlayAutomaticIntegrityProtection() {}
Java:
package com.google.android.play.protections.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Describe que un método es candidato para la protección mejorada.
*
* <p>Esta anotación se quitará automáticamente del código dex de tu
* paquete en el momento en que Google Play lo proteja. Solo se usa como
* una anotación a nivel del método. No se admite ningún otro uso (p. ej., acceder a la clase
* de forma reflexiva en el tiempo de ejecución).
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PlayAutomaticIntegrityProtection {}
# Conservar la clase de anotación y sus miembros.
-keep class com.google.android.play.protections.annotations.PlayAutomaticIntegrityProtection* { *; }
# Por defecto, ProGuard trata los atributos de anotación como opcionales y los quita
# durante el paso de ofuscación. Esta regla garantizará que se conserven.
-keepattributes RuntimeVisibleAnnotations, AnnotationDefault
# Mantener cualquier método que tenga la anotación, pero permitir que se ofusque.
-keepclassmembers,allowobfuscation class * {
@com.google.android.play.protections.annotations.PlayAutomaticIntegrityProtection *;
}
Paso 2: Anota métodos para la protección personalizada
import com.google.android.play.protections.annotations.PlayAutomaticIntegrityProtection
@PlayAutomaticIntegrityProtection()
fun myMethod() {
// Cuerpo del método...
}
Java:
import com.google.android.play.protections.annotations.PlayAutomaticIntegrityProtection;
@PlayAutomaticIntegrityProtection()
public void myMethod() {
// Cuerpo del método...
}Paso 3: Protege los secretos del cliente (opcional)
La protección personalizada de los métodos ofusca (oculta) el código directamente dentro del cuerpo del método anotado y sirve para proteger las claves de API sensibles.
Kotlin:
import com.google.android.play.protections.annotations.PlayAutomaticIntegrityProtection
@PlayAutomaticIntegrityProtection()
fun callApi() {
api.connect("YOUR_API_KEY")
}
Java:
import com.google.android.play.protections.annotations.PlayAutomaticIntegrityProtection;
@PlayAutomaticIntegrityProtection()
public static void callApi() {
api.connect("YOUR_API_KEY");
}
Paso 4: Administra la sobrecarga del rendimiento de la protección (opcional)
Por defecto, llamar a un método protegido agrega una sobrecarga de varios milisegundos. Así que, no se debe llamar en situaciones sensibles al rendimiento ni en el subproceso principal.
Si necesitas proteger un método en el que se requiere una ejecución rápida, hay disponible un modo de protección más ligero. Puedes usar un atributo de anotación para optar por un acceso más rápido (se carga al inicio), aunque la protección correspondiente no es tan sólida.
Kotlin:
@PlayAutomaticIntegrityProtection(loadAtStartup = true)
fun callApi() {
api.connect("YOUR_API_KEY")
}
Java:
@PlayAutomaticIntegrityProtection(loadAtStartup = true)
public static void callApi() {
api.connect("YOUR_API_KEY");
}
Para usarlo, agrega el atributo de interfaz al cuerpo de la definición de anotación original del paso 1:
// Actualización de la definición de anotación de Kotlin
public annotation class PlayAutomaticIntegrityProtection(
/**
* Si es verdadero, el método anotado se cargará al inicio. Si es falso, se cargará
* a pedido.
*
* <p>En el caso de la carga a pedido, llamar al método generará una penalización de
* rendimiento. En el caso de la carga al inicio, el método permanecerá desofuscado en la memoria
* durante la vida útil de la app.
*/
val loadAtStartup: Boolean = false
) {}
Paso 5: Prueba la app
Prácticas recomendadas para seleccionar métodos
La selección cuidadosa de métodos conduce a una protección general más sólida. Si cada nuevo lanzamiento tiene un método protegido recientemente, esa versión de la app o del juego será más resiliente frente a los ataques.
Como regla general para evitar afectar el rendimiento de tu app, selecciona métodos fríos en lugar de métodos activos. Si quieres obtener la máxima protección, selecciona métodos que cumplan con los siguientes requisitos:
- Son fundamentales para la aplicación (si se quitan, la app falla).
- No se ejecutan en el subproceso principal o de IU.
- Se ejecutan más de una vez durante el ciclo de vida de la app, pero no en un bucle activo.
- No son triviales (contienen código o datos no triviales).
- No se ejecutan durante el inicio, en lo posible.
- Son nuevos o refactorizados significativamente en la versión.
- No son abstractos, de interfaz ni constructores.
- No usan la reflexión ni carga directamente una biblioteca nativa.
Cómo quitar la protección personalizada
Si ya no quieres proteger un método específico, simplemente puedes quitar la anotación @PlayAutomaticIntegrityProtection().