Après avoir bien galéré pour les fichiers PDF (cf mon article précédent), je me suis attaqué à l’affichage de fichiers Microsoft Office sous Android.
Et figurez vous que le problème, bien que très différent, possède lui aussi une solution tout à fait particulière.
Comme mon application ne demande à priori pas la fonctionnalité « édition » des fichiers Office, je suis parti du postulat qu’il « suffisait » de convertir ceux ci au format HTML et à les afficher ainsi dans une WebView.
Pour faire moins dense, je vais découper la solution en plusieurs posts:
- – Convertir au HTML un fichier Office binaire (fichiers doc et non docX, par exemple) avec Apache POI
- – Convertir au HTML un fichier Office Open Document (xlsx, docx…) avec Apache POI
- – Convertir au HTML un fichier Office Open Document (xlsx, docx…) SANS Apache POI (c’est plus simple, mais moins intéressant!)
Donc, pour commencer… Convertir un fichier MSOffice binaire en HTML est relativement simple:
1) Il suffit d’aller chercher les bons jars sur le site de POI.
Dans mon exemple, je n’ai eu besoin que d’utiliser poi-scratchpad-3.8-beta4-20110826.jar, poi-3.8-beta4-20110826.jar et commons-codec-1.5.jar. Ce dernier est une dépendance et est disponible ici.
2) J’ai créé un projet Android sous Eclipse, ajouté des fichiers de test dans mon répertoire assets, ajouté les jars ci dessus au build path de mon projet et voila le résultat:
3) Directement dans le onCreate de mon activité (c’est pas bien, mais c’est suffisant pour ce test), j’ai copié les fichiers à convertir depuis mon répertoire Assets vers la SDCard. Puis, j’ai simplement appelé les méthodes de conversion du package Apache POI. Et voila!
Histoire de donner un bout de code, voilà mon onCreate():
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//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
WordToHtmlConverter.main(new String[]{"/mnt/sdcard/test.doc", "/mnt/sdcard/test.html"});
ExcelToHtmlConverter.main(new String[]{"/mnt/sdcard/testxls.xls", "/mnt/sdcard/testxls.html"});
}
Donc j’ai une méthode qui copie un fichier depuis les Assets Android vers la SDCard et j’ai simplement appelé les méthodes « main » des classes Apache POI WordToHtmlConverter et ExcelToHtmlConverter. Ci dessous le détail de ma méthode copyAssetToSDCard:
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;
}
Et voila! Il suffit de lire les fichiers HTML créés et de les insérer dans une WebView avec la méthode loadURL:
WebView v = (WebView) findViewById(R.id.ma_web_view);
v.loadUrl("file://mnt/sdcard/test.html");
Et pour les malins qui testeraient ce même code avec un fichier docx, xlsx ou autre Office Open Document… vous obtiendriez le message suivant:
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)
Bien essayé! ça aurait été trop simple. La solution dans le prochain post!
Pour conclure, mon apk final pèse 1,2 Mo, ce qui est beaucoup et finalement pas tant que ça, quand on considère ce qu’il fait. Cette notion de taille de l’apk, on le verra par la suite, a toute son importance!
On pourrait, pour diminuer la taille de l’apk final, « s’amuser » à ne prendre que la partie qui s’occupe de la conversion dans les jars Apache. Pour cela, j’ai téléchargé les sources sur le site de POI, puis j’ai lancé la conversion en mode DEBUG. Et j’ai regardé, aussi bien que je pouvais, quelles classes étaient utilisées.
Hum, honnêtement, j’ai essayé, je me suis cassé la tête pendant deux jours et au final, j’ai réduit la taille finale de mon apk à 800ko. C’est un peu mieux, mais le casse tête ne vaut probablement pas les 400ko gagnés. La méthode que j’ai utilisé n’était peut-être pas la bonne, et il y’a surement plus de choses qu’on peut supprimer.