[JAVA] Récupérer diverses informations des notifications LINE

introduction

Le service LINE a démarré le 23 juin 2011, et c'est la 9e année, mais comme le nombre d'utilisateurs actifs mensuels au Japon est d'environ 87 millions, la plupart des gens connaissent LINE. pense. Je pense que j'échange généralement des informations principalement avec LINE, mais je pensais que si je pouvais obtenir des données de LINE, que j'utilise fréquemment, je pourrais les utiliser de différentes manières, alors je me suis demandé si je pourrais d'une manière ou d'une autre obtenir des informations sur l'échange.

J'utilise cette méthode pour publier une application appelée "Pickup Notification Sound" qui permet aux sons de notification LINE et aux sonneries de sonner séparément sur Google Play! https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409628/e48b6416-da86-2db1-0c9a-0c1a5c4be66e.png https://play.google.com/store/apps/details?id=rabbitp.sns.notifisort https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409628/a4ce1b87-24e8-d6ae-c0ac-1e4ed07cf6f4.png Google Play et le logo Google Play sont des marques de commerce de Google LLC.

Pour expliquer comment faire grosso modo ...

Le message arrive sur LINE ↓ La notification est affichée ↓ Recevez des notifications à l'aide de la fonction "Accéder aux notifications" d'Android ↓ Ne supprimez que les informations dont vous avez besoin

C'est comme ça. Je vous montrerai comment le faire plus tard. (Si vous souhaitez ignorer l'introduction, cliquez sur [ici](# tableau de la méthode de scraping))

Avant de gratter ... "Comment recevoir des notifications"

Il est pratique de l'utiliser car il existe un projet de référence. Cliquez ici → https://github.com/oggata/NotificationListenerServiceDemo Si vous ouvrez Android Studio après le téléchargement, cela ressemblera à ceci: 000261.png Puisqu'il s'agit d'un projet 2015, un avertissement sera affiché car la version Gradle est ancienne. Ouvrez le menu Fichier → Structure du projet ..., remplacez la version du plug-in Android Gradle et la version Gradle par n'importe laquelle, puis cliquez sur OK. 000262.png (J'ai utilisé le plug-in 4.0.0 et Gradle 6.1.1.)

Après avoir cliqué sur OK, si vous voyez un écran comme celui-ci, modifiez les deux parties de «référentiels» comme suit. 000263.png

build.gradle


buildscript {
    repositories {
        google()
        jcenter()
    }
    
    ...réduction

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url "https://jitpack.io"
        }
    }
}

Une fois le correctif terminé, cliquez sur Réessayer en haut à gauche et attendez la fin de la synchronisation.

Ensuite, une erreur apparaîtra à nouveau, alors supprimez "targetSdkVersion 21" dans build.gradle, cliquez sur le lien "Supprimer minSdkVersion et synchroniser le projet", et supprimez la description suivante. 000264.png

AndroidManifest.xml


<uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="18" />

...Autres parties omises

Après l'avoir supprimé, ouvrez à nouveau build.gradle et cliquez sur "Synchroniser maintenant" dans le coin supérieur droit. Cela devrait effacer toutes les erreurs.

Ce projet consiste à "afficher les données brutes sous forme de superposition coulant du haut de l'écran lorsqu'une notification arrive", mais c'est un peu gênant à utiliser pour la confirmation, nous allons donc l'améliorer.

Ajouter un bouton pour ouvrir l'écran des paramètres "Notification d'accès"

Placez un bouton dans activity_main.xml et ajoutez le programme suivant.

MainActivity.java


        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Écran d'autorisation de notification
                Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
                startActivity(intent);
            }
        });

Arrêter la superposition et afficher dans EditText

J'ai pensé que ce serait bien de pouvoir copier, donc cette fois j'utiliserai EditText au lieu de TextView. Placez EditText sur le plein écran de activity_main.xml et ajoutez le programme suivant.

MainActivity.java


