Salut Habr!
Cher lecteur! Si vous êtes intéressé par l'analyse HTML et le développement Android, cet article est pour vous. J'espère que vous y trouverez beaucoup de choses intéressantes et utiles. J'y partage mon expérience dans ce domaine.
Description du problème
Un peu sur moi. Je suis un étudiant de troisième année de l'ITA SFU. Comme tous les élèves, je dois regarder le programme des cours tous les jours. Et j'ai besoin de connaître le calendrier non seulement le lendemain, mais aussi une ou deux semaines à l'avance.
Il semblerait, pourquoi ne pas simplement sauvegarder le programme et l'utiliser? Malheureusement, plusieurs raisons empêchent cela, à savoir:
- L'horaire d'une semaine peut être très différent de celui d'une autre
- L'horaire n'est pas constant et peut changer
Bien sûr, il existe un site avec un calendrier, mais ce n'est pas très pratique, car il affiche simplement un tableau brut avec un calendrier pour 20 semaines. L'étudiant doit retourner une grande page, à la recherche d'un horaire pour la journée souhaitée. De plus, en mode hors ligne, le programme devient indisponible.
J'ai décidé de faire une petite application qui pourrait analyser le site avec le calendrier de mon institut, et aurait l'ensemble de goodies suivant:
- Affichage: numéro de la semaine en cours, date, jour de la semaine et horaire pour ce jour
- La possibilité de faire défiler le calendrier avec les boutons "précédent" et "suivant"
- S'il n'y a pas d'Internet, affichez la dernière version hors ligne téléchargée du programme
Procéder à l'exécution
Alors, retroussant mes manches, je me mis au travail. Vous devez commencer petit. À savoir, de la modification du fichier manifeste. Il convient de rappeler que notre application fonctionnera avec Internet et il est très important pour nous d'obtenir l'autorisation appropriée:
Fichier manifesteAccédez à manifestes-> AndroidManifest.xml. Ajouter une autorisation. Le résultat est quelque chose comme ceci:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
Passons maintenant à l'interface. Pour l'instant, concentrons-nous sur les fonctionnalités et ne pas abuser des widgets. Par conséquent, je n'ai placé que quatre widgets: titre, zone de texte et boutons: d'avant en arrière.
Balisage d'activité <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/WeekNumber" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=" " app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/timetable" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="100dp" android:ems="10" android:inputType="textMultiLine" android:text="" app:layout_constraintTop_toBottomOf="@+id/WeekNumber" tools:layout_editor_absoluteX="0dp" /> <Button android:id="@+id/next" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" app:layout_constraintBottom_toBottomOf="parent" tools:layout_editor_absoluteX="0dp"></Button> <Button android:id="@+id/down" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" app:layout_constraintBottom_toTopOf="@+id/next" tools:layout_editor_absoluteX="0dp"></Button> </androidx.constraintlayout.widget.ConstraintLayout>
Commençons maintenant l'analyse. C'est là que le merveilleux analyseur open source Jsoup nous aide. J'ai immédiatement rejeté l'option en utilisant WebView, car j'ai trouvé cette méthode extrêmement gênante. De plus, je ne voulais pas vraiment utiliser un widget supplémentaire, sans lequel vous pouvez facilement le faire.
Connexion JsoupAjoutez la dépendance à build.gradle:
implementation 'org.jsoup:jsoup:1.11.1'
N'oubliez pas que travailler avec le Web pour Android est une tâche difficile. Pour empêcher l'application de se bloquer, vous devez travailler avec le Web situé à l'extérieur du flux d'interface utilisateur. Par conséquent, nous utiliserons la classe AsyncTask. Nous y mettrons les fonctionnalités de base, puis transférerons simplement les données vers le flux d'interface utilisateur.
Pour ceux qui ne connaissent pas AsyncTask, je veux dire que cette classe devrait être située à l'intérieur de la classe de votre activité. La classe elle-même est illustrée ci-dessous.
Code d'activité avec la classe AsyncTask package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class MainActivity extends AppCompatActivity { public boolean offline; public String request; public String WeekNumber; public int count;
En conséquence, nous obtenons les données sous cette forme:
Analysons les méthodes que nous avons utilisées:
Créer un élément de type Document
Document document = null;
Nous obtenons la page
document = Jsoup.connect(url).get();
Maintenant, nous obtenons le contenu de la balise body
answer = document.body().html();
Jsoup peut également récupérer le contenu d'autres balises principales. Par exemple, vous pouvez obtenir le titre de la page en utilisant la méthode title (), etc. Méthode Html () Renvoie du code html et text () est du texte brut sans balises html.
Après avoir reçu le code html, vous pouvez le convertir en texte brut, en supprimant toutes les balises. Cela peut être fait en utilisant parse (htmlcode) .text ():
return Jsoup.parse(answer).text();
Je voudrais partager quelques méthodes Jsoup plus utiles qui n'ont pas été utilisées:
Element link = document.select("tag");
L'image dans le spoiler ci-dessus est un exemple de programme d'une semaine. En fait, 20 de ces semaines nous seront retournées. Maintenant, notre tâche est de trouver aujourd'hui dans cet ensemble de données et de l'afficher.
Rappelant
Alors qu'avons-nous? Nous avons appris à convertir le code html d'une page en une chaîne qui peut être facilement analysée. Cela peut facilement être fait en utilisant les méthodes de chaîne .split () et .replace ().
En général, l'algorithme ressemblera à ceci.
D'abord, nous obtenons la date souhaitée d'Android. Ensuite, nous faisons deux cycles, l'un imbriqué dans l'autre. Le premier cycle se déroule chaque semaine, le second, qui est à l'intérieur, parcourt les jours de la semaine. Si la date du jour coïncide avec la date reçue d'Android, nous affichons le calendrier de cette journée dans la zone de texte. Cependant, chacun peut écrire cet algorithme à sa manière. J'ai joint ma version de sa mise en œuvre.
Code d'activité complet package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class MainActivity extends AppCompatActivity { public boolean offline; public String request; public String WeekNumber; public int count;
la récupération de la planification s'effectue dans la méthode formating (). En soumettant une date à la méthode de saisie, nous obtiendrons un calendrier pour cette journée. Nous pouvons donc facilement implémenter le code des boutons précédent et suivant
Code du bouton suivant:
count++; Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR,count); Date dayformat = calendar.getTime(); SimpleDateFormat format = new SimpleDateFormat("dd MMMM"); formating(format.format(dayformat));
En utilisant le calendrier, nous obtenons la date d'aujourd'hui. En utilisant la méthode add, nous ajoutons le nombre de jours enregistrés en nombre à la date d'aujourd'hui. Le code du bouton de retour sera similaire, seul le décompte devra diminuer la valeur.
Conclusion
Bien sûr, vous pouvez travailler sur la conception, mais c'est un autre sujet. Je voulais juste partager les technologies de base. Dans les spoilers ci-dessous, j'ai joint des captures d'écran avec un design amélioré. J'ai également ajouté plusieurs fonctions, par exemple: les paramètres, la possibilité de sélectionner un groupe d'étude, etc. L'application elle-même peut être consultée un peu plus tard, dès que j'y pense.
Capture d'écran de l'application