¡Deje que su aplicación comparta 2 mil millones!

Prefacio

¿OK? Qué diablos se divide en 2 mil millones, vea la imagen a continuación:


Durante el Año Nuevo chino, los íconos de muchas aplicaciones se han convertido en 2 mil millones de puntos y 1 mil millones de puntos. Afortunadamente, mi aplicación no tiene la función de actualizar íconos. ¿No ahorraría 2 mil millones?

Este centavo, oh, no, esta función, todos deberíamos saber que definitivamente no se actualiza a través de la actualización de la App. Durante el festival, para actualizar un ícono y permitir que los usuarios actualicen la App, se estima que serán asesinados. El nombre común de esta función es: reemplazar dinámicamente el ícono de la aplicación.

 

actividad-alias

De hecho, hay muchas formas de implementar íconos de reemplazo, como modificar o interceptar el Lanzador del sistema, pero este método requiere permisos del sistema y no es adecuado para desarrolladores comunes. Activity-alias significa un alias para la actividad, que se puede usar para crear un atajo para la actividad. De esta manera, le mostraremos cómo reemplazar el ícono. Para el alias de la actividad, puede ir a la introducción en el sitio web oficial . Lo más importante aquí es pisar el foso.

 

Pasos de implementación

Preparamos dos iconos diferentes de antemano como se muestra en la siguiente figura:

Agregar alias de actividad

Agregue la etiqueta activity-alias a la etiqueta de la aplicación AndroidManifest.xml para configurar los dos íconos anteriores respectivamente, el código es el siguiente:

<activity-alias
    android:icon="@mipmap/icon1"
    android:name=".icon1"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity-alias>

<activity-alias
    android:icon="@mipmap/icon2"
    android:name=".icon2"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity-alias>

Los resultados de ejecutar la aplicación son los siguientes:

Vemos que se muestran tres íconos en el escritorio al mismo tiempo. Al hacer clic en cada ícono se muestra la página MainActivity. Si está interesado en el proceso de hacer clic en el ícono para iniciar la aplicación, puede pasar a mi artículo anterior  Inicio de la aplicación Análisis de proceso

Al mismo tiempo, cabe señalar aquí que no importa en qué ícono hagamos clic para comenzar, podemos ver que el ícono en la barra de tareas es siempre el primero en comenzar. Solo necesitamos mostrar el ícono predeterminado por defecto, por lo que configuramos el atributo activity-alias android: enabled se establece en falso, lo que deshabilita otras dos entradas de íconos.

 

Método de modificación de la definición

Primero, agregamos tres posiciones de botones al diseño: icono de interruptor 1, icono de interruptor 2 y interruptor predeterminado

Defina tres códigos ComponentName correspondientes para los tres iconos de la siguiente manera:

private lateinit var componDefault: ComponentName
private lateinit var componIcon1: ComponentName
private lateinit var componIcon2: ComponentName
componDefault = ComponentName(this, "$packageName.MainActivity")
componIcon1 = ComponentName(this, "$packageName.icon1")
componIcon2 = ComponentName(this, "$packageName.icon2")

El icon1 aquí corresponde al atributo de nombre en alias.

Método de actualización utilizamos el método setComponentEnabledSetting de packageManager, el código es el siguiente:

/**
 * 更新别名显示
 * @param componentName componentName
 * @param enable 是否启用
 */
private fun updateAlias(enable: Boolean, componentName: ComponentName) {
    val newState = if (enable) {
        PackageManager.COMPONENT_ENABLED_STATE_ENABLED
    } else {
        PackageManager.COMPONENT_ENABLED_STATE_DISABLED
    }
    packageManager.setComponentEnabledSetting(
        componentName,
        newState,
        PackageManager.DONT_KILL_APP
    )
}

Suponiendo que queremos habilitar el ícono 1 ahora, lo que tenemos que hacer es deshabilitar los demás primero y luego habilitar el ícono 1, así que haga clic en el ícono del interruptor 1 para escuchar el método de evento de la siguiente manera:

//切换图标1
findViewById<Button>(R.id.button1).setOnClickListener {
    updateAlias(false,componDefault)
    updateAlias(false,componIcon2)
    updateAlias(true,componIcon1)
}

 

resultado de la operación

Los resultados de la operación son los siguientes:

Podemos ver que el ícono ha cambiado, pero la aplicación se ha salido automáticamente. Este tipo de experiencia no se siente bien para la gente, se siente como si se hubiera bloqueado, entonces, ¿cómo podemos solucionarlo?

El tercer parámetro del método setComponentEnabledSetting se puede ver en el código fuente y hay dos valores que se pueden establecer

/**
 * Flag parameter for
 * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
 * that you don't want to kill the app containing the component.  Be careful when you set this
 * since changing component states can make the containing application's behavior unpredictable.
 */
public static final int DONT_KILL_APP = 0x00000001;

/**
 * Flag parameter for
 * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
 * that the given user's package restrictions state will be serialised to disk after the
 * component state has been updated. Note that this is synchronous disk access, so calls using
 * this flag should be run on a background thread.
 */
public static final int SYNCHRONOUS = 0x00000002;

El valor que configuramos actualmente es DONT_KILL_APP que no mata la App. Se puede ver que el efecto real es que la aplicación se cierra automáticamente después de aproximadamente 1.5s. Ahora cambiamos el valor a SYNCHRONOUS y observamos el efecto.