public class MainActivity extends Activity {
    EditText editText;
    String log = "";

...réduction

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = (EditText) findViewById(R.id.editText);

...réduction

    class NotificationReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String msg = intent.getStringExtra("notification_msg") + "\n";
            
            final DateFormat df = new SimpleDateFormat("MM/dd HH:mm:ss");
            final Date date = new Date(System.currentTimeMillis());
            log=df.format(date)+"\n"+msg+"----------------\n"+log;

            editText.setText(log);
        }
    }
}

La nouvelle notification sera affichée en haut.

Ajouter un bouton de réinitialisation

Ajoutez un bouton pour réinitialiser le journal et l'affichage. Placez un bouton dans activity_main.xml et ajoutez le programme suivant.

MainActivity.java


        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //réinitialiser
                log="";
                editText.setText("");
            }
        });

Obtenez des informations détaillées sur les notifications

Vous pouvez également utiliser "sbn.getNotification (). Extras" pour obtenir des informations qui ne sont pas réellement affichées dans la notification. Vous pouvez obtenir le nom de l'expéditeur, le texte intégral du message, etc. à partir de là.

NLService.java


...réduction

            i.putExtra("notification_msg", ""
                    + "ID :" + sbn.getId() + "\n"
                    + "Txt :" + sbn.getNotification().tickerText + "\n"
                    + "Pkg :" + sbn.getPackageName() + "\n"
                    + "Tim :" + sbn.getPostTime() + "\n"
                    + "extras :" + sbn.getNotification().extras+"\n"
                    + "\n");

...réduction

Écran d'exécution de l'application

Il y a quelques changements dans la mise en page, etc. https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409628/6d2f3141-695c-2efc-b2e8-9764cc7f5ad2.png

Tableau des méthodes de grattage

Par souci de clarté, nous avons organisé chaque information que vous souhaitez gratter.

[Discrimination]
Notification LINE
message ou appel gratuit
[Pour les messages]
nom de l'expéditeur
nom du groupe cible
contenu du message
URL du tampon de ligne envoyé
Image de profil de l'expéditeur
ID de chat
Marquée ou lorsque la notification est supprimée
[Pour les appels gratuits]
Commencer à appeler
Appel entrant
appel manqué
Lancer l'appel
Mettre fin à l'appel

À propos de la fonction countStringInString

Une partie du programme utilise la fonction countStringInString, qui compte le nombre de fois qu'un caractère apparaît.

    //Obtenez le nombre d'apparitions de personnages
    public static int countStringInString(String target, String searchWord) {
        //return (target.length() - target.replaceAll(searchWord, "").length()) / searchWord.length();

        Pattern p = Pattern.compile(searchWord);
        Matcher m = p.matcher(target);
        String result = m.replaceAll("");

        int out = target.length() - result.length();
        return out;
    }

La discrimination

S'il s'agit d'une notification LINE

Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        if(sbn.getPackageName().equals("jp.naver.line.android")) {
            //Décrivez ici le traitement que vous souhaitez effectuer lorsque vous recevez une notification LINE
            
        }

Message ou appel gratuit

Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        if (String.valueOf(sbn.getId()).indexOf("880002") != -1 || String.valueOf(sbn.getId()).equals("110000")) {
             //Pour un appel manqué ou un identifiant de notification d'appel gratuit → Appel gratuit
             
        } else {
             //Sinon → message
             
        }

Emplacement de la description: dans «onNotificationRemoved» de «NLService.java»

NLService.java


        if (String.valueOf(sbn.getId()).equals("110000")) {
             //Lorsque l'appel gratuit est rejeté ou que le bouton de fin est enfoncé et que l'appel se termine → Appel gratuit
             
        }

Pour les messages

Nom de l'expéditeur

