crochet android (cas Toast BadTokenException)

Que sont les crochets ?

 La technologie de crochet est également appelée fonction de crochet. Avant que le système n'appelle la fonction, le programme de crochet capture d'abord le message et la fonction de crochet obtient d'abord le droit de contrôle. À ce stade, la fonction de crochet peut traiter (modifier) ​​le comportement d'exécution. de la fonction, et peut également être forcé à mettre fin à la livraison du message. Pour le dire simplement, il s'agit d'extraire le programme du système et de le transformer en un fragment de code que nous exécutons nous-mêmes.

Implémentation de Hook ?

Pour implémenter des hooks, nous devons connaître la réflexion et le proxy dynamique de Java.

​​​​​​Explication détaillée du mécanisme de réflexion Java

Cas : Toast WindowManager$BadTokenException

Conseils : Nous nous concentrons principalement sur Android7.x dans cette petite section de code source.

Je pense que les amis Android auraient dû rencontrer une panne de jeton lorsqu'ils se développent habituellement.

Selon le processus normal, cette anomalie ne se produira pas. Mais parce que dans certains cas, Androidun message d'un certain fil d'interface utilisateur du processus est bloqué. La méthode TNqui provoque l'affichage du message 0 est située après le message et n'a pas été exécutée depuis longtemps. À ce stade, la détection du délai d'expiration du service est terminée et l'enregistrement dans le service est supprimé . Autrement dit, comme indiqué, la suppression se produit avant la méthode de processus. Cela conduit à notre exception ci-dessus.showpostNotificationManagerWMStokentokenAndroidshow

L'ensemble du principe d'affichage et de l'analyse de toast Vous pouvez jeter un coup d'œil complet à l'analyse de l'équipe de technologie musicale QQ, (la source de l'image ci-dessus est également la même) [Android] Analyse du problème de Toast (1) - Tencent Cloud Developer Community - Nuage Tencent

Le token is valid n'est pas reproduit dans la méthode sleep, mais après lecture du code source de Toast, l'exception BadTokenException peut être reproduite d'une autre manière :

val mw = getSystemService(WINDOW_SERVICE) as WindowManager
        val tv = TextView(this)
        tv.layoutParams = WindowManager.LayoutParams(1, 1)
        tv.text = "模拟toast悬浮窗"
        val params = WindowManager.LayoutParams()
        params.type = WindowManager.LayoutParams.TYPE_TOAST
        mw.addView(tv, params)
        Toast.makeText(this, "xxxx", Toast.LENGTH_SHORT).show()

Parce que les toasts de type==TYPE_TOAST ne peuvent pas être ajoutés à plusieurs reprises, une BadTokenException sera également signalée. Ensuite, nous allons passer cette démo et utiliser la solution de crochet pour résoudre cette exception.

En lisant le code source, nous avons constaté que la méthode handleShow dans Android 7.0 Toast.java :

et sur Android 8.0 Toast.java :

La comparaison a révélé que dans Android 8.0, 8.0 dispose d'une couche de protection contre les tentatives d'interception lorsque WindowManager exécute addView, mais ce n'est pas le cas sur 7.0. Ensuite, nous pouvons nous référer à la méthode de 8.0 et intercepter directement cette exception.

Trouver le point d'accroche

Essayez d'accrocher des variables statiques et des objets singleton

Essayez d'accrocher des objets et des méthodes publics

En regardant la chaîne d'appel, un message est envoyé dans mHandler, et handlerShow est appelé après avoir traité le message affiché par le toast dans handlerMessage. mHandler est une variable dans la classe TN, et il y a une variable mTN (classe TN) dans Toast. C'est donc très simple, nous accrochons le point pour localiser ce mTN, puis réfléchissons et remplaçons la variable membre interne mHandler de TN, et ajoutons un try-catch à la méthode handleMessage pour le protéger.

public class HookToastUtil {
    private static Field sField_N;
    private static Field sField_TN_Handler;
    private static Toast mToast;


    private HookToastUtil() {

    }

    public static void show(Context context, CharSequence message, int duration) {
        if (mToast == null) {
            mToast = Toast.makeText(context.getApplicationContext(), message, duration);
            hook(mToast);
        } else {
            mToast.setDuration(duration);
            mToast.setText(message);

            mToast.show();
        }
    }

    public static void show(Context context, @StringRes int resId, int duration) {
        if (mToast == null) {
            mToast = Toast.makeText(context.getApplicationContext(), resId, duration);
            hook(mToast);
        } else {
            mToast.setDuration(duration);
            mToast.setText(context.getString(resId));
        }
        mToast.show();
    }

    private static void hook(Toast toast) {
        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.N_MR1) {
            return;
        }

        try {
            Class<?> cls = Class.forName("android.widget.Toast");
            sField_N = cls.getDeclaredField("mTN");
            sField_N.setAccessible(true);
            sField_TN_Handler = sField_N.getType().getDeclaredField("mHandler");
            sField_TN_Handler.setAccessible(true);
            Object tn = sField_N.get(toast);
            Handler handler = (Handler) sField_TN_Handler.get(tn);

            sField_TN_Handler.set(tn, new ReplaceHandler(handler));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class ReplaceHandler extends Handler {
        private Handler tnHandler;

        public ReplaceHandler(Handler handler) {
            this.tnHandler = handler;
        }

        @Override
        public void handleMessage(Message msg) {
            try{
                tnHandler.handleMessage(msg);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

 Appelez HookToastUtil.show(this,"111",1000) pour remplacer le précédent Toast.makeText et aucune erreur ne sera signalée

Je suppose que tu aimes

Origine blog.csdn.net/u013773608/article/details/130048177
conseillé
Classement