首页 > 其他分享 >android:加载PDF几种方法汇总对比

android:加载PDF几种方法汇总对比

时间:2022-10-14 16:13:36浏览次数:101  
标签:intent new PDF android 加载 public Intent

在安卓项目中,加载PDF文件,是一个比较常见的需求。又分为两大类,

1.加载网络PDF

2.加载一个本地静态PDF。

查阅资料,纵观网上在安卓中打开PDF的各种方式,大致可以分为以下几类,

1.直接使用第三方软件打开(包括浏览器打开和第三方软件打开)

如果是在app内部加载PDF文件,虽然安卓原生API对于PDF的支持又不是太好,但是各种第三方专门的阅读或者办公软件支持的是很不错的,可以通过Intent配置data和type实现,:
其中,在实际需求中又会分为加载本地PDF和网络PDF的情况。

使用浏览器打开PDF:(APP外部打开,适用于加载网络PDF)
public static void openPDFInBrowser(Context context, String url) {
        Uri uri = Uri.parse(url);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Log.w("error", "Activity was not found for intent, " + intent.toString());
        }
    }
使用浏览器打开PDF:(APP外部打开,适用于加载网络PDF)
使用手机上已安装的可以打开PDF的第三方软件来打开PDF:(APP外部打开,适用于加载本地PDF)
(使用这种方式缺点是:手机上如果没有一个可以打开PDF的软件,那么就尴尬了~
 public static void openPDFInNative(Context context, String FILE_NAME) {
        File file = new File(context.getExternalCacheDir(),FILE_NAME);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri = Uri.fromFile(file);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(uri, "application/pdf");
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Log.w("URLSpan", "Activity was not found for intent, " + intent.toString());
        }
    }
加载本地文件

2.连接Google服务器解析

安卓的WebView不支持PDF解析,因此通过连接Google的一个服务器转换成功后返回给WebView显示。但是,但是,但是呢,大家都懂的,天朝和Google之间有一道高高的墙。方法还是贴出来,作为国际化APP的一种方案。

mWebView.loadUrl("http://docs.google.com/gview?embedded=true&url="+ pdfUrl);   

3.用第三方库加载

Github上有一个Java开源项目 https://github.com/barteksc/AndroidPdfViewer ,
这个库的大致原理,是内置了一个PDF解析器,以流的方式将网络PDF从网上Down下来,然后再以流的方式将其还原成PDF展示出来(具体细节没关注)。亲测中,这个库每次进入webview页面都会解析加载一遍PDF,如果PDF过大,费时无缓存不说,最致命的问题乃是,

APK包体积会瞬间增大15M左右,

具体原因不明,估计应该是内置PDF解析器的问题。于是,此方法被我抛弃了。

4.使用Moliza开源的Pdf.js(推荐)

这个JS类库也是很强大的,配合原生的WebView使用,支持预览,缩放,翻页的功能,实现效果和WKWebView没差。同样也有体积问题,全部放到本地apk的话包大小差不多会增加5M左右。但相比上一种方式还是轻量一些:
http://www.jb51.net/article/136364.htm

5.使用安卓自带的PdfRenderer类加载

如果要求支持的功能不是很多,用安卓提供的PdfRender就可以满足需求了。PdfRender加载多页的话可以配合ViewPager或者RecyclerView使用.需要注意的是使用PdfRender需要先将PDF文件下载到本地,是线程不安全的,并且API>=21才能使用。因为这种方式是将PDF下载到本地,于是就产生了新问题:占内存。如果是静态的PDF文件不大还好,但是如果是频繁加载网络PDF的需求,那就头疼了,这种方式需要做好定时清理删除PDF的工作,否则,GG。

这里提供的示例是阿里巴巴Android开发手册,放到assets目录下.

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MainActivity extends AppCompatActivity {

    private ViewPager vpPdf;

    private LayoutInflater mInflater;
    private ParcelFileDescriptor mDescriptor;
    private PdfRenderer          mRenderer;

    public static final String FILE_NAME = "alibaba.pdf";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mInflater = LayoutInflater.from(this);
        vpPdf =findViewById(R.id.vp_pdf);

        try {
            openRender();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void openRender() throws IOException {

        File file = new File(getExternalCacheDir(), FILE_NAME);
        if (!file.exists()) {
            //复制文件到本地存储
            InputStream asset = getAssets().open(FILE_NAME);
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024];

            int size;
            while ((size = asset.read(buffer)) != -1) {
                fos.write(buffer, 0, size);
            }

            asset.close();
            fos.close();
        }

        //初始化PdfRender
        mDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        if (mDescriptor != null) {
            mRenderer = new PdfRenderer(mDescriptor);
        }

        //初始化ViewPager的适配器并绑定
        MyAdapter adapter = new MyAdapter();
        vpPdf.setAdapter(adapter);
    }

    @Override
    protected void onDestroy() {
        //销毁页面的时候释放资源,习惯
        try {
            closeRenderer();
        } catch (IOException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

    private void closeRenderer() throws IOException{
        mRenderer.close();
        mDescriptor.close();

    }

    class MyAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return mRenderer.getPageCount();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view==object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = mInflater.inflate(R.layout.item_pdf, null);

            PhotoView pvPdf = view.findViewById(R.id.iv_pdf);
            pvPdf.enable();

            if (getCount() <= position) {
                return view;
            }

            PdfRenderer.Page currentPage = mRenderer.openPage(position);
            Bitmap bitmap = Bitmap.createBitmap(1080, 1760, Bitmap.Config
                    .ARGB_8888);
            currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
            pvPdf.setImageBitmap(bitmap);
            //关闭当前Page对象
            currentPage.close();

            container.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            //销毁需要销毁的视图
            container.removeView((View) object);
        }
    }

}
assets

 

