/* * Copyright 2014, 2015, 2016 Anael Mobilia * * This file is part of NextINpact-Unofficial. * * NextINpact-Unofficial is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NextINpact-Unofficial is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NextINpact-Unofficial. If not, see <http://www.gnu.org/licenses/> */ package com.pcinpact.network; import android.content.Context; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.util.Log; import android.widget.Toast; import com.pcinpact.R; import com.pcinpact.datastorage.DAO; import com.pcinpact.items.ArticleItem; import com.pcinpact.items.CommentaireItem; import com.pcinpact.items.Item; import com.pcinpact.parseur.ParseurHTML; import com.pcinpact.utils.Constantes; import java.util.ArrayList; import java.util.Date; import java.util.concurrent.RejectedExecutionException; /** * téléchargement du code HTML. * * @author Anael */ public class AsyncHTMLDownloader extends AsyncTask<String, Void, ArrayList<? extends Item>> { /** * Parent qui sera rappelé à la fin. */ private final RefreshDisplayInterface monParent; /** * URL de la page. */ private final String urlPage; /** * Type de la ressource. */ private final int typeHTML; /** * accès à la BDD. */ private final DAO monDAO; /** * Context de l'application. */ private final Context monContext; /** * Est-ce du contenu abonné ? */ private Boolean isAbonne = false; /** * téléchargement uniquement si connecté ? */ private Boolean uniquementSiConnecte = false; /** * DL avec gestion du compte abonné et de l'état de la connexion. * * @param parent parent à callback à la fin * @param unType type de la ressource (Cf Constantes.TYPE_) * @param uneURL URL de la ressource * @param unDAO accès sur la DB * @param unContext context de l'application * @param onlyifConnecte dois-je télécharger uniquement si le compte abonné est connecté ? */ public AsyncHTMLDownloader(final RefreshDisplayInterface parent, final int unType, final String uneURL, final DAO unDAO, final Context unContext, final Boolean onlyifConnecte) { // Mappage des attributs de cette Requête monParent = parent; urlPage = uneURL; typeHTML = unType; monDAO = unDAO; monContext = unContext.getApplicationContext(); isAbonne = true; uniquementSiConnecte = onlyifConnecte; // DEBUG if (Constantes.DEBUG) { Log.w("AsyncHTMLDownloader", "AsyncHTMLDownloader() - abonné " + urlPage + " - Uniquement si connecté : " + onlyifConnecte.toString()); } } /** * DL sans gestion du statut abonné. * * @param parent parent à callback à la fin * @param unType type de la ressource (Cf Constantes.TYPE_) * @param uneURL URL de la ressource * @param unDAO accès sur la DB * @param unContext context de l'application */ public AsyncHTMLDownloader(final RefreshDisplayInterface parent, final int unType, final String uneURL, final DAO unDAO, final Context unContext) { // Mappage des attributs de cette Requête monParent = parent; urlPage = uneURL; typeHTML = unType; monDAO = unDAO; monContext = unContext; // DEBUG if (Constantes.DEBUG) { Log.i("AsyncHTMLDownloader", "AsyncHTMLDownloader() - NON abonné : " + urlPage); } } @Override protected ArrayList<Item> doInBackground(String... params) { // Retour ArrayList<Item> mesItems = new ArrayList<>(); try { // Date du refresh long dateRefresh = new Date().getTime(); // Retour du Downloader byte[] datas; if (isAbonne) { // Je récupère mon contenu HTML en passant par la partie abonné datas = Downloader.downloadArticleAbonne(urlPage, monContext, uniquementSiConnecte); } else { // Je récupère mon contenu HTML directement datas = Downloader.download(urlPage, monContext); } // Vérifie que j'ai bien un retour (vs erreur DL) if (datas != null) { // Je convertis mon byte[] en String String contenu = new String(datas, Constantes.NEXT_INPACT_ENCODAGE); switch (typeHTML) { case Constantes.HTML_LISTE_ARTICLES: // Je passe par le parser ArrayList<ArticleItem> monRetour = ParseurHTML.getListeArticles(contenu, urlPage); // DEBUG if (Constantes.DEBUG) { Log.i("AsyncHTMLDownloader", "doInBackground() - HTML_LISTE_ARTICLES : le parseur à retourné " + monRetour.size() + " résultats"); } // Je ne conserve que les nouveaux articles for (ArticleItem unArticle : monRetour) { // Stockage en BDD if (monDAO.enregistrerArticleSiNouveau(unArticle)) { // Ne retourne que les nouveaux articles mesItems.add(unArticle); } } // MàJ de la date de MàJ uniquement si DL de la première page (évite plusieurs MàJ si dl de plusieurs // pages) if (urlPage.equals(Constantes.NEXT_INPACT_URL_NUM_PAGE + "1")) { // MàJ de la date de rafraichissement monDAO.enregistrerDateRefresh(Constantes.DB_REFRESH_ID_LISTE_ARTICLES, dateRefresh); } // DEBUG if (Constantes.DEBUG) { Log.i("AsyncHTMLDownloader", "doInBackground() - Au final " + mesItems.size() + " résultats"); } break; case Constantes.HTML_ARTICLE: // Je passe par le parser ArticleItem articleParser = ParseurHTML.getArticle(contenu, urlPage); // Chargement de l'article depuis la BDD ArticleItem articleDB = monDAO.chargerArticle(articleParser.getId()); // Ajout du contenu à l'objet chargé articleDB.setContenu(articleParser.getContenu()); // Article abonné ? if (articleDB.isAbonne()) { // Suis-je connecté ? boolean etatAbonne = Downloader.estConnecte(); // Suis-je connecté ? articleDB.setDlContenuAbonne(etatAbonne); } // Je viens de DL l'article => non lu articleDB.setLu(false); // Enregistrement de l'objet complet monDAO.enregistrerArticle(articleDB); // pas de retour à l'utilisateur, il s'agit d'un simple DL break; case Constantes.HTML_COMMENTAIRES: /** * MàJ des commentaires */ // Je passe par le parser ArrayList<CommentaireItem> lesCommentaires = ParseurHTML.getCommentaires(contenu, urlPage); // DEBUG if (Constantes.DEBUG) { Log.i("AsyncHTMLDownloader", "doInBackground() - HTML_COMMENTAIRES : le parseur à retourné " + lesCommentaires.size() + " résultats"); } // Je ne conserve que les nouveaux commentaires for (CommentaireItem unCommentaire : lesCommentaires) { // Stockage en BDD if (monDAO.enregistrerCommentaireSiNouveau(unCommentaire)) { // Ne retourne que les nouveaux articles mesItems.add(unCommentaire); } } // Calcul de l'ID de l'article concerné (entre "newsId=" et "&page=") int debut = urlPage.indexOf(Constantes.NEXT_INPACT_URL_COMMENTAIRES_PARAM_ARTICLE_ID + "="); debut += Constantes.NEXT_INPACT_URL_COMMENTAIRES_PARAM_ARTICLE_ID.length() + 1; int fin = urlPage.indexOf("&"); int idArticle = Integer.valueOf(urlPage.substring(debut, fin)); // MàJ de la date de rafraichissement monDAO.enregistrerDateRefresh(idArticle, dateRefresh); /** * MàJ du nombre de commentaires */ int nbCommentaires = ParseurHTML.getNbCommentaires(contenu, urlPage); monDAO.updateNbCommentairesArticle(idArticle, nbCommentaires); // DEBUG if (Constantes.DEBUG) { Log.i("AsyncHTMLDownloader", "doInBackground() - HTML_COMMENTAIRES : Au final, " + mesItems.size() + " résultats"); } break; default: if (Constantes.DEBUG) { Log.e("AsyncHTMLDownloader", "doInBackground() - type HTML incohérent : " + typeHTML + " - URL : " + urlPage); } break; } } else { // DEBUG if (Constantes.DEBUG) { Log.w("AsyncHTMLDownloader", "doInBackground() - contenu NULL pour " + urlPage + " - abonneUniquement = " + uniquementSiConnecte.toString()); } } } catch (Exception e) { // DEBUG if (Constantes.DEBUG) { Log.e("AsyncHTMLDownloader", "doInBackground()", e); } } return mesItems; } @Override protected void onPostExecute(ArrayList<? extends Item> result) { try { monParent.downloadHTMLFini(urlPage, result); } catch (Exception e) { // DEBUG if (Constantes.DEBUG) { Log.e("AsyncHTMLDownloader", "onPostExecute()", e); } } } /** * Lancement du téléchargement asynchrone * * @return résultat de la commande */ public boolean run() { boolean monRetour = true; try { // Parallélisation des téléchargements pour l'ensemble de l'application if (Build.VERSION.SDK_INT >= Constantes.HONEYCOMB) { this.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { this.execute(); } } catch (RejectedExecutionException e) { // DEBUG if (Constantes.DEBUG) { Log.e("AsyncHTMLDownloader", "run() - RejectedExecutionException (trop de monde en queue)", e); } // Je note l'erreur monRetour = false; // L'utilisateur demande-t-il un debug ? Boolean debug = Constantes.getOptionBoolean(monContext, R.string.idOptionDebug, R.bool.defautOptionDebug); // Retour utilisateur ? if (debug) { Handler handler = new Handler(monContext.getMainLooper()); handler.post(new Runnable() { @Override public void run() { Toast monToast = Toast.makeText(monContext, "Trop de téléchargements simultanés", Toast.LENGTH_SHORT); monToast.show(); } }); } } return monRetour; } }