Je me suis rendu compte qu'Android n'a pas de méthode intégrée d'affichage de fichiers PDF.
Comment puis-je rendre un fichier PDF en utilisant Java sur Android?
Depuis API niveau 21 (Lollipop) Android fournit une classe PdfRenderer :
// create a new renderer
PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor());
// let us just render all pages
final int pageCount = renderer.getPageCount();
for (int i = 0; i < pageCount; i++) {
Page page = renderer.openPage(i);
// say we render for showing on the screen
page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY);
// do stuff with the bitmap
// close the page
page.close();
}
// close the renderer
renderer.close();
Pour plus d'informations, voir exemple d'application .
Pour les anciennes API, je recommande Bibliothèque Android PdfViewer , il est très rapide et facile à utiliser, sous licence Apache License 2.0:
pdfView.fromAsset(String)
.pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default
.enableSwipe(true)
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
.onDraw(onDrawListener)
.onLoad(onLoadCompleteListener)
.onPageChange(onPageChangeListener)
.onPageScroll(onPageScrollListener)
.onError(onErrorListener)
.enableAnnotationRendering(false)
.password(null)
.scrollHandle(null)
.load();
public class MyPdfViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView mWebView=new WebView(MyPdfViewActivity.this);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.loadUrl("https://docs.google.com/gview?embedded=true&url="+LinkTo);
setContentView(mWebView);
}
}
J'ai adopté une approche hybride à partir de certaines des réponses apportées à cet article et à d'autres postes similaires:
Cette solution vérifie si une application de lecteur PDF est installée et procède comme suit: - Si un lecteur est installé, téléchargez le fichier PDF sur le périphérique et démarrez une application de lecture PDF. - Si aucun lecteur n'est installé, demandez à l'utilisateur s'il souhaite visualiser le fichier PDF en ligne via Google Drive.
REMARQUE! Cette solution utilise Android DownloadManager
class, introduit dans API9 (Android 2.3 ou Gingerbread). Cela signifie que (cela ne fonctionne pas sur Android 2.2 ou une version antérieure.} _
J'ai écrit un article de blog à ce sujet ici , mais j'ai fourni le code complet ci-dessous par souci d'exhaustivité:
public class PDFTools {
private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://drive.google.com/viewer?url=";
private static final String PDF_MIME_TYPE = "application/pdf";
private static final String HTML_MIME_TYPE = "text/html";
/**
* If a PDF reader is installed, download the PDF file and open it in a reader.
* Otherwise ask the user if he/she wants to view it in the Google Drive online PDF reader.<br />
* <br />
* <b>BEWARE:</b> This method
* @param context
* @param pdfUrl
* @return
*/
public static void showPDFUrl( final Context context, final String pdfUrl ) {
if ( isPDFSupported( context ) ) {
downloadAndOpenPDF(context, pdfUrl);
} else {
askToOpenPDFThroughGoogleDrive( context, pdfUrl );
}
}
/**
* Downloads a PDF with the Android DownloadManager and opens it with an installed PDF reader app.
* @param context
* @param pdfUrl
*/
@TargetApi(Build.VERSION_CODES.Gingerbread)
public static void downloadAndOpenPDF(final Context context, final String pdfUrl) {
// Get filename
final String filename = pdfUrl.substring( pdfUrl.lastIndexOf( "/" ) + 1 );
// The place where the downloaded PDF file will be put
final File tempFile = new File( context.getExternalFilesDir( Environment.DIRECTORY_DOWNLOADS ), filename );
if ( tempFile.exists() ) {
// If we have downloaded the file before, just go ahead and show it.
openPDF( context, Uri.fromFile( tempFile ) );
return;
}
// Show progress dialog while downloading
final ProgressDialog progress = ProgressDialog.show( context, context.getString( R.string.pdf_show_local_progress_title ), context.getString( R.string.pdf_show_local_progress_content ), true );
// Create the download request
DownloadManager.Request r = new DownloadManager.Request( Uri.parse( pdfUrl ) );
r.setDestinationInExternalFilesDir( context, Environment.DIRECTORY_DOWNLOADS, filename );
final DownloadManager dm = (DownloadManager) context.getSystemService( Context.DOWNLOAD_SERVICE );
BroadcastReceiver onComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if ( !progress.isShowing() ) {
return;
}
context.unregisterReceiver( this );
progress.dismiss();
long downloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, -1 );
Cursor c = dm.query( new DownloadManager.Query().setFilterById( downloadId ) );
if ( c.moveToFirst() ) {
int status = c.getInt( c.getColumnIndex( DownloadManager.COLUMN_STATUS ) );
if ( status == DownloadManager.STATUS_SUCCESSFUL ) {
openPDF( context, Uri.fromFile( tempFile ) );
}
}
c.close();
}
};
context.registerReceiver( onComplete, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE ) );
// Enqueue the request
dm.enqueue( r );
}
/**
* Show a dialog asking the user if he wants to open the PDF through Google Drive
* @param context
* @param pdfUrl
*/
public static void askToOpenPDFThroughGoogleDrive( final Context context, final String pdfUrl ) {
new AlertDialog.Builder( context )
.setTitle( R.string.pdf_show_online_dialog_title )
.setMessage( R.string.pdf_show_online_dialog_question )
.setNegativeButton( R.string.pdf_show_online_dialog_button_no, null )
.setPositiveButton( R.string.pdf_show_online_dialog_button_yes, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
openPDFThroughGoogleDrive(context, pdfUrl);
}
})
.show();
}
/**
* Launches a browser to view the PDF through Google Drive
* @param context
* @param pdfUrl
*/
public static void openPDFThroughGoogleDrive(final Context context, final String pdfUrl) {
Intent i = new Intent( Intent.ACTION_VIEW );
i.setDataAndType(Uri.parse(GOOGLE_DRIVE_PDF_READER_PREFIX + pdfUrl ), HTML_MIME_TYPE );
context.startActivity( i );
}
/**
* Open a local PDF file with an installed reader
* @param context
* @param localUri
*/
public static final void openPDF(Context context, Uri localUri ) {
Intent i = new Intent( Intent.ACTION_VIEW );
i.setDataAndType( localUri, PDF_MIME_TYPE );
context.startActivity( i );
}
/**
* Checks if any apps are installed that supports reading of PDF files.
* @param context
* @return
*/
public static boolean isPDFSupported( Context context ) {
Intent i = new Intent( Intent.ACTION_VIEW );
final File tempFile = new File( context.getExternalFilesDir( Environment.DIRECTORY_DOWNLOADS ), "test.pdf" );
i.setDataAndType( Uri.fromFile( tempFile ), PDF_MIME_TYPE );
return context.getPackageManager().queryIntentActivities( i, PackageManager.MATCH_DEFAULT_ONLY ).size() > 0;
}
}
J'ai finalement pu modifier le code de butelo pour ouvrir n'importe quel fichier PDF du système de fichiers Android à l'aide de pdf.js
. Le code peut être trouvé sur mon GitHub
Ce que j'ai fait a été modifié le pdffile.js
pour lire l'argument HTML file
comme ceci:
var url = getURLParameter('file');
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null}
Vous devez donc simplement ajouter le chemin du fichier après le index.html
comme ceci:
Uri path = Uri.parse(Environment.getExternalStorageDirectory().toString() + "/data/test.pdf");
webView.loadUrl("file:///Android_asset/pdfviewer/index.html?file=" + path);
Mettez à jour la variable path
pour qu'elle pointe vers un PDF valide dans le système de fichiers Adroid.
Téléchargez le code source ici ( Afficher le fichier PDF dans mon application Android )
Ajoutez cette dépendance dans votre note: Compile 'com.github.barteksc: Android-pdf-viewer: 2.0.3'
activity_main.xml
<RelativeLayout Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="#ffffff"
xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<TextView
Android:layout_width="match_parent"
Android:layout_height="40dp"
Android:background="@color/colorPrimaryDark"
Android:text="View PDF"
Android:textColor="#ffffff"
Android:id="@+id/tv_header"
Android:textSize="18dp"
Android:gravity="center"></TextView>
<com.github.barteksc.pdfviewer.PDFView
Android:id="@+id/pdfView"
Android:layout_below="@+id/tv_header"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
</RelativeLayout>
MainActivity.Java
import Android.app.Activity;
import Android.database.Cursor;
import Android.net.Uri;
import Android.provider.OpenableColumns;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.ImageView;
import Android.widget.RelativeLayout;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.shockwave.pdfium.PdfDocument;
import Java.util.List;
public class MainActivity extends Activity implements OnPageChangeListener,OnLoadCompleteListener{
private static final String TAG = MainActivity.class.getSimpleName();
public static final String SAMPLE_FILE = "Android_tutorial.pdf";
PDFView pdfView;
Integer pageNumber = 0;
String pdfFileName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView= (PDFView)findViewById(R.id.pdfView);
displayFromAsset(SAMPLE_FILE);
}
private void displayFromAsset(String assetFileName) {
pdfFileName = assetFileName;
pdfView.fromAsset(SAMPLE_FILE)
.defaultPage(pageNumber)
.enableSwipe(true)
.swipeHorizontal(false)
.onPageChange(this)
.enableAnnotationRendering(true)
.onLoad(this)
.scrollHandle(new DefaultScrollHandle(this))
.load();
}
@Override
public void onPageChanged(int page, int pageCount) {
pageNumber = page;
setTitle(String.format("%s %s / %s", pdfFileName, page + 1, pageCount));
}
@Override
public void loadComplete(int nbPages) {
PdfDocument.Meta meta = pdfView.getDocumentMeta();
printBookmarksTree(pdfView.getTableOfContents(), "-");
}
public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) {
for (PdfDocument.Bookmark b : tree) {
Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx()));
if (b.hasChildren()) {
printBookmarksTree(b.getChildren(), sep + "-");
}
}
}
}
Pour ajouter un peu de lumière à cela, je devrais utiliser la solution pdf.js de Mozilla. Voici le lien vers une implémentation déjà bien écrite de ceci: https://bitbucket.org/butelo/pdfviewer/ .
Voici les modifications que j'ai ajoutées dans mon activité Android:
private String getInternalPDFURL(String interalPDFName){
return "file:///Android_asset/pdfviewer/index.html?pdf=" + interalPDFName + ".pdf";
}
Voici les modifications que j'ai apportées dans pdffile.js
:
var url = '../' + getPDFURL();
function getPDFURL(){
var query = window.location.search.substring(1);
var vars = query.split("=");
var pdfPage = vars[1];
return pdfPage;
}
J'ai utilisé le code ci-dessous pour ouvrir et imprimer le PDF à l'aide du Wi-Fi. J'envoie tout mon code et j'espère que c'est utile.
public class MainActivity extends Activity {
int Result_code = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mButton = (Button)findViewById(R.id.button1);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PrintManager printManager = (PrintManager)getSystemService(Context.PRINT_SERVICE);
String jobName = " Document";
printManager.print(jobName, pda, null);
}
});
}
public void openDocument(String name) {
Intent intent = new Intent(Android.content.Intent.ACTION_VIEW);
File file = new File(name);
String extension = Android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
String mimetype = Android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (extension.equalsIgnoreCase("") || mimetype == null) {
// if there is no extension or there is no definite mimetype, still try to open the file
intent.setDataAndType(Uri.fromFile(file), "text/*");
}
else {
intent.setDataAndType(Uri.fromFile(file), mimetype);
}
// custom message for the intent
startActivityForResult((Intent.createChooser(intent, "Choose an Application:")), Result_code);
//startActivityForResult(intent, Result_code);
//Toast.makeText(getApplicationContext(),"There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
@SuppressLint("NewApi")
PrintDocumentAdapter pda = new PrintDocumentAdapter(){
@Override
public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback){
InputStream input = null;
OutputStream output = null;
try {
String filename = Environment.getExternalStorageDirectory() + "/" + "Holiday.pdf";
File file = new File(filename);
input = new FileInputStream(file);
output = new FileOutputStream(destination.getFileDescriptor());
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buf)) > 0) {
output.write(buf, 0, bytesRead);
}
callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
}
catch (FileNotFoundException ee){
//Catch exception
}
catch (Exception e) {
//Catch exception
}
finally {
try {
input.close();
output.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras){
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
// int pages = computePageCount(newAttributes);
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("Name of file").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();
callback.onLayoutFinished(pdi, true);
}
};
}
vous pouvez utiliser une méthode simple par import
implementation 'com.github.barteksc:Android-pdf-viewer:2.8.2'
et le code XML est
<com.github.barteksc.pdfviewer.PDFView
Android:id="@+id/pdfv"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
</com.github.barteksc.pdfviewer.PDFView>
et juste déclarer et ajouter un fichier à un dossier d'actifs et simplement attribuer le nom
PDFView pdfView=findViewById(R.id.pdfv);
pdfView.fromAsset("agl.pdf").load();
Il n’existe aucun moyen de prévisualiser un document pdf dans une vue Web Android. Si vous souhaitez prévisualiser un fichier PDF base64. Cela nécessite une bibliothèque tierce.
construire.Bradle
compile 'com.github.barteksc:Android-pdf-viewer:2.7.0'
dialog_pdf_viewer
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2017.
~ Samet Öztoprak
~ All rights reserved.
-->
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center_horizontal"
Android:orientation="vertical">
<ImageView
Android:id="@+id/dialog_pdf_viewer_close"
style="@style/ExitButtonImageViewStyle"
Android:src="@drawable/popup_exit" />
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1"
Android:background="@color/white"
Android:orientation="vertical">
<com.github.barteksc.pdfviewer.PDFView
Android:id="@+id/pdfView"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</LinearLayout>
<View style="@style/HorizontalLine" />
<com.pozitron.commons.customviews.ButtonFont
Android:id="@+id/dialog_pdf_viewer_button"
style="@style/ButtonPrimary2"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:padding="15dp"
Android:text="@string/agreed" />
</LinearLayout>
DailogPDFViewer.Java
public class DialogPdfViewer extends Dialog {
PDFView pdfView;
byte[] decodedString;
public interface OnDialogPdfViewerListener {
void onAgreeClick(DialogPdfViewer dialogFullEula);
void onCloseClick(DialogPdfViewer dialogFullEula);
}
public DialogPdfViewer(Context context, String base64, final DialogPdfViewer.OnDialogPdfViewerListener onDialogPdfViewerListener) {
super(context);
setContentView(R.layout.dialog_pdf_viewer);
findViewById(R.id.dialog_pdf_viewer_close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDialogPdfViewerListener.onCloseClick(DialogPdfViewer.this);
}
});
findViewById(R.id.dialog_pdf_viewer_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDialogPdfViewerListener.onAgreeClick(DialogPdfViewer.this);
}
});
decodedString = Base64.decode(base64.toString(), Base64.DEFAULT);
pdfView = ((PDFView) findViewById(R.id.pdfView));
pdfView.fromBytes(decodedString).load();
setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
onDialogPdfViewerListener.onCloseClick(DialogPdfViewer.this);
}
return true;
}
});
}
}