{"id":10,"date":"2012-04-28T21:07:00","date_gmt":"2012-04-28T21:07:00","guid":{"rendered":"http:\/\/cyol.fr\/blogwp\/?p=10"},"modified":"2013-11-14T16:27:11","modified_gmt":"2013-11-14T15:27:11","slug":"srdice-log-des-lancers-de-des","status":"publish","type":"post","link":"https:\/\/cyol.fr\/blog\/post\/srdice-log-des-lancers-de-des\/","title":{"rendered":"SRDice : Log des lancers de D\u00e9s"},"content":{"rendered":"<p><a href=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/icones\/Android_Robot_100.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-124\" title=\"Android_Robot_100\" alt=\"Logo Android\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/icones\/Android_Robot_100.png\" width=\"85\" height=\"100\" \/><\/a>Le logs des lancers de D\u00e9s est une fonctionnalit\u00e9 que j&rsquo;ai en t\u00eate depuis le d\u00e9but du d\u00e9veloppement de SRDice, mais je voulais d&rsquo;abord me familiariser avec des aspects plus simple (entr\u00e9e utilisateur-traitement-affichage retour) avant de me lancer dans le stockage et la restitution d&rsquo;information. Un premier pas dans ce sens avait \u00e9t\u00e9 franchi avec la <a title=\"D\u00e9v Android : Mise en place des Pr\u00e9f\u00e9rences\" href=\"https:\/\/cyol.fr\/blog\/post\/dev-android-mise-en-place-des-preferences\/\">mise en place des pr\u00e9f\u00e9rences<\/a>, m\u00eame si Android propose justement sur ce point un fonctionnement l\u00e9ger et surtout d\u00e9di\u00e9.<\/p>\n<p>Il est maintenant temps de s&rsquo;int\u00e9resser au stockage et \u00e0 la restitution d&rsquo;information, en l\u2019occurrence le log des lancers de D\u00e9s. Ceci posera notamment la base d&rsquo;une fonctionnalit\u00e9 \u00e0 venir : la gestion des Tests \u00c9tendus de Shadowrun, \u00e0 savoir des tests utilisant plusieurs lancers (Ou pas&#8230; Le test \u00e9tendu utilisera certainement une fonctionnalit\u00e9 de stockage de l&rsquo;information moins p\u00e9renne que le log).<\/p>\n<p><!--more--><\/p>\n<p>Un petit parcours rapide des diff\u00e9rentes options pour stocker de l&rsquo;information dans le cadre d&rsquo;un d\u00e9veloppement Android. Bien que d\u00e9cousu cot\u00e9 exemples de code, je vous met en lien cette page qui a l&rsquo;avantage de pr\u00e9senter clairement les solutions \u00e0 notre disposition : <a title=\"Le stockage sous Android\" href=\"http:\/\/www.mti.epita.fr\/blogs\/2010\/11\/17\/le-stockage-sous-android\/\" hreflang=\"fr\">http:\/\/www.mti.epita.fr\/blogs\/2010\/11\/17\/le-stockage-sous-android\/<\/a> (traduction FR de <a title=\"Android Data Storage\" href=\"http:\/\/developer.android.com\/guide\/topics\/data\/data-storage.html\" hreflang=\"en\">http:\/\/developer.android.com\/guide\/topics\/data\/data-storage.html<\/a> )<\/p>\n<p>Les solutions sont donc :<\/p>\n<ul>\n<li>Les pr\u00e9f\u00e9rences =&gt; Voir \u00e0 ce sujet mon billet sur la <a title=\"D\u00e9v Android : Mise en place des Pr\u00e9f\u00e9rences\" href=\"https:\/\/cyol.fr\/blog\/post\/dev-android-mise-en-place-des-preferences\/\">mise en place des pr\u00e9f\u00e9rences<\/a>, sp\u00e9cifiquement d\u00e9di\u00e9 \u00e0 la gestion des pr\u00e9f\u00e9rences, \u00e7a ne va pas \u00eatre utile ici.<\/li>\n<li>Le stockage interne =&gt; \u00c9crire des fichiers sur la m\u00e9moire interne de l&rsquo;Android<\/li>\n<li>Le stockage externe =&gt; \u00c9crire des fichiers sur la m\u00e9moire externe de l&rsquo;Android, comprendre une carte SD (SDCard) la plupart du temps<\/li>\n<li>La base de donn\u00e9e =&gt; Stocker l&rsquo;information dans une base de donn\u00e9e de type SQLite<\/li>\n<\/ul>\n<p>J&rsquo;ai choisi le stockage externe pour la bonne et simple raison que je pr\u00e9f\u00e8re garder l&rsquo;application aussi l\u00e9g\u00e8re que possible pour la m\u00e9moire interne, beaucoup d&rsquo;appareils tournant sur Android ayant une m\u00e9moire interne assez limit\u00e9e.<\/p>\n<h3>Etape 0 : D\u00e9clarer la permission dans le Manifest.xml<\/h3>\n<p>Vu que SRDice va maintenant \u00e9crire un fichier de log sur la carte SD, il faut qu&rsquo;il en ai la Permission. Pour cela, cette permission doit \u00eatre d\u00e9clar\u00e9e dans le fichier qui sert de pr\u00e9sentation de l&rsquo;application : AndroidManifest.xml<\/p>\n<p>C&rsquo;est dans ce fichier qu&rsquo;on d\u00e9clare la version actuelle de l&rsquo;appli (point que je mets \u00e0 jour \u00e0 chaque fois que je commence \u00e0 travailler sur une nouvelle fonctionnalit\u00e9, j&rsquo;en suis \u00e0 la 1.8), si l&rsquo;application peut (doit) s&rsquo;installer sur la Carte SD : installLocation=\u00a0\u00bbpreferExternal\u00a0\u00bb (personnellement je vire de mon Android toutes les appli incapables de faire \u00e7a&#8230;), les ic\u00f4nes de l&rsquo;appli et les activity \u00e0 lancer (avec le chemin).<\/p>\n<p>Et aussi donc, les Permissions :<\/p>\n<pre class=\"brush:xml\">&lt;manifest xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n\u00a0\u00a0\u00a0 package=\"fr.cyol.android.shadowrundice\"\r\n\u00a0\u00a0\u00a0 android:versionCode=\"8\"\r\n\u00a0\u00a0\u00a0 android:versionName=\"1.8\" android:installLocation=\"preferExternal\"&gt;\r\n\u00a0\u00a0\u00a0 <strong>&lt;uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"\/&gt;<\/strong><\/pre>\n<p>Un autre truc qu&rsquo;il faudra que je pense \u00e0 faire lors de la mise \u00e0 disposition de cette version : Expliquer le pourquoi de cette Permission suppl\u00e9mentaire dans la pr\u00e9sentation des nouveaut\u00e9s. Je pense qu&rsquo;il s&rsquo;agit l\u00e0 d&rsquo;un minimum de politesse envers les utilisateurs qui voient une application changer ses demandes de Permissions.<\/p>\n<p>(Personnellement j&rsquo;ai tendance \u00e0 virer de mon Android ou \u00e0 ne pas installer d&rsquo;applications qui demandent des Permissions qui me semblent non justifi\u00e9es par ses fonctionnalit\u00e9s pr\u00e9sent\u00e9es. A quoi servent ces autres Permissions, que fait l&rsquo;appli comme action qui ne m&rsquo;est pas pr\u00e9sent\u00e9, dont je n&rsquo;ai pas l&rsquo;utilit\u00e9 ?)<\/p>\n<h3>Etape 1 : v\u00e9rifier que la carte SD est disponible pour ne proposer la fonctionnalit\u00e9 que dans ce cas<\/h3>\n<p>Je disais que cette page :\u00a0<a title=\"Android Data Storage\" href=\"http:\/\/developer.android.com\/guide\/topics\/data\/data-storage.html\" hreflang=\"en\">http:\/\/developer.android.com\/guide\/topics\/data\/data-storage.html<\/a> \u00e9tait d\u00e9cousue cot\u00e9 exemples de code, je m&rsquo;explique: Il nous donne effectivement un bout de code bien utile pour v\u00e9rifier s&rsquo;il y a une m\u00e9moire externe de disponible et si on peut \u00e9crire dessus mais apr\u00e8s, il se contente de donner la fonction getExternalFilesDir sans trop d\u00e9tailler son fonctionnement. Mais voyons d\u00e9j\u00e0 le code propos\u00e9 (et utile!) :<\/p>\n<pre class=\"brush:java\">boolean mExternalStorageAvailable = false;\r\nboolean mExternalStorageWriteable = false;\r\nString state = Environment.getExternalStorageState();\r\n\r\nif (Environment.MEDIA_MOUNTED.equals(state)) {\r\n\u00a0\u00a0\u00a0 \/\/ We can read and write the media\r\n\u00a0\u00a0\u00a0 mExternalStorageAvailable = mExternalStorageWriteable = true;\r\n} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {\r\n\u00a0\u00a0\u00a0 \/\/ We can only read the media\r\n\u00a0\u00a0\u00a0 mExternalStorageAvailable = true;\r\n\u00a0\u00a0\u00a0 mExternalStorageWriteable = false;\r\n} else {\r\n\u00a0\u00a0\u00a0 \/\/ Something else is wrong. It may be one of many other states, but all we need\r\n\u00a0\u00a0\u00a0 \/\/\u00a0 to know is we can neither read nor write\r\n\u00a0\u00a0\u00a0 mExternalStorageAvailable = mExternalStorageWriteable = false;\r\n}<\/pre>\n<p>Que dire de plus ? C&rsquo;est un bel exemple de code bien comment\u00e9 qui r\u00e9pond \u00e0 toutes les questions (en tous cas aux miennes ! Si vous en avez, n&rsquo;h\u00e9sitez pas \u00e0 les poser.)<\/p>\n<p>Sur la fen\u00eatre de restitution du r\u00e9sultat du jet, l\u00e0 o\u00f9 je proposais juste un bouton \u00ab\u00a0OK\u00a0\u00bb,si mExternalStorageAvailable et mExternalStorageWriteable sont \u00e0 true, je propose d\u00e9sormais en plus un bouton \u00ab\u00a0Save\u00a0\u00bb.<\/p>\n<h3>Etape 2 : Cr\u00e9er et \u00e9crire un fichier de log<\/h3>\n<p>Maintenant qu&rsquo;on s&rsquo;est assur\u00e9 de la possibilit\u00e9 d&rsquo;\u00e9crire sur la m\u00e9moire externe, \u00e9crivons y le log ! Tout d&rsquo;abord quelques liens sources d&rsquo;inspiration et de compr\u00e9hensions sur le sujet :<\/p>\n<ul>\n<li><a title=\"Android Developers : public abstract File getExternalFilesDir (String type)\" href=\"http:\/\/developer.android.com\/reference\/android\/content\/Context.html#getExternalFilesDir%28java.lang.String%29\" hreflang=\"en\">http:\/\/developer.android.com\/reference\/android\/content\/Context.html#getExternalFilesDir%28java.lang.String%29<\/a><\/li>\n<li><a title=\"Android Developers : Using the External Storage\" href=\"http:\/\/developer.android.com\/guide\/topics\/data\/data-storage.html#filesExternal\" hreflang=\"en\">http:\/\/developer.android.com\/guide\/topics\/data\/data-storage.html#filesExternal<\/a><\/li>\n<li><a title=\"[Android][Java] Simuler une sd-card, ajouter des fichiers et y acc\u00e9der dans une application Android\" href=\"http:\/\/blog.developpez.com\/android23\/p8541\/android\/creer-un-sd-card-ajouter-des-fichiers-et\/\" hreflang=\"fr\">http:\/\/blog.developpez.com\/android23\/p8541\/android\/creer-un-sd-card-ajouter-des-fichiers-et\/<\/a><\/li>\n<\/ul>\n<p>Quand l&rsquo;utilisateur clique sur le bouton \u00ab\u00a0Save\u00a0\u00bb, je d\u00e9clenche cette fonction :<\/p>\n<pre class=\"brush:java\">\/**\r\n * @desc inscrire le r\u00e9sultat dans un fichier de log\r\n * @param bundle contient les r\u00e9sultats\r\n *\/\r\nprivate void _saveResult(Bundle bundle) {\r\n\tString LOG =\"log.txt\";\r\n\tFile logFile = new File(Environment.getExternalStorageDirectory(), LOG);\r\n\tString currentDateTimeString = _getCurrentDateTimeString();\r\n\tString resultMessage = bundle.getString(\"resultats\");\r\n\ttry {\r\n\t\tlogFile.createNewFile();\r\n\t\tFileWriter filewriter = new FileWriter(logFile,false);\r\n\t\tfilewriter.write(currentDateTimeString + \" :\\n\");\r\n\t\tfilewriter.write(resultMessage);\r\n\t\tfilewriter.close();\r\n\t\tToast.makeText(getApplicationContext(), R.string.log_saved,Toast.LENGTH_SHORT).show();\r\n\t} catch (IOException e) {\r\n\t\te.printStackTrace();\r\n\t\tToast.makeText(getApplicationContext(), R.string.log_error,Toast.LENGTH_SHORT).show();\r\n\t}\r\n}<\/pre>\n<p>Pour la fonction _getCurrentDateTimeString() je vous renvoie au billet <a title=\"D\u00e9v Android : attention \u00e0 l\u2019import de classe Date\" href=\"https:\/\/cyol.fr\/blog\/post\/dev-android-attention-a-l-import-de-classe-date\/\">D\u00e9v Android : attention \u00e0 l&rsquo;import de classe Date<\/a><\/p>\n<p>Petits probl\u00e8mes en l&rsquo;\u00e9tat :<\/p>\n<ul>\n<li>Le log s&rsquo;inscrit \u00e0 la racine de la carte SD et non pas comme j&rsquo;avais cru le comprendre dans un dossier d\u00e9di\u00e9 de l&rsquo;application<\/li>\n<li>A chaque fois que j&rsquo;\u00e9cris, j&rsquo;\u00e9crase ce qu&rsquo;il y avait d\u00e9j\u00e0 dans le fichier de log.<\/li>\n<\/ul>\n<h4>R\u00e9solution de ces probl\u00e8mes :<\/h4>\n<p>Je n&rsquo;ai pas trouv\u00e9 de m\u00e9thode magique ciblant un dossier d\u00e9di\u00e9 \u00e0 l&rsquo;application, donc on le cr\u00e9e<\/p>\n<pre class=\"brush:java\">String DIR = \"SRDiceInfos\";\r\nString LOG = \"log.txt\";\r\nFile sdCard = Environment.getExternalStorageDirectory();\r\nFile dir = new File (sdCard.getAbsolutePath() + \"\/\" + DIR);\r\ndir.mkdirs();\r\nFile logFile = new File(dir, LOG);<\/pre>\n<p>Un truc qui me d\u00e9range maintenant est qu&rsquo;on ne va pas cr\u00e9er le dossier s&rsquo;il existe d\u00e9j\u00e0. Apr\u00e8s v\u00e9rification dans la doc, il semble que <a title=\"Android Developers function mkdirs\" href=\"http:\/\/developer.android.com\/reference\/java\/io\/File.html\" hreflang=\"en\">mkdirs()<\/a> retourne true si le dossier a \u00e9t\u00e9 cr\u00e9\u00e9, false dans le cas contraire. Dans le false, il y a la possibilit\u00e9 que le dossier existe d\u00e9j\u00e0 mais aussi celle o\u00f9 la cr\u00e9ation a \u00e9chou\u00e9 pour une autre raison, du coup, je fais une v\u00e9rification suppl\u00e9mentaire avec <a title=\"Android Developers function isDirectory\" href=\"http:\/\/developer.android.com\/reference\/java\/io\/File.html#isDirectory%28%29\" hreflang=\"en\">isDirectory()<\/a> avant d&rsquo;essayer d&rsquo;\u00e9crire :<\/p>\n<pre class=\"brush:java\">if(dir.mkdirs() == true || dir.isDirectory() == true)<\/pre>\n<p><a title=\"Android Developers function createNewFile\" href=\"http:\/\/developer.android.com\/reference\/java\/io\/File.html\" hreflang=\"en\">createNewFile()<\/a> n&rsquo;est visiblement pas le plus n\u00e9cessaire, ils proposent plut\u00f4t d&rsquo;en utiliser d&rsquo;autre qui font aussi la cr\u00e9ation de fichier tout en offrant la possibilit\u00e9 de lire ou d&rsquo;\u00e9crire. En fait <a title=\"Android Developers function FileWriter\" href=\"http:\/\/developer.android.com\/reference\/java\/io\/FileWriter.html\" hreflang=\"en\">FileWriter()<\/a> que j&rsquo;utilise le fait par exemple.<\/p>\n<p>Pour le second probl\u00e8me, la solution est bien simple et est due \u00e0 une erreur de copier-coller. La fonction <a title=\"Android Developers function FileWriter\" href=\"http:\/\/developer.android.com\/reference\/java\/io\/FileWriter.html\" hreflang=\"en\">FileWriter()<\/a> prend en second argument facultatif un bool\u00e9en disant si on \u00e9crase le contenu du fichier (false) ou si on \u00e9crit \u00e0 la suite (true).<\/p>\n<h3>Etape 3 : Consultation des logs<\/h3>\n<p>Cette fois, contrairement au r\u00e9sultat d&rsquo;un lancer, je ne veux pas d&rsquo;une esp\u00e8ce de popup, mais j&rsquo;aimerais essayer un v\u00e9ritable nouvel \u00e9cran, ce qui implique, si j&rsquo;ai bien tout compris une nouvelle Activity !<\/p>\n<p>Bon, par contre, \u00e7a fera le sujet d&rsquo;un nouveau billet et d&rsquo;une nouvelle version. Pour l&rsquo;instant je veux aller au plus vite et donc r\u00e9utiliser le maximum de fonctions d\u00e9j\u00e0 en place. On ajoute un nouvel \u00e9l\u00e9ment de menu proposant de consulter les logs.<\/p>\n<p>Le menu pourra faire lui aussi le sujet d&rsquo;un billet d\u00e9di\u00e9, mais un truc rapide en passant : Pour un \u00e9l\u00e9ment de menu, on peut d\u00e9finir un ic\u00f4ne.<\/p>\n<pre class=\"brush:xml\">android:icon=\"@android:drawable\/ic_menu_info_details<\/pre>\n<p>Android en propose une bonne base. Et voici un site o\u00f9 les visualiser tous pour mieux choisir celui qu&rsquo;il vous faut : <a title=\"Android R Drawables\" href=\"http:\/\/androiddrawableexplorer.appspot.com\/\">http:\/\/androiddrawableexplorer.appspot.com\/<\/a><\/p>\n<p>Avant d&rsquo;afficher la fen\u00eatre de dialogue je r\u00e9cup\u00e8re le contenu du fichier :<\/p>\n<pre class=\"brush:java\">\/**\r\n * Lit le fichier de log.txt\r\n * @return Bundle\r\n *\/\r\nprivate Bundle _getLogs() {\r\n\tBundle logBundle = new Bundle();\r\n\tif (dir.mkdirs() == true || dir.isDirectory() == true) {\r\n\t\tFile logFile = new File(dir, LOG);\r\n\t\t\/\/ Read text from file\r\n\t\tStringBuilder text = new StringBuilder();\r\n\t\t\ttry {\r\n\t\t\tBufferedReader br = new BufferedReader(new FileReader(logFile));\r\n\t\t\tString line;\r\n\t\t\t\twhile ((line = br.readLine()) != null) {\r\n\t\t\t\ttext.append(line);\r\n\t\t\t\ttext.append('\\n');\r\n\t\t\t}\r\n\t\t\t\tlogBundle.putString(\"resultats\", text.toString());\r\n\t\t} catch (IOException e) {\r\n\t\t\te.printStackTrace();\r\n\t\t\tlogBundle = null;\r\n\t\t}\r\n\t}\r\n\treturn logBundle;\r\n}<\/pre>\n<p>if (dir.mkdirs() == true || dir.isDirectory() == true) me sert \u00e0 v\u00e9rifier la pr\u00e9sence du dossier avant d&rsquo;essayer de lire le fichier.<\/p>\n<p>Utiliser un BufferedReader est conseill\u00e9 dans le cas d&rsquo;un FileReader pour des questions de performances (<a title=\"public class BufferedReader\" href=\"http:\/\/developer.android.com\/reference\/java\/io\/BufferedReader.html\" hreflang=\"en\">Informations sur le site de r\u00e9f\u00e9rence de d\u00e9veloppement Android<\/a> ). Il faudra que je vois \u00e0 creuser cette question, je ne suis pas certain de l&rsquo;utilit\u00e9 de la chose dans mon cas.<\/p>\n<p>Les deux boutons sont : OK pour fermer la fen\u00eatre de dialogue et l&rsquo;autre pour vider les logs.<\/p>\n<p>Pour les vider, je me contente de supprimer le fichier log.txt :<\/p>\n<pre class=\"brush:java\">File logFile = new File(dir, LOG);\r\nboolean deleted = logFile.delete()<\/pre>\n<p>J&rsquo;ai encore quelques points \u00e0 revoir, notamment une optimisation \u00e0 mener sur la fa\u00e7on dont je g\u00e8re les Dialog. Ce sera le <a title=\"D\u00e9v Android : les Dialog (probl\u00e8me de persistance du contenu avec onCreateDialog)\" href=\"https:\/\/cyol.fr\/blog\/post\/dev-android-les-dialog-probleme-de-persistance-du-contenu-avec-oncreatedialog\/\">prochain billet<\/a>.<\/p>\n<p>Quelques id\u00e9es pour la suite :<\/p>\n<ul>\n<li>Proposer dans les pr\u00e9f\u00e9rences un choix \u00ab\u00a0Logguer tous les jets\u00a0\u00bb, \u00ab\u00a0Demander \u00e0 chaque jet\u00a0\u00bb, \u00ab\u00a0Ne jamais logguer\u00a0\u00bb<\/li>\n<li>Enregistrer les log de mani\u00e8re ant\u00e9chronologique (nouveau log en haut du fichier et non pas en bas)<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Le logs des lancers de D\u00e9s est une fonctionnalit\u00e9 que j&rsquo;ai en t\u00eate depuis le d\u00e9but du d\u00e9veloppement de SRDice, mais je voulais d&rsquo;abord me familiariser avec des aspects plus simple (entr\u00e9e utilisateur-traitement-affichage retour) avant de me lancer dans le stockage et la restitution d&rsquo;information. Un premier pas dans ce sens avait \u00e9t\u00e9 franchi avec la mise en place des pr\u00e9f\u00e9rences, m\u00eame si Android propose justement sur ce point un fonctionnement l\u00e9ger et surtout d\u00e9di\u00e9. Il est maintenant temps de s&rsquo;int\u00e9resser au stockage et \u00e0 la restitution d&rsquo;information, en l\u2019occurrence le log des lancers de D\u00e9s. [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":124,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,2,4],"tags":[26,114,30,15,62,34,47,36,19,51,112,32],"class_list":["post-10","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-developpement","category-srdice","tag-activity","tag-android","tag-androidmanifest","tag-des","tag-developpement-2","tag-dialog","tag-preferences","tag-sdcard","tag-shadowrun","tag-sqlite","tag-srdice","tag-tests-etendus","odd"],"_links":{"self":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts\/10","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/comments?post=10"}],"version-history":[{"count":9,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts\/10\/revisions"}],"predecessor-version":[{"id":373,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts\/10\/revisions\/373"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/media\/124"}],"wp:attachment":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/media?parent=10"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/categories?post=10"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/tags?post=10"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}