Android:PDF文件签批功能实现历程

我正在参加「掘金·启航计划」,这是我参加的第5篇文章。

这次的启航计划连上这篇是第5篇,几乎都是最近项目中遇到的问题和实现的方式。不难发现,近期和签名相关功能杠上了,本篇就来简单聊聊在Android上如何实现PDF文件签批功能。

实现PDF文件签批,具体需要具备什么功能呢:

  • 在手机上展示PDF文件
  • 在页面上使用手签功能用于批注
  • 保存批注信息到PDF文件(这一步很关键)
  • 回显带有批注的PDF文件,支持删除和再次添加(这一步很关键)

在这之前很少接触到这类功能,唯一有重合点的是用过腾讯的TBS,内部有一个类可用于加载这些办公类文件。问题也比较多,必须成功加载它的x5内核才能正常加载这些文件,而在某些机型上大概率需要手动下载x5内核。如今这个项目由于一些特殊原因,不能使用网络,所以这个库也不能使用,于是首先开启了寻找加载PDF的相关库。

  1. 安卓自带库PdfRenderer: 将PDF文件转为Bitmap的方式加载。
  2. 优秀的第三方库AndroidPdfViewer 星数高达7.6k,最后维护时间是4年前,仅支持加载功能
  3. 支持签批功能的PdfViewerDemo 星数118,最后维护时间也是4年前,但支持签批功能,完全无法扩展

搜索了一大圈发现可用的东西并不多,要实现PDF插入信息就得借助类似MuPDF、PDFBox、IText、droidText相关库。其中还涉及到放大缩小的时候签名信息跟着变化,滑动的一些处理等等,可以说功能还是比较复杂,想要自己造一个估计是不可能了,最后选择了第三种方式去实现。

PdfViewerDemo:

该库跑起来基本功能都有,但可定制化几乎无,只能修改外部一些界面。心想能不能通过继承的方式去自定义一些属性和功能,最后发现一动则全动。没有源码可不行,于是用了最笨的方式手动复制了该依赖库,又在网上下载了依赖中的droidText.jar包,最关键的其实还是so库,虽说该库中有编译好的so库文件,但配置的时候位置没放好会出现编译失败的情况。

image.png

最终折腾了一两天完美复刻了该库,内部也可根据需求修改。心想能将自己带笔锋效果的功能移植进去,最后却碰了个大壁。该库仅仅支持点的批注,而我实现的笔锋效果是用椭圆。由于大部分操作PDF的功能都是用C写的,这里只能先到此为止。

//获取当前绘制信息
protected PointF[][] getDraw() {
    if (mDrawing == null)
        return null;

    PointF[][] path = new PointF[mDrawing.size()][];

    for (int i = 0; i < mDrawing.size(); i++) {
        ArrayList<PointF> arc = mDrawing.get(i);
        path[i] = arc.toArray(new PointF[arc.size()]);
    }

    return path;
}

/**
    * 绘制
    * @param arcs 点
    * @param colorR 颜色值 R
    * @param colorG 颜色值 G
    * @param colorB 颜色值 B
    * @param inkThickness 线的粗细
    * 添加批注到pdf
    */
private native void addInkAnnotationInternal(PointF[][] arcs, float colorR, float colorG, float colorB, float inkThickness);

另外,在使用过程中发现放大拖动时速度相当快,体验不是很好,领导要求优化。好在我们复刻了除C以外的源码,通过调试发现在onScroll回调中其赋值的滑动距离值mXScroll减幅过大,将其值减小后拖动效果相对较缓,这个根据自己需求修改即可。

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                        float distanceY) {
    if (!mScaling) {
        //mXScroll -= distanceX;
        //mYScroll -= distanceY;
        mXScroll -= distanceX/3;
        mYScroll -= distanceY/2;
        requestLayout();
    }
    return true;
}

接下来让我们看看完成后的效果:

image.png

放大:

image.png

好了,以上便是在PDF文件签批功能实现历程的一些经验,希望对大家有所帮助。如有好的方案也可留言分享。   

我是一个喜爱Jay、Vae的安卓开发者,喜欢结交五湖四海的兄弟姐妹,欢迎大家到沸点来点歌!