PdfRender的大致调用方式是:

  • 初始化PdfRender,将PDF文件转换为ParcelFileDescriptor作为入参
  • 通过getPageCount()获得Pdf的总页数
  • 循环遍历,通过openPage()获得一个封装了当前页Pdf参数的内部类Page
  • 创建一个Bitmap对象,,用上步获取的Page加载,相当于把当前Pdf页的内容渲染到了Bitmap上
  • 对Bitmap进行你想要的操作,每次循环结束后关闭当前Page.

大部分都是常规操作,但要注意两点:

1,每次循环创建的Page对象在使用完毕后必须调用close().否则其内部的openPage()判断会抛异常;
2.Bitmap占用内存较大,如果用ViewPager加载一定要重写Adapter中的destroyItem(),及时的将需要销毁的视图从父容器中移除,否则快速滑动几页后会OOM

 
 

 
转自:https://www.jianshu.com/p/f68e1087ea36 

标签:intent,new,PDF,android,加载,public,Intent
From: https://www.cnblogs.com/zt007/p/16791897.html

相关文章

  • Android加载PDF方案(pdf.js,支持缩放)
    都知道,Android本身的webview是不支持pdf加载的(比不上iOS的webview,谁让人家NB呢),因此通过连接Google的一个服务器转换成功后返回给WebView显示。但是,但是,但是呢,大家都懂的,天......
  • 如何处理Office Powerpoint打开WPS文件提示异常加载项的问题
    https://answers.microsoft.com/zh-hans/msoffice/forum/all/ppt-关闭加载项/88896ada-41ab-48ed-a83e-282619f04f191.单击“文件”>“选项”>“加载项”,2.朝窗口底部“......
  • Android root 原理
    0x00关于rootlinux和类Unix系统的最初设计都是针对多用户的操作系统,对于用户权限的管理很非常严格的,而root用户(超级用户)就是整个系统的唯一管理员,拥有等同于操作系统的所有......
  • VMware虚拟机安装Android系统(转)
    一、首先我们先要准备好虚拟机和android系统安装包1、VMware下载:https://www.vmware.com/go/getworkstation-win激活码:ZF3R0-FHED2-M80TY-8QYGC-NPKYF2、Android系统下......
  • 用C#实现生成PDF文档
    usingSystem;usingSystem.IO;usingSystem.Text;usingSystem.Collections;namespacePDFGenerator{publicclassPDFGenerator{staticf......
  • 你真的懂谜男方法PDF吗?
    之前我听说过谜男方法后,感觉这本书挺不错的,在网上找了好久,终于找到谜男方法PDF微盘资源了,我通读了谜男方法PDF,把妹达人PDF,约会倍增术等书籍,而且看了网络上各种情感......
  • 【软件更新】系统激活、硬盘检测、XMind、IDM、万兴PDF、李跳跳、SpeedTest、Ventoy、
    今天照例给大家更新一下之前发过的软件到新版本。大家可以打开每个软件下的链接查看,或者在公众号后台回复相应的关键词获取百度网盘和蓝奏云的下载链接。Windows和Office激......
  • android开发使用git-tortoisesvn合并代码处理冲突的使用记录
    android开发使用git-tortoisesvn合并代码处理冲突的使用记录工具Androidstudio,Git,tortoisesvn作为Android开发的,androidstudio离不开,使用git管理项目也是离不开的,......
  • vant2 List 组件 下拉加载 onLoad
    ps:loadingfinishedonLoad两个变量一个函数;asynconLoad(){console.log("onload");//异步更新数据//setTimeout仅做示例,真实场景中一般为......
  • android开发记录一个依赖冲突问题
    Executionfailedfortask':ent:entPdfConvert:generateEntDebugRFile'.Couldnotresolveallfilesforconfiguration':ent:entPdfConvert:entDebugCompileClasspat......