Vous pouvez obtenir le nom de la personne qui l'a envoyé. Il peut être obtenu pour les cas individuels et collectifs. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        //Façonner
        String ex=String.valueOf(sbn.getNotification().extras);
        ex=ex.substring(8);  //Supprimer 8 caractères du début "Bundle[{」
        String[] extars = ex.split(",");
        int dir = countStringInString(ex, ",");  //「,Nombre de

        //Extraire le nom de l'expéditeur
        String Name="";
        for (int a = 0; a < dir; a++){
            if(extars[a].indexOf("android.title=")==0){
                //"Android" au début.title=Entré → Nom de l'expéditeur
                Name = extars[a].substring(14);  //Supprimer les caractères du début "android.title=」
                break;
            }
        }
        if(Name.indexOf(" - ")!=-1){
            //Dans la série Android 5/6, le nom est "[Nom de l'expéditeur] - [nom de groupe]"devenir
            Name=Name.split(" - ")[0];
        }
        //Nom: nom de l'expéditeur

Nom du groupe cible

Vous pouvez obtenir le nom du groupe auquel le message a été envoyé. Null est retourné s'il s'agissait d'un individu plutôt que d'un groupe. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        //Façonner
        String ex=String.valueOf(sbn.getNotification().extras);
        ex=ex.substring(8);  //Supprimer 8 caractères du début "Bundle[{」
        String[] extars = ex.split(",");
        int dir = countStringInString(ex, ",");  //「,Nombre de
        
        //Extraire le nom du groupe
        String GroupName="";
        for (int a = 0; a < dir; a++){
            if(extars[a].indexOf("android.title=")==0){
                //"Android" au début.title=Entré → Nom de l'expéditeur
                GroupName = extars[a].substring(14);  //Supprimer les caractères du début "android.title=」
                break;
            }
        }
        if(GroupName.indexOf(" - ")!=-1){
            //Dans la série Android 5/6, le nom est "[Nom de l'expéditeur] - [nom de groupe]"devenir
            GroupName=Name.split(" - ")[1];
        }else {
            GroupName=sbn.getNotification().extras.getString(Notification.EXTRA_CONVERSATION_TITLE);
            if(GroupName!=null){
                Name=Name.substring(GroupName.length()+2);  //Au début ":Est donné, alors supprimez-le
            }
        }
        //GroupName: nom du groupe

Contenu du message

Vous pouvez recevoir le message envoyé. Même si "..." est affiché dans la notification et omis, le texte intégral peut être obtenu. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        //Extraire le contenu
        String Text = sbn.getNotification().extras.getString(Notification.EXTRA_TEXT);
        //Texte: Contenu

URL du tampon LINE envoyé

URL commençant par " https://stickershop.line-scdn.net/products/ " et se terminant par ".png " Peut être obtenu. Il est également possible d'afficher l'image du tampon par HTTP GET en fonction de cette URL. (Comment afficher l'image par HTTP GET: https://akira-watson.com/android/httpurlconnection-get.html) S'il ne s'agit pas d'un tampon, null est renvoyé. À propos, la taille de l'image varie en fonction du tampon, mais elle est d'environ 120 pixels ou plus. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        //Extraire l'URL de l'image du tampon
        String StampURL="null";
        for (int a = 0; a < dir; a++){
            if(extars[a].indexOf(" line.sticker.url=")==0){
                //"Ligne" au début.sticker.url="→ URL de l'image du tampon
                StampURL = extars[a].substring(18);  //Supprimer 18 caractères de la «ligne» de début.sticker.url=」
                break;
            }
        }
        //StampURL: URL de l'image du tampon

Photo de profil de l'expéditeur

Puisqu'il peut être obtenu en tant que type Bitmap, il peut être affiché dans ImageView ou enregistré au format PNG. La taille de l'image est de 108 px x 108 px. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        Bitmap LargeIcon = drawableToBitmap(sbn.getNotification().getLargeIcon().loadDrawable(NLService.this));

...réduction

    //Convertir le type Drawable en type Bitmap
    public static Bitmap drawableToBitmap (Drawable drawable) {
        Bitmap bitmap = null;

        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            if(bitmapDrawable.getBitmap() != null) {
                return bitmapDrawable.getBitmap();
            }
        }

        if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }

ID de chat

