You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Android Studio中用iText5添加PDF图片报NullPointerException的解决方法

解决Android中iText5添加图片时的NullPointerException问题

嘿,我太懂你试了四种方法都碰壁的烦躁了——其实问题核心出在资源路径错误或者Drawable类型不兼容上,我给你捋清楚靠谱的实现方式,分两种常用场景:

先说说你之前尝试的问题

快速拆解下你那四段代码的问题:

  • 方法1:assets.open("res/drawable/logo.png")完全搞错了目录,res/drawableassets是两个独立的资源文件夹,assets里根本没有这个路径。
  • 方法2/3:直接强制把Drawable转成BitmapDrawable,如果你的logo是矢量图(VectorDrawable),这会直接抛出ClassCastException,进而引发后续的NPE。
  • 方法4:Image.getInstance("res/drawable/logo.png")不认识Android的内部资源路径,iText会把它当成手机文件系统的路径,自然找不到资源。

正确实现方式

方式1:从res/drawable读取(兼容矢量图)

不管你的图片是普通Bitmap还是矢量图,这种方式都能安全转换:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import androidx.core.content.ContextCompat;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public Image getLogoFromDrawable(Context context) {
    try {
        // 用ContextCompat.getDrawable兼容不同Android版本
        Drawable drawable = ContextCompat.getDrawable(context, R.drawable.logo);
        if (drawable == null) {
            throw new IOException("找不到指定的Drawable资源");
        }

        // 将Drawable转为Bitmap(兼容矢量图)
        Bitmap bitmap = Bitmap.createBitmap(
                drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(),
                Bitmap.Config.ARGB_8888
        );
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        // 转成iText能识别的Image对象
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        Image image = Image.getInstance(stream.toByteArray());

        // 可选:调整图片大小,比如缩放至宽100px
        image.scaleToFit(100, 100);
        return image;
    } catch (IOException | BadElementException e) {
        e.printStackTrace();
        return null;
    }
}

方式2:从assets目录读取

如果你把图片放到assets文件夹下(比如创建assets/images/logo.png),可以直接读取:

import android.content.Context;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;
import java.io.IOException;
import java.io.InputStream;

public Image getLogoFromAssets(Context context) {
    try {
        // 注意assets里的路径是相对assets根目录的
        InputStream inputStream = context.getAssets().open("images/logo.png");
        Image image = Image.getInstance(inputStream);
        
        // 可选:按比例缩放50%
        image.scalePercent(50);
        return image;
    } catch (IOException | BadElementException e) {
        e.printStackTrace();
        return null;
    }
}

最后要注意的细节

  • 确保资源存在:检查文件名大小写(Android资源文件名是大小写敏感的),不要有空格或特殊字符。
  • 正确添加到PDF:获取到Image后,要在document.open()之后、document.close()之前调用document.add(image),不然也会出错。
  • 内存优化:如果是大图,建议先压缩再转换,避免出现OOM问题。

内容的提问来源于stack exchange,提问作者Otavio Miguel

火山引擎 最新活动