SlideShare uma empresa Scribd logo
1 de 33
Visualiser un document
dans une appli Android
       by Johann Hilbold
        & Alain Boudard
          @OxianeIT




                           1
Abstract

• Ce que je veux faire: afficher un document Office ou PDF dans une application
  Android
• Comment pallier à l‟absence de gestion native des documents Office et PDF?
• Présentation des différentes solutions
• Un retour sur expérience d‟une aventure folle
   Portabilité de Java vers Android
   Utilisation du code natif “quand y‟a pas le choix!”


                                                                                  2
Johann Hilbold & Alain Boudard

Développeur Android              Développeur Android
Développeur Swing à ses débuts   Webdesigner
Oxiane                           Oxiane Studio




                                                       3
Plan

•   Introduction
•   Contraintes
•   Solutions
•   Conclusion


                   4
Contraintes
• Ne pas sortir de l‟application pour ouvrir un document (!)
• Ne pas sortir le document du SI (= pas de google docs)
• Afficher des documents Office (Office 2003, 2007) et PDF




                                                               5
Solutions
• Afficher un document Office « binaire » dans une app
• Afficher un document Office « xml » dans une app
• Afficher un PDF dans une app




                                                         6
Afficher un fichier Office « binaire » - 1
C‟est l‟exemple le plus simple:

Il suffit d‟utiliser la librairie Apache POI.



3 jars à télécharger:
• poi-scratchpad-3.8.jar,
• poi-3.8.jar
• et commons-codec.jar


Copier des fichiers de test dans le répertoire Assets

                                                        7
Afficher un fichier Office « binaire » - 2
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
//copier les fichiers de test depuis mon répertoire assets vers la SDCard

    copyAssetToSDCard("test.doc");
    copyAssetToSDCard("testxls.xls");

//lancer la conversion avec les jars d'apache POI(source, dest)
    WordToHtmlConverter.main(new String[]{"/mnt/sdcard/test.doc",
"/mnt/sdcard/test.html"});
    ExcelToHtmlConverter.main(new String[]{"/mnt/sdcard/testxls.xls",
 "/mnt/sdcard/testxls.html"});
}

                                                                            8
