diff --git a/README.md b/README.md index a580805b..5ca138eb 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,23 @@ This is beta release because of big number of small changes and something could * removed minimap and mask configuration ## Installation +## Step 1. Add the JitPack repository to your build file +Add it in your root build.gradle at the end of repositories: + + allprojects { + repositories { + ... + maven { url 'https://jitpack.io' } + } + } + +## Step 2. Add the dependency + dependencies { + compile 'com.github.shxdos:AndroidPdfViewer:2.7.0-beta.2' + } -Add to _build.gradle_: -`compile 'com.github.barteksc:android-pdf-viewer:2.7.0-beta.1'` or `2.6.1` for more stable version -Library is available in jcenter repository, probably it'll be in Maven Central soon. ## Include PDFView in your layout @@ -53,6 +64,16 @@ Library is available in jcenter repository, probably it'll be in Maven Central s All available options with default values: ``` java pdfView.fromUri(Uri) +or + pdfView.fromUrl("http://www.anweitong.com/upload/document/standard/national_standards/138793918364316200.pdf") + .enableSwipe(true) // allows to block changing pages using swipe + .defaultPage(0) + .onLoad(this) // called after document is loaded and starts to be rendered + .onPageChange(this) + .swipeHorizontal(false) + .enableAntialiasing(true) + .onFileDownload(this) + .loadFromUrl(); or pdfView.fromFile(File) or diff --git a/android-pdf-viewer/build.gradle b/android-pdf-viewer/build.gradle index 2ec789a0..a85e4e03 100644 --- a/android-pdf-viewer/build.gradle +++ b/android-pdf-viewer/build.gradle @@ -39,6 +39,7 @@ android { dependencies { compile 'com.github.barteksc:pdfium-android:1.7.0' + compile 'com.squareup.okhttp3:okhttp:3.8.1' } apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java index d57d9da6..140fff41 100644 --- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java +++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java @@ -28,6 +28,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; +import android.os.Environment; import android.os.HandlerThread; import android.util.AttributeSet; import android.util.Log; @@ -35,6 +36,7 @@ import com.github.barteksc.pdfviewer.listener.OnDrawListener; import com.github.barteksc.pdfviewer.listener.OnErrorListener; +import com.github.barteksc.pdfviewer.listener.OnFileDownloadCompleteListener; import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener; import com.github.barteksc.pdfviewer.listener.OnPageChangeListener; import com.github.barteksc.pdfviewer.listener.OnPageScrollListener; @@ -47,8 +49,10 @@ import com.github.barteksc.pdfviewer.source.FileSource; import com.github.barteksc.pdfviewer.source.InputStreamSource; import com.github.barteksc.pdfviewer.source.UriSource; +import com.github.barteksc.pdfviewer.source.UrlSource; import com.github.barteksc.pdfviewer.util.ArrayUtils; import com.github.barteksc.pdfviewer.util.Constants; +import com.github.barteksc.pdfviewer.util.DownloadUtil; import com.github.barteksc.pdfviewer.util.MathUtils; import com.github.barteksc.pdfviewer.util.Util; import com.shockwave.pdfium.PdfDocument; @@ -1288,7 +1292,14 @@ public Configurator fromAsset(String assetName) { public Configurator fromFile(File file) { return new Configurator(new FileSource(file)); } - + /** + * Use a url as the pdf source + */ + public Configurator fromUrl(String url) { + Configurator source= new Configurator(new UrlSource(url)); + source.fileUrl(url); + return source; + } /** * Use URI as the pdf source, for use with content providers */ @@ -1322,7 +1333,7 @@ private enum State {DEFAULT, LOADED, SHOWN, ERROR} public class Configurator { private final DocumentSource documentSource; - + private String fileUrl; private int[] pageNumbers = null; private boolean enableSwipe = true; @@ -1334,6 +1345,7 @@ public class Configurator { private OnDrawListener onDrawAllListener; private OnLoadCompleteListener onLoadCompleteListener; + private OnFileDownloadCompleteListener onFileDownloadCompleteListener; private OnErrorListener onErrorListener; @@ -1365,6 +1377,10 @@ public Configurator pages(int... pageNumbers) { this.pageNumbers = pageNumbers; return this; } + private Configurator fileUrl(String fileUrl){ + this.fileUrl=fileUrl; + return this; + } public Configurator enableSwipe(boolean enableSwipe) { this.enableSwipe = enableSwipe; @@ -1395,7 +1411,10 @@ public Configurator onLoad(OnLoadCompleteListener onLoadCompleteListener) { this.onLoadCompleteListener = onLoadCompleteListener; return this; } - + public Configurator onFileDownload(OnFileDownloadCompleteListener onFileDownloadCompleteListener) { + this.onFileDownloadCompleteListener = onFileDownloadCompleteListener; + return this; + } public Configurator onPageScroll(OnPageScrollListener onPageScrollListener) { this.onPageScrollListener = onPageScrollListener; return this; @@ -1468,5 +1487,40 @@ public void load() { PDFView.this.load(documentSource, password, onLoadCompleteListener, onErrorListener); } } + public void loadFromUrl(){ + final String SDPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/PDFViewCache/"; + int index = fileUrl.lastIndexOf("/"); + String fileName = fileUrl.substring(index); + final File file = new File(SDPath, fileName); + if(file.exists()){ + //文件存在 + if(onFileDownloadCompleteListener!=null){ + onFileDownloadCompleteListener.onDownloadComplete(file); + } + PDFView.this.fromFile(file); + load(); + }else{ + DownloadUtil.get().download(fileUrl, SDPath, new DownloadUtil.OnDownloadListener() { + @Override + public void onDownloadSuccess(File file) { + if(onFileDownloadCompleteListener!=null){ + onFileDownloadCompleteListener.onDownloadComplete(file); + } + PDFView.this.fromFile(file); + load(); + } + + @Override + public void onDownloading(int progress) { + + } + + @Override + public void onDownloadFailed() { + + } + }); + } + } } } diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnFileDownloadCompleteListener.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnFileDownloadCompleteListener.java new file mode 100644 index 00000000..94fcbd4b --- /dev/null +++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnFileDownloadCompleteListener.java @@ -0,0 +1,31 @@ +/** + * Copyright 2016 Bartosz Schiller + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.barteksc.pdfviewer.listener; + +import java.io.File; + +/** + * Implement this interface to receive events from PDFView + * when the url file loading is complete. + */ +public interface OnFileDownloadCompleteListener { + + /** + * Called when the PDF is loaded + * @param file the number of pages in this PDF file + */ + void onDownloadComplete(File file); +} diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/UrlSource.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/UrlSource.java new file mode 100644 index 00000000..5dbe040f --- /dev/null +++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/UrlSource.java @@ -0,0 +1,38 @@ +package com.github.barteksc.pdfviewer.source; + +import android.content.Context; +import android.os.Environment; +import android.os.ParcelFileDescriptor; + +import com.shockwave.pdfium.PdfDocument; +import com.shockwave.pdfium.PdfiumCore; + +import java.io.File; +import java.io.IOException; + +/** + * Created by 邵鸿轩 on 2017/7/21. + */ + +public class UrlSource implements DocumentSource { + private File file; + private String url; + + public UrlSource(String url) { + this.url = url; + } + + @Override + public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException { + final String SDPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/PDFViewCache/"; + int index = url.lastIndexOf("/"); + String fileName = url.substring(index); + file = new File(SDPath, fileName); + if (file.exists()) { + ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); + return core.newDocument(pfd, password); + } + return null; + + } +} diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/DownloadUtil.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/DownloadUtil.java new file mode 100644 index 00000000..bddaa0b3 --- /dev/null +++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/DownloadUtil.java @@ -0,0 +1,133 @@ +package com.github.barteksc.pdfviewer.util; + +import android.support.annotation.NonNull; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +public class DownloadUtil { + + private static DownloadUtil downloadUtil; + private final OkHttpClient okHttpClient; + + public static DownloadUtil get() { + if (downloadUtil == null) { + downloadUtil = new DownloadUtil(); + } + return downloadUtil; + } + + private DownloadUtil() { + okHttpClient = new OkHttpClient(); + } + + /** + * @param url 下载连接 + * @param saveDir 储存下载文件的SDCard目录 + * @param listener 下载监听 + */ + public void download(final String url, final String saveDir, final OnDownloadListener listener) { + Request request = new Request.Builder().url(url).build(); + okHttpClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + // 下载失败 + listener.onDownloadFailed(); + } + @Override + public void onResponse(Call call, Response response) throws IOException { + InputStream is = null; + byte[] buf = new byte[2048]; + int len = 0; + FileOutputStream fos = null; + // 储存下载文件的目录 + String savePath = isExistDir(saveDir); + try { + is = response.body().byteStream(); + long total = response.body().contentLength(); + + int index = url.lastIndexOf("/"); + String fileName = url.substring(index); + final File file = new File(saveDir, fileName); + fos = new FileOutputStream(file); + long sum = 0; + while ((len = is.read(buf)) != -1) { + fos.write(buf, 0, len); + sum += len; + int progress = (int) (sum * 1.0f / total * 100); + // 下载中 + listener.onDownloading(progress); + } + fos.flush(); + // 下载完成 + listener.onDownloadSuccess(file); + } catch (Exception e) { + listener.onDownloadFailed(); + } finally { + try { + if (is != null) + is.close(); + } catch (IOException e) { + } + try { + if (fos != null) + fos.close(); + } catch (IOException e) { + } + } + } + }); + } + + /** + * @param saveDir + * @return + * @throws IOException + * 判断下载目录是否存在 + */ + private String isExistDir(String saveDir) throws IOException { + // 下载位置 + File downloadFile = new File( saveDir); + if (!downloadFile.mkdirs()) { + downloadFile.createNewFile(); + } + String savePath = downloadFile.getAbsolutePath(); + return savePath; + } + + /** + * @param url + * @return + * 从下载连接中解析出文件名 + */ + @NonNull + private String getNameFromUrl(String url) { + return url.substring(url.lastIndexOf("/") + 1); + } + + public interface OnDownloadListener { + /** + * 下载成功 + */ + void onDownloadSuccess(File fiel); + + /** + * @param progress + * 下载进度 + */ + void onDownloading(int progress); + + /** + * 下载失败 + */ + void onDownloadFailed(); + } +} diff --git a/build.gradle b/build.gradle index 63272134..9cb085f4 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index d6ce646c..78e26d92 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -2,19 +2,29 @@ package="com.github.barteksc.sample"> - + + + + + - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/java/com/github/barteksc/sample/PDFViewActivity.java b/sample/src/main/java/com/github/barteksc/sample/PDFViewActivity.java index ed18cea1..6c3c957b 100755 --- a/sample/src/main/java/com/github/barteksc/sample/PDFViewActivity.java +++ b/sample/src/main/java/com/github/barteksc/sample/PDFViewActivity.java @@ -15,202 +15,58 @@ */ package com.github.barteksc.sample; -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.database.Cursor; -import android.graphics.Color; -import android.net.Uri; -import android.provider.OpenableColumns; -import android.support.annotation.NonNull; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; +import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; -import android.util.Log; -import android.widget.Toast; +import android.view.View; +import android.widget.Button; import com.github.barteksc.pdfviewer.PDFView; +import com.github.barteksc.pdfviewer.listener.OnFileDownloadCompleteListener; 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 org.androidannotations.annotations.AfterViews; -import org.androidannotations.annotations.EActivity; -import org.androidannotations.annotations.NonConfigurationInstance; -import org.androidannotations.annotations.OnActivityResult; -import org.androidannotations.annotations.OptionsItem; -import org.androidannotations.annotations.OptionsMenu; -import org.androidannotations.annotations.ViewById; +import java.io.File; -import java.util.List; -@EActivity(R.layout.activity_main) -@OptionsMenu(R.menu.options) -public class PDFViewActivity extends AppCompatActivity implements OnPageChangeListener, OnLoadCompleteListener { - - private static final String TAG = PDFViewActivity.class.getSimpleName(); - - private final static int REQUEST_CODE = 42; - public static final int PERMISSION_CODE = 42042; - - public static final String SAMPLE_FILE = "sample.pdf"; - public static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"; - - @ViewById +public class PDFViewActivity extends AppCompatActivity implements OnPageChangeListener, OnLoadCompleteListener ,OnFileDownloadCompleteListener{ PDFView pdfView; - - @NonConfigurationInstance - Uri uri; - - @NonConfigurationInstance - Integer pageNumber = 0; - - String pdfFileName; - - @OptionsItem(R.id.pickFile) - void pickFile() { - int permissionCheck = ContextCompat.checkSelfPermission(this, - READ_EXTERNAL_STORAGE); - - if (permissionCheck != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions( - this, - new String[]{READ_EXTERNAL_STORAGE}, - PERMISSION_CODE - ); - - return; - } - - launchPicker(); - } - - void launchPicker() { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("application/pdf"); - try { - startActivityForResult(intent, REQUEST_CODE); - } catch (ActivityNotFoundException e) { - //alert user that file manager not working - Toast.makeText(this, R.string.toast_pick_file_error, Toast.LENGTH_SHORT).show(); - } - } - - @AfterViews - void afterViews() { - pdfView.setBackgroundColor(Color.LTGRAY); - if (uri != null) { - displayFromUri(uri); - } else { - displayFromAsset(SAMPLE_FILE); - } - setTitle(pdfFileName); - } - - private void displayFromAsset(String assetFileName) { - pdfFileName = assetFileName; - - pdfView.fromAsset(SAMPLE_FILE) - .defaultPage(pageNumber) - .onPageChange(this) - .enableAnnotationRendering(true) - .onLoad(this) - .scrollHandle(new DefaultScrollHandle(this)) - .spacing(10) // in dp - .load(); - } - - private void displayFromUri(Uri uri) { - pdfFileName = getFileName(uri); - - pdfView.fromUri(uri) - .defaultPage(pageNumber) - .onPageChange(this) - .enableAnnotationRendering(true) - .onLoad(this) - .scrollHandle(new DefaultScrollHandle(this)) - .spacing(10) // in dp - .load(); - } - - @OnActivityResult(REQUEST_CODE) - public void onResult(int resultCode, Intent intent) { - if (resultCode == RESULT_OK) { - uri = intent.getData(); - displayFromUri(uri); - } - } + private Button btnLoad; @Override - public void onPageChanged(int page, int pageCount) { - pageNumber = page; - setTitle(String.format("%s %s / %s", pdfFileName, page + 1, pageCount)); - } - - public String getFileName(Uri uri) { - String result = null; - if (uri.getScheme().equals("content")) { - Cursor cursor = getContentResolver().query(uri, null, null, null, null); - try { - if (cursor != null && cursor.moveToFirst()) { - result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); - } - } finally { - if (cursor != null) { - cursor.close(); - } + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + pdfView= (PDFView) findViewById(R.id.pdfView); + btnLoad= (Button) findViewById(R.id.btnLoad); + btnLoad.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + pdfView.fromUrl("http://www.anweitong.com/upload/document/standard/national_standards/138793918364316200.pdf") + .enableSwipe(true) // allows to block changing pages using swipe + .defaultPage(0) + .onLoad(PDFViewActivity.this) // called after document is loaded and starts to be rendered + .onPageChange(PDFViewActivity.this) + .swipeHorizontal(false) + .enableAntialiasing(true) + .onFileDownload(PDFViewActivity.this) + .loadFromUrl(); } - } - if (result == null) { - result = uri.getLastPathSegment(); - } - return result; + }); } @Override public void loadComplete(int nbPages) { - PdfDocument.Meta meta = pdfView.getDocumentMeta(); - Log.e(TAG, "title = " + meta.getTitle()); - Log.e(TAG, "author = " + meta.getAuthor()); - Log.e(TAG, "subject = " + meta.getSubject()); - Log.e(TAG, "keywords = " + meta.getKeywords()); - Log.e(TAG, "creator = " + meta.getCreator()); - Log.e(TAG, "producer = " + meta.getProducer()); - Log.e(TAG, "creationDate = " + meta.getCreationDate()); - Log.e(TAG, "modDate = " + meta.getModDate()); - - printBookmarksTree(pdfView.getTableOfContents(), "-"); } - public void printBookmarksTree(List tree, String sep) { - for (PdfDocument.Bookmark b : tree) { - - Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx())); + @Override + public void onPageChanged(int page, int pageCount) { - if (b.hasChildren()) { - printBookmarksTree(b.getChildren(), sep + "-"); - } - } } - /** - * Listener for response to user permission request - * - * @param requestCode Check that permission request code matches - * @param permissions Permissions that requested - * @param grantResults Whether permissions granted - */ @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], - @NonNull int[] grantResults) { - if (requestCode == PERMISSION_CODE) { - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - launchPicker(); - } - } - } + public void onDownloadComplete(File file) { + } } diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index a14dd73d..657a76c8 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -1,11 +1,17 @@ - - + android:layout_height="match_parent" + android:orientation="vertical"> +