Afficher du PDF intégré dans une activité Android

On est en 2011 et les voitures ne volent toujours pas. On pourrait croire que sous Android, ce système révolutionnaire, il est facile d’afficher du PDF dans votre activité. Ce n’est pas non plus le cas!

Il a fallu un peu chercher, mais voici la solution:

1) tout d’abord, si vous êtes sous Windows, suivre les étapes 2 et 3 de ce tuto: http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/

1 bis) Si vous vous êtes perdus et que vous avez une folle envie de faire votre première application NDK, ce tuto est très bien fait et vous pouvez continuer à lire jusqu’au bout!

2) Aller chercher le code du projet APV (http://code.google.com/p/apv/)
2 bis) Oui, cela implique d’installer Tortoise Hg (ici http://mercurial.selenic.com/downloads/), de faire un clic droit dans un dossier vide -> Tortoise Hg -> Clone …, de coller l’url du repository https://code.google.com/p/apv/ dans la case « source » et de laisser le nom de votre dossier vide dans la case « destination ». Chez moi, j’ai laissé C:/temp/ dans la case « destination ».

3) Ouvrir dans un éditeur de texte le fichier « build-native.sh » qui se trouve dans /scripts de votre projet APV que vous venez de télécharger et éditer la dernière ligne « build-ndk ». Il faut rajouter le chemin entier vers le fichier « build-ndk » qui se trouve dans votre répertoire « android-ndk-XXX ». Attention! Sous Cygwin, le disque dur est monté sous l’alias /cygdrive/c/ . Donc chez moi, la dernière ligne du fichier « build-native » est comme cela: /cygdrive/c/javabin/android-ndk-r6b/ndk-build
Vous l’aurez deviné, le chemin de mon répertoire android-ndk est C:/javabin/android-ndk-r6b/

4) Lancer une console cygwin (menu démarrer / Cygwin / Cygwin Bash Shell) pour lancer le script « build-native.sh » que l’on vient d’éditer à l’étape 3.
Voici les commandes que j’ai tapées dans mon environnement:

cd /cygdrive/c/temp/APVTest/scripts

puis, pour être sur que le script est exécutable,

chmod a+x build-native.sh

suivi de

./build-native.sh

5) Si tout s’est bien passé, le script devrait avoir créé un tas de fichiers, et surtout, il devrait à la fin avoir compilé vos sources dans un fichier « libpdfview2.so » qui se trouve dans votre répertoire « libs/armeabi » de votre projet APV. A ce stade, on peut ouvrir le projet dans Eclipse (import -> existing projects into workspace -> choisir votre projet APV) et lancer l’application APV. L’application affiche une liste simplifiée des fichiers de votre SDCard et, lorsqu’on sélectionne un fichier PDF, permet de l’ouvrir!

6) Pour intégrer la vue dans votre application, il « suffit » de copier le répertoire libs et la plupart des classes dans le projet où vous voulez afficher du PDF et de reprendre la classe « PagesView » dans le package cx.hell.android.lib.pagesview.
Pour ma part, je me suis contenté pour l’instant d’y ajouter un nouveau constructeur de la façon suivante:

public PagesView(Context context, AttributeSet attrs, int defStyle) {
		this(context);
		TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.pdfStylable);
		String filePath = a.getString(R.styleable.pdfStylable_android_text);
		a.recycle();
		this.pdf = new PDF(new File(filePath), 2);
		SharedPreferences options = PreferenceManager
				.getDefaultSharedPreferences(context);
		this.colorMode = Options.getColorMode(options);
		this.pdfPagesProvider = new PDFPagesProvider(this.activity, pdf,
				Options.isGray(this.colorMode), options.getBoolean(
						Options.PREF_OMIT_IMAGES, false), options.getBoolean(
						Options.PREF_RENDER_AHEAD, true));
		setPagesProvider(pdfPagesProvider);
		Bookmark b = new Bookmark(context.getApplicationContext()).open();
		setStartBookmark(b, filePath);
		b.close();
	}

Cela me permet de déclarer un composant n’importe où dans mon application de la façon suivante:

Pour repérer l’attribut « android:text » de la balise PagesView ci-dessus, j’ai déclaré dans le fichier res/values/attrs.xml le styaleable suivant:

    
    	
    

Pfiou…

Enfin, à l’utilisation, c’est pas si pratique que ça finalement! C’est sur, j’affiche un PDF au sein de mon appli. Le résultat est là. Mais je n’ai pas réussi à exporter dans un jar les fichiers « .so » compilés par le NDK, ce qui aurait permis une bien plus grande souplesse.
Par ailleurs, utiliser la classe PagesView n’est probablement pas très judicieux. En effet, dans le projet APV, c’est au sein de l’activité « OpenFileActivity » que sont gérés tous les éléments de navigation (zoom, passer à la page suivante etc…). Il faudrait donc idéalement regrouper les deux classes en une seule qui hérite de View et qui contienne, en plus de l’affichage du PDF qu’on a vu dans cet article, les commandes diverses pour manipuler cette vue.

Et les mauvaises langues diront:
NSURL *targetURL = [NSURL URLWithString:@ »http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/UIWebView_Class.pdf »];

Mais je ne les écouterai pas! Android vaincra!!!