Afficher un fichier Office « binaire » - 3
private final int BUF_SIZE = 8192;
private File copyAssetToSDCard(String assetName) {
       File copiedFileStoragePath = new File("/mnt/sdcard/"+assetName);
       BufferedInputStream bis = null;
       OutputStream dexWriter = null;
       try {
           bis = new BufferedInputStream(getAssets().open(assetName));
           dexWriter = new BufferedOutputStream(new FileOutputStream(copiedFileStoragePath));
           byte[] buf = new byte[BUF_SIZE];
           int len;
           while((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
               dexWriter.write(buf, 0, len);
           }
           dexWriter.close();
           bis.close();

      } catch (Exception e) {e.printStackTrace();
      return null;}
      Log.d("OfficeCopy", "copied "+assetName+" to /sdcard");
      return copiedFileStoragePath;
}


                                                                                                9
Afficher un fichier Office « binaire » - 4
                                   Et voila!

           Maintenant, on peut afficher le résultat dans une webview

WebView v = (WebView) findViewById(R.id.ma_web_view);
v.loadUrl("file://mnt/sdcard/test.html");



                                                 DEMO
                                                                       10
Afficher un document Office « xml » - 1
Apache POI offre des services de lecture/écriture de fichiers Open XML

Mais c‟est plus compliqué!

Si on essaye la méthode précédente (documents binaires)…

org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears
 to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2
 Office Documents. You need to call a different part of POI to process this data (eg
 XSSF instead of HSSF)




                                                                                       11
Afficher un document Office « xml » - 2
                         Utilisation d‟Apache POI – XSSF

Le plan:

Utiliser le même raisonnement que pour les documents « binaires »:
  • télécharger les jars pour les documents Open XML
      http://poi.apache.org/overview.html#components  OK!
  • Les ajouter au build path  OK!
  • Créer une petite classe pour appeler les bonnes méthodes
     org.apache.poi.ss.examples.html.ToHtml.main(String[] files)  OK!
  • Lancer le projet et prier!  NOK!



                                                                         12
Afficher un document Office « xml » - 3
Que s‟est-il passé?
Avant même de pouvoir installer l‟APK sur le device,

[Dex Loader] Unable to execute dex: null
[myProject] Conversion to Dalvik format failed: Unable to execute dex: null

Lors de la génération du fichier APK, tous les fichiers .class sont
 transformés en un unique fichier .dex (Dalvik EXecutable).

Cette transformation est limitée à 64k références de méthodes (!)
Nos jars (de 24Mo) pèsent plus de 64k méthodes!


                                                                              13
Afficher un document Office « xml » - 4
                La solution du blog Android Developper

Il « suffit » de découper nos classes en plusieurs fichiers .jar

Puis de lancer la dx.bat sur chacun des jars

Il convient d‟utiliser le script Ant fourni dans le SDK
android-sdktoolsantbuild.xml

Et de le modifier de la sorte:
<dex-helper-mod input-dir="${basedir}/libsToSpecialDEX/1"
output-dex-file="${out.absolute.dir}/onary_dex_dir/classes.dex"/>
<jar destfile="${asset.absolute.dir}/onary_dex.jar"
  basedir="${out.absolute.dir}/onary_dex_dir" includes="classes.dex"
  />
                                                                       14
Afficher un document Office « xml » - 5
                             Si tout s‟est bien passé…
On peut maintenant charger les classes en mémoire à l‟exécution

private Class loadClass(String className) {
    new File("/sdcard/office/opti").mkdirs();
    final File optimizedDexOutputPath = new File("/sdcard/office/opti");

    DexClassLoader cl = new DexClassLoader("/sdcard/office/one.jar:/sdcard/office/two.jar",
                                            optimizedDexOutputPath.getAbsolutePath(),
                                            null,
                                            TestOfficeAndroidActivity.this.getClassLoader());
    Class libProviderClazz = null;
    try {
        libProviderClazz = cl.loadClass(className);
    }
    catch(Exception e)
    {e.printStackTrace();}
    return libProviderClazz;
}
                                                                                                15
Afficher un document Office « xml » - 6
                       Une fois la classe chargée en mémoire…

Class cl = loadClass( "org.apache.poi.ss.examples.html.ToHtml");
Class[] paramTypes = new Class[] { String[].class };
Method main = cl.getMethod("main", paramTypes);
main.invoke(o, (Object) new String[] {"/sdcard/office/SampleSS.xlsx",
                                      "/sdcard/office/SampleSS.html"});



Et c‟est seulement à partir d‟ici que ça devient vraiment intéressant!

W/System.err(370): Caused by: java.lang.RuntimeException: Installation Problem???
 Couldn‟t load messages: Can‟t find resource for bundle
 „org.apache.xmlbeans.impl.regex.message_en_US‟, key »

                                                                                    16
Afficher un document Office « xml » - 7
                      Que peut bien vouloir dire cette erreur?
  Le fichier message.properties est introuvable !

 Il n‟est plus présent dans mon fichier dex!
 Mais présent dans XmlBeans-1.0.jar

La compilation en fichier APK, c‟est un zip avec
      un fichier .dex pour les .class (et uniquement les .class!)
      tout le reste (images, xml de layout, fichiers raw) dans des dossiers
     /res/drawable, /res/layout, /raw…

Le fichier .properties n‟est donc pas resté dans le .dex!



                                                                               17
Afficher un document Office « xml » - 8
                                         On peut tricher…
   XmlBeans est OpenSource!
 public void setLocale(Locale locale) {
   try {//this.resources = ResourceBundle.getBundle("org.apache.xmlbeans.impl.regex.message", locale);
     this.resources = new ResourceBundle() {
             @Override
             protected Object handleGetObject(String key) {
             return res.get(key);
             }
             @Override
             public Enumeration<String> getKeys() {
             return Collections.enumeration(res.keySet());
             }
       };
   } catch (MissingResourceException mre) {
  throw new RuntimeException("Installation Problem??? Couldn't load messages: "+mre.getMessage());
     }
}
static HashMap<String, String> res = new HashMap<String, String>();
static{res.put("parser.parse.1", "Wrong character.");}
                                                                                                         18
Afficher un document Office « xml » - 9
                               Cette fois-ci, ça va passer…
  Toujours pas!
  org.apache.xmlbeans.SchemaTypeLoaderException: XML-BEANS compiled schema: Could not locate
  compiled schema resource {…..}/index.xsb
  Les fichiers .xsb ne sont pas dans les .dex, mais cette fois, on sait pourquoi!
package org.apache.xmlbeans.impl.schema;
public class ClassLoaderResourceLoader{
public InputStream getResourceAsStream(String name) {
   try {
   return new
     FileInputStream("/sdcard/office/xsb/"+name.substring(name.lastIndexOf("/")+1));
   } catch (FileNotFoundException e) {e.printStackTrace();
   }   //_classLoader.getResourceAsStream(resourceName);
   return null;
}

                                                                                               19
Afficher un document Office « xml » - 10
                                 On tient le bout…

Maintenant qu‟on accède à toutes les ressources du jar original…

ClassNotFoundException: java.awt.Color

  POI est censé tourner sous Java 1.5
                                                              DEMO
  Android ne connait pas les packages java.awt (et quelques autres)

Une ultime manipulation:
   remplacer tous les java.awt par des and.awt dans les sources de POI
                      http://code.google.com/p/awt-android-compat/
Attention, le résultat n‟est pas parfait
   pas de gestion des images (pour l‟instant)
                                                                          20
Afficher un document Office « xml » - 11
Une approche plus sexy:
- Intégrer les ressources manquantes aux jars

- Création d‟un jar simple
- « Dexisation » du jar en un fichier classes.dex
- Réimportation des ressources dans un nouveau jar créé à la main  NOK!

Le dexloader n‟a pas l‟air de gérer les jars et les APK de la même façon
- Packaging du classes.dex dans un APK « maison »  OK!


- En réutilisant cette technique, on peut donc, en théorie, se passer des étapes précédentes



                                                         DEMO
                                                                                               21
Afficher un document Office « xml » - 12
                           Conclusion de la méthode POI

                         Le code complet est disponible ici:
     https://code.google.com/p/display-msoffice-docs-android-with-apache-poi/

Avantages:
• Permet une conversion très complète (celle que permet le client POI)
• Est très rapide (adaptée aux processeurs « lents » des mobiles d‟aujourd‟hui)
• Donne accès à tous les formats (doc/docx, ppt/pptx, xls/xlsx, et même Visio .vsd
  ou Outlook msg)
• Est chargeable dynamiquement en mémoire
• Laisse la porte ouverte à un futur « mode édition »


                                                                                     22
Afficher un document Office « xml » - 13
Inconvénients:
• Utilise énormément de place sur la SDcard (8Mo d‟APK + 15Mo de ressources)
• Compliqué à mettre en œuvre
• Pour la partie AWT, repose sur le package and.awt
   Pas de gestion des java.awt.BufferedImage. Il faudrait les convertir en
     android.graphics.Bitmap!




                                                                               23
Afficher un document Office « xml » - 14
                                             L‟alternative

La transformation XSL basée sur la solution de Julien Chable
     http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2006/11/21/openxmlandjava.aspx
• Un procédé beaucoup plus simple, mais moins efficace.
<!-- Body and paragraphs -->
<xsl:template match="w:body">
   <html>
   <body>
       <xsl:for-each select="w:p">
          <p>
              <xsl:apply-templates select="w:pPr" />
              <xsl:apply-templates select="w:r" />
          </p>
       </xsl:for-each>
   </body>
   </html>
</xsl:template>
                                                                                                  24
Afficher un document Office « xml » - 15
Avantages:
• D‟une légèreté déconcertante: mon APK fait seulement 261k
• D‟une simplicité déconcertante: un seul jar à ajouter au Build Path et c‟est fini.
• Facilement améliorable: il « suffit » d‟ajouter les balises qu‟on veut gérer

Inconvénients:
• Ne gère que les OfficeOpen XML (donc pas les formats « binaires »)
• Il faut trouver (ou écrire soi même?) un XSL vraiment complet pour un résultat
   parfait.
       Les images ne sont pas du tout gérées
       Seuls quelques styles sont implémentés, pas de formule, tableaux, wordart…



                                                                                       25
Afficher un document Office « xml » - 16
             Structure d‟un fichier docx




                                           26
Afficher un document Office « xml » - 17
Utilisation des rID pour retrouver le style ou le nom de fichier pour une image avec le
  fichier document.xml.rels

w:drawing crée une balise <img>
avec pour attribut id = rID

On extrait toutes les images de
/word/media vers la SDCard



2ème parsing:
  scan de toutes les balises img et ajout de l‟attribut grâce à la correspondance rID

                                                                                          27
Afficher un document Office « xml » - 18
     Malgré cette technique pour afficher les images, cette solution reste imparfaite

• Les positions des éléments ne sont pas gérées
• Les puces, formules, tableaux ne sont pas gérés

• Un exemple existant de traitement XSL de document duquel on pourrait s‟inspirer:
   DocBook

Mon code est disponible ici
   https://code.google.com/p/display-msoffice-docs-android-without-apache-poi/


                                              DEMO
                                                                                        28
Afficher un PDF -1
                         Une bonne occasion de voir le NDK

• Sous windows, installer Cygwin
  http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/
                                  (étapes 2 et 3)
• Télécharger le projet APV
  http://code.google.com/p/apv/

• Lancer la commande /script/build-native.sh du projet APV

• Si tout s‟est bien passé, on peut lancer le projet APV sous Eclipse!




                                                                               29
Afficher un PDF -2
          C‟est très bien mais c‟est pas ce qu‟on veut!
On vient de faire l‟équivalent d‟installer l‟appli « Acrobat Reader »




                       Fichier librairie qui permet de parser les PDFs




                                                                         30
Afficher un PDF -2
                                Customiser un peu…
Extraction de la View PagesView
• Par défaut, apv offre une view qui fait de nombreux appels à une activité.


Un composant personnalisé

<com.oxiane.DisplayPDF
        android:id="@+id/my_pdf_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        app:src="http://monpdf.com" />



                                                                               31
Afficher un PDF -3
                          Inconvénients de la méthode

• Pas de gestion des liens HTTP
• Encore 1,7Mo à rajouter à l‟APK!
• Chargement se fait en rectangles

                             Avantages de la méthode

  • Ça a le mérite de marcher!




                                                        32
Conclusion


• Une aventure pionnière!
• Un aperçu des possibilités qu‟offre l‟open source Java dans Android
• Des ouvertures pour arriver à des résultats plus professionnels




                                                                        33

Mais conteúdo relacionado

Mais procurados

Ajax et Accessibilite
Ajax et AccessibiliteAjax et Accessibilite
Ajax et Accessibilitemikeh
 
Tout ce que le getting started mongo db ne vous dira pas
Tout ce que le getting started mongo db ne vous dira pasTout ce que le getting started mongo db ne vous dira pas
Tout ce que le getting started mongo db ne vous dira pasPierre-Alban DEWITTE
 
Moteurs de recherche : un oeil sous le capot avec Elastic Search
Moteurs de recherche : un oeil sous le capot avec Elastic SearchMoteurs de recherche : un oeil sous le capot avec Elastic Search
Moteurs de recherche : un oeil sous le capot avec Elastic SearchAudrey Neveu
 
R2DOCX : R + WORD
R2DOCX : R + WORDR2DOCX : R + WORD
R2DOCX : R + WORDCdiscount
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScriptAbdoulaye Dieng
 
Fondamentaux d’une API REST
Fondamentaux d’une API RESTFondamentaux d’une API REST
Fondamentaux d’une API RESTAbdoulaye Dieng
 
Tout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pasTout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pasBruno Bonnin
 
Mop export-dataloader-salesforce-en-ligne-commande
Mop export-dataloader-salesforce-en-ligne-commandeMop export-dataloader-salesforce-en-ligne-commande
Mop export-dataloader-salesforce-en-ligne-commandeCyrille Coeurjoly
 
Workshop Spring - Session 4 - Spring Batch
Workshop Spring -  Session 4 - Spring BatchWorkshop Spring -  Session 4 - Spring Batch
Workshop Spring - Session 4 - Spring BatchAntoine Rey
 

Mais procurados (18)

Introduction à Symfony
Introduction à SymfonyIntroduction à Symfony
Introduction à Symfony
 
Ajax et Accessibilite
Ajax et AccessibiliteAjax et Accessibilite
Ajax et Accessibilite
 
Tout ce que le getting started mongo db ne vous dira pas
Tout ce que le getting started mongo db ne vous dira pasTout ce que le getting started mongo db ne vous dira pas
Tout ce que le getting started mongo db ne vous dira pas
 
Introduction à Laravel
Introduction à LaravelIntroduction à Laravel
Introduction à Laravel
 
Moteurs de recherche : un oeil sous le capot avec Elastic Search
Moteurs de recherche : un oeil sous le capot avec Elastic SearchMoteurs de recherche : un oeil sous le capot avec Elastic Search
Moteurs de recherche : un oeil sous le capot avec Elastic Search
 
Adopte une BDD
Adopte une BDDAdopte une BDD
Adopte une BDD
 
R2DOCX : R + WORD
R2DOCX : R + WORDR2DOCX : R + WORD
R2DOCX : R + WORD
 
Introduction à Symfony
Introduction à SymfonyIntroduction à Symfony
Introduction à Symfony
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScript
 
Fondamentaux d’une API REST
Fondamentaux d’une API RESTFondamentaux d’une API REST
Fondamentaux d’une API REST
 
Tout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pasTout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pas
 
Salesforce Tooling API
Salesforce Tooling APISalesforce Tooling API
Salesforce Tooling API
 
L'avenir de LAMP
L'avenir de LAMPL'avenir de LAMP
L'avenir de LAMP
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
 
Interfaces controlesbasededonné
Interfaces controlesbasededonnéInterfaces controlesbasededonné
Interfaces controlesbasededonné
 
Javascript
JavascriptJavascript
Javascript
 
Mop export-dataloader-salesforce-en-ligne-commande
Mop export-dataloader-salesforce-en-ligne-commandeMop export-dataloader-salesforce-en-ligne-commande
Mop export-dataloader-salesforce-en-ligne-commande
 
Workshop Spring - Session 4 - Spring Batch
Workshop Spring -  Session 4 - Spring BatchWorkshop Spring -  Session 4 - Spring Batch
Workshop Spring - Session 4 - Spring Batch
 

Semelhante a Affichage d'un document Office sous Android

Formation Efficy CRM - Technical training
Formation Efficy CRM - Technical trainingFormation Efficy CRM - Technical training
Formation Efficy CRM - Technical trainingEfficy CRM
 
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -introNosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -introOlivier Mallassi
 
log file sous Netbeans et J2ME
log file sous Netbeans et J2MElog file sous Netbeans et J2ME
log file sous Netbeans et J2MEZied
 
Génération de documents Office avec Open XML et VSTO
Génération de documents Office avec Open XML et VSTOGénération de documents Office avec Open XML et VSTO
Génération de documents Office avec Open XML et VSTOguested7f6
 
Presentation dublincore l3
Presentation dublincore l3Presentation dublincore l3
Presentation dublincore l3DublinCore2b
 
Framework Hibernate
Framework HibernateFramework Hibernate
Framework HibernateInes Ouaz
 
Hadoop Introduction in Paris
Hadoop Introduction in ParisHadoop Introduction in Paris
Hadoop Introduction in ParisTed Drake
 
Docker en Production (Docker Paris)
Docker en Production (Docker Paris)Docker en Production (Docker Paris)
Docker en Production (Docker Paris)Jérôme Petazzoni
 
Azure Camp 9 Décembre - slides session développeurs webmedia
Azure Camp 9 Décembre - slides session développeurs webmediaAzure Camp 9 Décembre - slides session développeurs webmedia
Azure Camp 9 Décembre - slides session développeurs webmediaMicrosoft
 
Exports de r vers office
Exports de r vers officeExports de r vers office
Exports de r vers officefrancoismarical
 
Hands on lab Elasticsearch
Hands on lab ElasticsearchHands on lab Elasticsearch
Hands on lab ElasticsearchDavid Pilato
 
4- Architectures physique et logique d'ODI 11
4-  Architectures physique et logique d'ODI 114-  Architectures physique et logique d'ODI 11
4- Architectures physique et logique d'ODI 11samr
 
Performance et optimisation de PrestaShop
Performance et optimisation de PrestaShopPerformance et optimisation de PrestaShop
Performance et optimisation de PrestaShopPrestaShop
 
ElasticSearch : Architecture et Développement
ElasticSearch : Architecture et DéveloppementElasticSearch : Architecture et Développement
ElasticSearch : Architecture et DéveloppementMohamed hedi Abidi
 
Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?GreenIvory
 

Semelhante a Affichage d'un document Office sous Android (20)

openFrameworks
openFrameworksopenFrameworks
openFrameworks
 
Spark - Ippevent 19-02-2015
Spark - Ippevent 19-02-2015Spark - Ippevent 19-02-2015
Spark - Ippevent 19-02-2015
 
Formation Efficy CRM - Technical training
Formation Efficy CRM - Technical trainingFormation Efficy CRM - Technical training
Formation Efficy CRM - Technical training
 
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -introNosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
 
log file sous Netbeans et J2ME
log file sous Netbeans et J2MElog file sous Netbeans et J2ME
log file sous Netbeans et J2ME
 
Génération de documents Office avec Open XML et VSTO
Génération de documents Office avec Open XML et VSTOGénération de documents Office avec Open XML et VSTO
Génération de documents Office avec Open XML et VSTO
 
Presentation dublincore l3
Presentation dublincore l3Presentation dublincore l3
Presentation dublincore l3
 
Big sql4meetup
Big sql4meetupBig sql4meetup
Big sql4meetup
 
Framework Hibernate
Framework HibernateFramework Hibernate
Framework Hibernate
 
Hadoop Introduction in Paris
Hadoop Introduction in ParisHadoop Introduction in Paris
Hadoop Introduction in Paris
 
Docker en Production (Docker Paris)
Docker en Production (Docker Paris)Docker en Production (Docker Paris)
Docker en Production (Docker Paris)
 
Elastic serach
Elastic serachElastic serach
Elastic serach
 
Outils front-end
Outils front-endOutils front-end
Outils front-end
 
Azure Camp 9 Décembre - slides session développeurs webmedia
Azure Camp 9 Décembre - slides session développeurs webmediaAzure Camp 9 Décembre - slides session développeurs webmedia
Azure Camp 9 Décembre - slides session développeurs webmedia
 
Exports de r vers office
Exports de r vers officeExports de r vers office
Exports de r vers office
 
Hands on lab Elasticsearch
Hands on lab ElasticsearchHands on lab Elasticsearch
Hands on lab Elasticsearch
 
4- Architectures physique et logique d'ODI 11
4-  Architectures physique et logique d'ODI 114-  Architectures physique et logique d'ODI 11
4- Architectures physique et logique d'ODI 11
 
Performance et optimisation de PrestaShop
Performance et optimisation de PrestaShopPerformance et optimisation de PrestaShop
Performance et optimisation de PrestaShop
 
ElasticSearch : Architecture et Développement
ElasticSearch : Architecture et DéveloppementElasticSearch : Architecture et Développement
ElasticSearch : Architecture et Développement
 
Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?
 

Mais de Stéphane Liétard

DevoxxFR Présentation des portails en 2014
DevoxxFR Présentation des portails en 2014DevoxxFR Présentation des portails en 2014
DevoxxFR Présentation des portails en 2014Stéphane Liétard
 
Introduction aux méthodes agiles pour conduite de projet
Introduction aux méthodes agiles pour conduite de projetIntroduction aux méthodes agiles pour conduite de projet
Introduction aux méthodes agiles pour conduite de projetStéphane Liétard
 
Google Web Toolkit 1.5 Presentation Web Creative Common
Google Web Toolkit 1.5 Presentation Web Creative CommonGoogle Web Toolkit 1.5 Presentation Web Creative Common
Google Web Toolkit 1.5 Presentation Web Creative CommonStéphane Liétard
 

Mais de Stéphane Liétard (7)

Présentation Oxiane 2016
Présentation Oxiane 2016Présentation Oxiane 2016
Présentation Oxiane 2016
 
Présentation OXiane 2015
Présentation OXiane 2015Présentation OXiane 2015
Présentation OXiane 2015
 
DevoxxFR Présentation des portails en 2014
DevoxxFR Présentation des portails en 2014DevoxxFR Présentation des portails en 2014
DevoxxFR Présentation des portails en 2014
 
Présentation OXiane Value
Présentation OXiane ValuePrésentation OXiane Value
Présentation OXiane Value
 
Introduction aux méthodes agiles pour conduite de projet
Introduction aux méthodes agiles pour conduite de projetIntroduction aux méthodes agiles pour conduite de projet
Introduction aux méthodes agiles pour conduite de projet
 
Usine Logicielle 2013
Usine Logicielle 2013Usine Logicielle 2013
Usine Logicielle 2013
 
Google Web Toolkit 1.5 Presentation Web Creative Common
Google Web Toolkit 1.5 Presentation Web Creative CommonGoogle Web Toolkit 1.5 Presentation Web Creative Common
Google Web Toolkit 1.5 Presentation Web Creative Common
 

Affichage d'un document Office sous Android

  • 1. Visualiser un document dans une appli Android by Johann Hilbold & Alain Boudard @OxianeIT 1
  • 2. Abstract • Ce que je veux faire: afficher un document Office ou PDF dans une application Android • Comment pallier à l‟absence de gestion native des documents Office et PDF? • Présentation des différentes solutions • Un retour sur expérience d‟une aventure folle  Portabilité de Java vers Android  Utilisation du code natif “quand y‟a pas le choix!” 2
  • 3. Johann Hilbold & Alain Boudard Développeur Android Développeur Android Développeur Swing à ses débuts Webdesigner Oxiane Oxiane Studio 3
  • 4. Plan • Introduction • Contraintes • Solutions • Conclusion 4
  • 5. Contraintes • Ne pas sortir de l‟application pour ouvrir un document (!) • Ne pas sortir le document du SI (= pas de google docs) • Afficher des documents Office (Office 2003, 2007) et PDF 5
  • 6. Solutions • Afficher un document Office « binaire » dans une app • Afficher un document Office « xml » dans une app • Afficher un PDF dans une app 6
  • 7. Afficher un fichier Office « binaire » - 1 C‟est l‟exemple le plus simple: Il suffit d‟utiliser la librairie Apache POI. 3 jars à télécharger: • poi-scratchpad-3.8.jar, • poi-3.8.jar • et commons-codec.jar Copier des fichiers de test dans le répertoire Assets 7
  • 8. Afficher un fichier Office « binaire » - 2 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //copier les fichiers de test depuis mon répertoire assets vers la SDCard copyAssetToSDCard("test.doc"); copyAssetToSDCard("testxls.xls"); //lancer la conversion avec les jars d'apache POI(source, dest) WordToHtmlConverter.main(new String[]{"/mnt/sdcard/test.doc", "/mnt/sdcard/test.html"}); ExcelToHtmlConverter.main(new String[]{"/mnt/sdcard/testxls.xls", "/mnt/sdcard/testxls.html"}); } 8
  • 9. Afficher un fichier Office « binaire » - 3 private final int BUF_SIZE = 8192; private File copyAssetToSDCard(String assetName) { File copiedFileStoragePath = new File("/mnt/sdcard/"+assetName); BufferedInputStream bis = null; OutputStream dexWriter = null; try { bis = new BufferedInputStream(getAssets().open(assetName)); dexWriter = new BufferedOutputStream(new FileOutputStream(copiedFileStoragePath)); byte[] buf = new byte[BUF_SIZE]; int len; while((len = bis.read(buf, 0, BUF_SIZE)) > 0) { dexWriter.write(buf, 0, len); } dexWriter.close(); bis.close(); } catch (Exception e) {e.printStackTrace(); return null;} Log.d("OfficeCopy", "copied "+assetName+" to /sdcard"); return copiedFileStoragePath; } 9
  • 10. Afficher un fichier Office « binaire » - 4 Et voila! Maintenant, on peut afficher le résultat dans une webview WebView v = (WebView) findViewById(R.id.ma_web_view); v.loadUrl("file://mnt/sdcard/test.html"); DEMO 10
  • 11. Afficher un document Office « xml » - 1 Apache POI offre des services de lecture/écriture de fichiers Open XML Mais c‟est plus compliqué! Si on essaye la méthode précédente (documents binaires)… org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF) 11
  • 12. Afficher un document Office « xml » - 2 Utilisation d‟Apache POI – XSSF Le plan: Utiliser le même raisonnement que pour les documents « binaires »: • télécharger les jars pour les documents Open XML http://poi.apache.org/overview.html#components  OK! • Les ajouter au build path  OK! • Créer une petite classe pour appeler les bonnes méthodes org.apache.poi.ss.examples.html.ToHtml.main(String[] files)  OK! • Lancer le projet et prier!  NOK! 12
  • 13. Afficher un document Office « xml » - 3 Que s‟est-il passé? Avant même de pouvoir installer l‟APK sur le device, [Dex Loader] Unable to execute dex: null [myProject] Conversion to Dalvik format failed: Unable to execute dex: null Lors de la génération du fichier APK, tous les fichiers .class sont transformés en un unique fichier .dex (Dalvik EXecutable). Cette transformation est limitée à 64k références de méthodes (!) Nos jars (de 24Mo) pèsent plus de 64k méthodes! 13
  • 14. Afficher un document Office « xml » - 4 La solution du blog Android Developper Il « suffit » de découper nos classes en plusieurs fichiers .jar Puis de lancer la dx.bat sur chacun des jars Il convient d‟utiliser le script Ant fourni dans le SDK android-sdktoolsantbuild.xml Et de le modifier de la sorte: <dex-helper-mod input-dir="${basedir}/libsToSpecialDEX/1" output-dex-file="${out.absolute.dir}/onary_dex_dir/classes.dex"/> <jar destfile="${asset.absolute.dir}/onary_dex.jar" basedir="${out.absolute.dir}/onary_dex_dir" includes="classes.dex" /> 14
  • 15. Afficher un document Office « xml » - 5 Si tout s‟est bien passé… On peut maintenant charger les classes en mémoire à l‟exécution private Class loadClass(String className) { new File("/sdcard/office/opti").mkdirs(); final File optimizedDexOutputPath = new File("/sdcard/office/opti"); DexClassLoader cl = new DexClassLoader("/sdcard/office/one.jar:/sdcard/office/two.jar", optimizedDexOutputPath.getAbsolutePath(), null, TestOfficeAndroidActivity.this.getClassLoader()); Class libProviderClazz = null; try { libProviderClazz = cl.loadClass(className); } catch(Exception e) {e.printStackTrace();} return libProviderClazz; } 15
  • 16. Afficher un document Office « xml » - 6 Une fois la classe chargée en mémoire… Class cl = loadClass( "org.apache.poi.ss.examples.html.ToHtml"); Class[] paramTypes = new Class[] { String[].class }; Method main = cl.getMethod("main", paramTypes); main.invoke(o, (Object) new String[] {"/sdcard/office/SampleSS.xlsx", "/sdcard/office/SampleSS.html"}); Et c‟est seulement à partir d‟ici que ça devient vraiment intéressant! W/System.err(370): Caused by: java.lang.RuntimeException: Installation Problem??? Couldn‟t load messages: Can‟t find resource for bundle „org.apache.xmlbeans.impl.regex.message_en_US‟, key » 16
  • 17. Afficher un document Office « xml » - 7 Que peut bien vouloir dire cette erreur? Le fichier message.properties est introuvable !  Il n‟est plus présent dans mon fichier dex!  Mais présent dans XmlBeans-1.0.jar La compilation en fichier APK, c‟est un zip avec  un fichier .dex pour les .class (et uniquement les .class!)  tout le reste (images, xml de layout, fichiers raw) dans des dossiers /res/drawable, /res/layout, /raw… Le fichier .properties n‟est donc pas resté dans le .dex! 17
  • 18. Afficher un document Office « xml » - 8 On peut tricher…  XmlBeans est OpenSource! public void setLocale(Locale locale) { try {//this.resources = ResourceBundle.getBundle("org.apache.xmlbeans.impl.regex.message", locale); this.resources = new ResourceBundle() { @Override protected Object handleGetObject(String key) { return res.get(key); } @Override public Enumeration<String> getKeys() { return Collections.enumeration(res.keySet()); } }; } catch (MissingResourceException mre) { throw new RuntimeException("Installation Problem??? Couldn't load messages: "+mre.getMessage()); } } static HashMap<String, String> res = new HashMap<String, String>(); static{res.put("parser.parse.1", "Wrong character.");} 18
  • 19. Afficher un document Office « xml » - 9 Cette fois-ci, ça va passer… Toujours pas! org.apache.xmlbeans.SchemaTypeLoaderException: XML-BEANS compiled schema: Could not locate compiled schema resource {…..}/index.xsb Les fichiers .xsb ne sont pas dans les .dex, mais cette fois, on sait pourquoi! package org.apache.xmlbeans.impl.schema; public class ClassLoaderResourceLoader{ public InputStream getResourceAsStream(String name) { try { return new FileInputStream("/sdcard/office/xsb/"+name.substring(name.lastIndexOf("/")+1)); } catch (FileNotFoundException e) {e.printStackTrace(); } //_classLoader.getResourceAsStream(resourceName); return null; } 19
  • 20. Afficher un document Office « xml » - 10 On tient le bout… Maintenant qu‟on accède à toutes les ressources du jar original… ClassNotFoundException: java.awt.Color  POI est censé tourner sous Java 1.5 DEMO  Android ne connait pas les packages java.awt (et quelques autres) Une ultime manipulation:  remplacer tous les java.awt par des and.awt dans les sources de POI http://code.google.com/p/awt-android-compat/ Attention, le résultat n‟est pas parfait  pas de gestion des images (pour l‟instant) 20
  • 21. Afficher un document Office « xml » - 11 Une approche plus sexy: - Intégrer les ressources manquantes aux jars - Création d‟un jar simple - « Dexisation » du jar en un fichier classes.dex - Réimportation des ressources dans un nouveau jar créé à la main  NOK! Le dexloader n‟a pas l‟air de gérer les jars et les APK de la même façon - Packaging du classes.dex dans un APK « maison »  OK! - En réutilisant cette technique, on peut donc, en théorie, se passer des étapes précédentes DEMO 21
  • 22. Afficher un document Office « xml » - 12 Conclusion de la méthode POI Le code complet est disponible ici: https://code.google.com/p/display-msoffice-docs-android-with-apache-poi/ Avantages: • Permet une conversion très complète (celle que permet le client POI) • Est très rapide (adaptée aux processeurs « lents » des mobiles d‟aujourd‟hui) • Donne accès à tous les formats (doc/docx, ppt/pptx, xls/xlsx, et même Visio .vsd ou Outlook msg) • Est chargeable dynamiquement en mémoire • Laisse la porte ouverte à un futur « mode édition » 22
  • 23. Afficher un document Office « xml » - 13 Inconvénients: • Utilise énormément de place sur la SDcard (8Mo d‟APK + 15Mo de ressources) • Compliqué à mettre en œuvre • Pour la partie AWT, repose sur le package and.awt  Pas de gestion des java.awt.BufferedImage. Il faudrait les convertir en android.graphics.Bitmap! 23
  • 24. Afficher un document Office « xml » - 14 L‟alternative La transformation XSL basée sur la solution de Julien Chable http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2006/11/21/openxmlandjava.aspx • Un procédé beaucoup plus simple, mais moins efficace. <!-- Body and paragraphs --> <xsl:template match="w:body"> <html> <body> <xsl:for-each select="w:p"> <p> <xsl:apply-templates select="w:pPr" /> <xsl:apply-templates select="w:r" /> </p> </xsl:for-each> </body> </html> </xsl:template> 24
  • 25. Afficher un document Office « xml » - 15 Avantages: • D‟une légèreté déconcertante: mon APK fait seulement 261k • D‟une simplicité déconcertante: un seul jar à ajouter au Build Path et c‟est fini. • Facilement améliorable: il « suffit » d‟ajouter les balises qu‟on veut gérer Inconvénients: • Ne gère que les OfficeOpen XML (donc pas les formats « binaires ») • Il faut trouver (ou écrire soi même?) un XSL vraiment complet pour un résultat parfait.  Les images ne sont pas du tout gérées  Seuls quelques styles sont implémentés, pas de formule, tableaux, wordart… 25
  • 26. Afficher un document Office « xml » - 16 Structure d‟un fichier docx 26
  • 27. Afficher un document Office « xml » - 17 Utilisation des rID pour retrouver le style ou le nom de fichier pour une image avec le fichier document.xml.rels w:drawing crée une balise <img> avec pour attribut id = rID On extrait toutes les images de /word/media vers la SDCard 2ème parsing: scan de toutes les balises img et ajout de l‟attribut grâce à la correspondance rID 27
  • 28. Afficher un document Office « xml » - 18 Malgré cette technique pour afficher les images, cette solution reste imparfaite • Les positions des éléments ne sont pas gérées • Les puces, formules, tableaux ne sont pas gérés • Un exemple existant de traitement XSL de document duquel on pourrait s‟inspirer:  DocBook Mon code est disponible ici https://code.google.com/p/display-msoffice-docs-android-without-apache-poi/ DEMO 28
  • 29. Afficher un PDF -1 Une bonne occasion de voir le NDK • Sous windows, installer Cygwin http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/ (étapes 2 et 3) • Télécharger le projet APV http://code.google.com/p/apv/ • Lancer la commande /script/build-native.sh du projet APV • Si tout s‟est bien passé, on peut lancer le projet APV sous Eclipse! 29
  • 30. Afficher un PDF -2 C‟est très bien mais c‟est pas ce qu‟on veut! On vient de faire l‟équivalent d‟installer l‟appli « Acrobat Reader » Fichier librairie qui permet de parser les PDFs 30
  • 31. Afficher un PDF -2 Customiser un peu… Extraction de la View PagesView • Par défaut, apv offre une view qui fait de nombreux appels à une activité. Un composant personnalisé <com.oxiane.DisplayPDF android:id="@+id/my_pdf_view" android:layout_width="fill_parent" android:layout_height="fill_parent" app:src="http://monpdf.com" /> 31
  • 32. Afficher un PDF -3 Inconvénients de la méthode • Pas de gestion des liens HTTP • Encore 1,7Mo à rajouter à l‟APK! • Chargement se fait en rectangles Avantages de la méthode • Ça a le mérite de marcher! 32
  • 33. Conclusion • Une aventure pionnière! • Un aperçu des possibilités qu‟offre l‟open source Java dans Android • Des ouvertures pour arriver à des résultats plus professionnels 33