Un identifiant qui est fixe pour chaque ami ou groupe. Vous pouvez l'utiliser pour déterminer si vous avez des amis ou des groupes portant le même nom. Peut-être que la fonctionnalité "Créer un raccourci de conversation" de LINE est un schéma d'URL qui utilise cet identifiant, mais je ne l'ai pas trouvé lors de la recherche ...

NLService.java


        //Façonner
        String ex=String.valueOf(sbn.getNotification().extras);
        ex=ex.substring(8);  //Supprimer 8 caractères du début "Bundle[{」
        String[] extars = ex.split(",");
        int dir = countStringInString(ex, ",");  //「,Nombre de
        
        //Extraire l'ID de chat
        String ChatID="";
        for (int a = 0; a < dir; a++){
            if(extars[a].indexOf("line.chat.id=")==0){
                //"Ligne" au début.chat.id=Entré → ID de chat
                ChatID = extars[a].substring(13);  //Supprimer 13 caractères de la «ligne» de début.chat.id=」
                break;
            }
        }
        //ChatID: ID de chat

Marqué comme lu ou lorsque la notification est supprimée

Appelé lorsque vous ouvrez l'écran de conversation LIGNE et que vous le marquez comme lu ou que vous supprimez la notification de message. Emplacement de la description: dans «onNotificationRemoved» de «NLService.java»

NLService.java


        if (String.valueOf(sbn.getId()).indexOf("880000") != -1) {  //Soit 15880000 ou 16880000?
            //Marqué comme lu ou lorsque la notification est supprimée
            
        }

Pour des appels gratuits

Le processus est appelé dans le flux suivant.

Commencer à appeler

Appelé lorsque vous passez un appel. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        if (String.valueOf(sbn.getId()).indexOf("110000") != -1 && Text.indexOf("Sortant") != -1) {  //Soit 15880002 ou 1688002?
            //Commencer à appeler
            
        }

Appel entrant

Appelé lorsqu'un appel arrive. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        if (String.valueOf(sbn.getId()).indexOf("110000") != -1 && Text.indexOf("Appel entrant") != -1) {  //Soit 15880002 ou 1688002?
            //Appel entrant
            
        }

Appel manqué

Appelé lorsqu'il y a un appel entrant et que l'autre partie raccroche (appuie sur le bouton de rejet ou ne répond pas). Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        if (String.valueOf(sbn.getId()).indexOf("880002") != -1 && Name.equals("Appel manqué LINE")) {  //Soit 15880002 ou 1688002?
            //Appel manqué
            
        }

Lancer un appel

Il est appelé lorsque l'appel est lancé. Emplacement de la description: dans "onNotificationPosted" de "NLService.java"

NLService.java


        if (String.valueOf(sbn.getId()).indexOf("110000") != -1 && Text.indexOf("parlant") != -1) {  //Soit 15880002 ou 1688002?
            //Lancer un appel
            
        }

Fin d'appel

Appelé chaque fois que l'appel se termine de quelque manière que ce soit. Emplacement de la description: dans «onNotificationRemoved» de «NLService.java»

NLService.java


        if (String.valueOf(sbn.getId()).equals("110000")) {
            //Fin d'appel
            
        }

Mise en garde

C'est une méthode que j'ai trouvée en recevant réellement des notifications LINE et en vérifiant comment gratter avec succès. Veuillez noter qu'il est possible qu'il ne soit plus utilisable à l'avenir en fonction du changement de spécification de LINE. (En fait, il y a eu une modification majeure des spécifications en 2018, et certaines modifications ont été apportées en 2020.)

De plus, sous Android 7.0 (?), Il semble y avoir un problème que "onNotificationPosted" ne soit pas appelé lors de la tentative. Si vous souhaitez l'utiliser pour la vérification, veuillez utiliser Android 7.0 ou supérieur. Il est également recommandé de définir minSdkVersion sur 24 (Android 7.0) ou plus.

Site de référence

Recommended Posts

Récupérer diverses informations des notifications LINE