You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Android使用PDF生成库报Bitmap空指针错误求助

Fixing "Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference" in React Native PDF Generation

Let's break down why you're hitting this error and walk through how to fix it step by step:

Root Causes of the Error

This null pointer exception happens because the PDF generation library can't load your images properly—either the paths you're passing are invalid, the image data isn't accessible, or you're using a URI format the library can't handle (super common on Android). Here's what's off in your current code:

  1. Incorrect handling of multiple selected images
    When multiple: true is set in ImagePicker.openPicker, the callback returns an array of image objects, not a single image. Your current code tries to push image.path directly, which would either push undefined (since image is an array here) or only process one image incorrectly.

  2. Non-persistent state for image paths
    Declaring var photoPath = []; inside your component function means this array gets reset every time your component re-renders. By the time you try to generate the PDF, the array might not hold the paths you expect.

  3. Android URI compatibility issue
    On Android, react-native-image-crop-picker returns a content:// URI instead of a direct file system path. Libraries like react-native-image-to-pdf can't resolve these URIs to bitmaps natively, leading to the null Bitmap error you're seeing.

Step-by-Step Fix

Here's the revised code with all issues addressed:

import * as React from 'react';
import {View, Button, Dimensions, Platform} from 'react-native';
import ImagePicker from 'react-native-image-crop-picker';
import RNImageToPdf from 'react-native-image-to-pdf';
import RNFS from 'react-native-fs'; // Install via npm install react-native-fs

const {width: deviceWidth, height: deviceHeight} = Dimensions.get('window');

const App = () => {
  // Use useState to persist image paths across component re-renders
  const [photoPaths, setPhotoPaths] = React.useState([]);

  const handlePick = async () => {
    try {
      // Get the full array of selected images
      const images = await ImagePicker.openPicker({
        multiple: true,
      });

      // Convert Android content URIs to valid file paths
      const processedPaths = await Promise.all(
        images.map(async (image) => {
          if (Platform.OS === 'android' && image.path.startsWith('content://')) {
            // Resolve content URI to a readable file path
            const realPath = await RNFS.copyFileAssets(image.path, RNFS.DocumentDirectoryPath + `/temp_${Date.now()}.jpg`);
            return RNFS.DocumentDirectoryPath + `/temp_${Date.now()}.jpg`;
          }
          return image.path;
        })
      );

      // Update state with valid paths
      setPhotoPaths(processedPaths);

      // Generate the PDF
      const options = {
        imagePaths: processedPaths,
        name: 'PDFName',
        maxSize: {
          width: 900,
          height: Math.round((deviceHeight / deviceWidth) * 900),
        },
        quality: 0.7,
      };
      const pdf = await RNImageToPdf.createPDFbyImages(options);
      console.log('PDF generated at:', pdf.filePath);
    } catch (e) {
      console.error('Error during PDF generation:', e);
    }
  };

  return (
    <View style={{padding: 20}}>
      <Button title="Pick images" onPress={handlePick} />
    </View>
  );
};

export default App;

Key Fixes Explained

  • Use useState for image paths: This ensures your selected image paths are retained even when the component re-renders, avoiding unexpected empty arrays.
  • Handle multiple images correctly: We iterate over the full images array returned by the picker, processing every selected image.
  • Resolve Android content URIs: We use react-native-fs to copy the content URI-backed image to a local file path that the PDF library can read directly.
  • Simplify async flow: Replaced nested promise chains with async/await for cleaner, more maintainable code and better error handling.

Additional Checks

  • Make sure you've added the required permissions to your AndroidManifest.xml:
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
  • For Android API 30+, you may need to adjust scoped storage settings or request the MANAGE_EXTERNAL_STORAGE permission if your use case requires it.

内容的提问来源于stack exchange,提问作者g-mahendra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:47:41