/**
 * 更新别名显示
 * @param componentName componentName
 * @param enable 是否启用
 */
private fun updateAlias(enable: Boolean, componentName: ComponentName) {
    val newState = if (enable) {
        PackageManager.COMPONENT_ENABLED_STATE_ENABLED
    } else {
        PackageManager.COMPONENT_ENABLED_STATE_DISABLED
    }
    packageManager.setComponentEnabledSetting(
        componentName,
        newState,
        PackageManager.SYNCHRONOUS
    )
}

El resultado de ejecutar de nuevo es el siguiente:

Podemos ver que cuando el valor de flag se establece en PackageManager.SYNCHRONOUS, el efecto es salir de la aplicación inmediatamente y el programa se mata sin importar de qué manera. Obviamente, ya sea que el programa se elimine o no, no podemos manejarlo y puede comportarse de manera diferente en diferentes sistemas de telefonía móvil.

 

Cómo desencadenar en el proyecto real

Aquí usamos la simulación de evento de clic de botón, entonces, ¿cómo lo activamos en nuestro proyecto en línea?

Por lo general, hay dos formas:

  • Método 1: la aplicación cliente evalúa según la marca de tiempo para determinar si la hora actual del sistema está dentro de un determinado día festivo para cambiar los iconos. El problema con este método es que si la hora del sistema del teléfono es inexacta o se ajusta deliberadamente, la aplicación cambiará automáticamente los iconos correspondientes. Pero aquellos que ajustan el tiempo quieren celebrar las vacaciones antes, así que tenemos que cooperar también, ¿verdad?
  • El segundo método es que el cliente juzga si es necesario cambiar el icono al recibir el mensaje del servidor, y el método específico se divide en interfaz de solicitud o push.

Los dos métodos anteriores, sin importar qué método, no pueden evitar el hecho de que el programa se eliminará, pero no podemos decir que el interruptor se llama inmediatamente después de recibir la interfaz, por lo que la prueba nos dice que su aplicación se ha bloqueado. ! También estaremos perdidos.

Entonces, ¿cómo podemos optimizar esto? La sugerencia es encontrar el momento adecuado para cambiar. Por ejemplo, cuando la aplicación se cambia a un segundo plano, cuando la aplicación está en segundo plano, se juzga si es necesario cambiarla. Si debe cambiarse y luego volver a cambiar. No lo demostraré aquí. Ahora, si no sabe cómo supervisar la aplicación en segundo plano, puede consultar mi artículo anterior  sobre el ciclo de vida de la serie Android Jetpack . Sin embargo, incluso si cambia en segundo plano, todavía habrá problemas debido a coincidencias. Entonces, ¿cómo lo resuelven otros software como ** bao? Después de muchas rondas y consultas, obtuve una respuesta convincente: al cambiar Si está no muerto, necesita permisos del sistema.

 

Algunas cosas que debes saber sobre el pozo

Actualización de la aplicación

¿Crees que esto está bien? Eso es demasiado simple. Siguiendo el ejemplo anterior, cambiaremos el ícono al ícono 1. Eliminaremos la información de configuración del ícono 1 durante la próxima actualización de la versión. Veamos qué sucede.:

¿Qué ?, ¿falta el icono? Falta el icono, es decir: la nueva versión de Activity-alias debe contener todos los Activity-alias de la versión anterior , de lo contrario, es posible que no se encuentre la entrada después de instalar la aplicación. Al mismo tiempo, también debemos prestar atención a los cambios en el proceso de actualización de la prueba. La sugerencia aquí es que una vez que se agrega la etiqueta Alias, solo se puede agregar pero no eliminar, y el valor del atributo enable debe no se cambiará arbitrariamente, de lo contrario habrá cosas inesperadas.

 

Arranque durante el traspaso

Cuando se cambia el ícono anterior, también mencionamos que en el modelo probado esta vez (OPPO ACE 10.0), cambiará después de aproximadamente 1.5 s. Esta vez será diferente en diferentes modelos. Ahora soy un experto en pruebas rápidas muy útil, haga clic en el ícono del interruptor 2, y luego regrese inmediatamente al escritorio, haga clic en el ícono anterior antes de que se actualice el ícono, el diagrama de resultados de la prueba:

Podemos ver que cuando se hace clic en el icono de inicio entre la ejecución del método del icono de cambio y antes de que se complete el cambio, aparecerá "la lectura de datos de la aplicación falló ...", y algunos modelos pueden indicar directamente "la aplicación no existe". "..."

Sí, ¿qué puedo hacer? No lo sé ~, si lo sabe, hágamelo saber.

Escribir al final

No se recomienda que las aplicaciones pequeñas realicen esta función. Después de todo, sin el apoyo de los fabricantes, es difícil hacer lo mismo que las aplicaciones del sistema.

También hay personas que dicen que el reemplazo dinámico todavía está codificado. ¿Puedes obtener *** del servidor? Obviamente no. En cuanto a si el método de reparación en caliente de agregar alias dinámicamente es factible en proyectos reales, depende de tus jefes .Practica, si tienes un buen camino, deja un mensaje para decirme ~

 

 

Supongo que te gusta

Origin blog.csdn.net/huangliniqng/article/details/114037467
Recomendado
Clasificación