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

Android Studio中自定义相机拍摄图片如何设置到GridView并传递路径

代码存在的核心问题
  • 异步执行逻辑顺序错误:camera.takePicture()是异步操作,点击拍照按钮后立刻读取文件路径,此时图片还未写入存储,拿到的是空或者旧文件。且拍照按钮里创建的Intent未调用startActivity(),参数根本没有传递到相册页。
  • 传参类型不匹配:MainActivity中存入Intent的是字符串类型的图片路径,CustomGallary中却按Bitmap类型读取,必然返回null。
  • 存储权限缺失:仅申请了相机权限,未申请存储读写权限,安卓10以下无法写入外部存储,安卓13以上无法读取公共目录图片。
  • 图片命名重复:保存的图片固定命名为temp.jpg,每次拍照都会覆盖上一张,最终相册只能看到最新一张图片。
  • GridView适配器使用错误:系统默认ArrayAdapter仅适配TextView布局,无法直接加载Bitmap到ImageView,需要自定义适配器。
  • 相册页逻辑错误:仅尝试读取传入的单张图片,没有扫描存储自定义图片的GUI文件夹下的所有图片,不符合自定义相册的功能需求。
修复方案

1. 修复MainActivity逻辑

补全权限申请

在AndroidManifest.xml中添加权限:

<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 安卓9及以下存储写入权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<!-- 安卓13及以上图片读取权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

在MainActivity的权限申请逻辑中,同步申请存储相关权限。

修改图片命名逻辑,避免覆盖

修改getOutputMediaFile()方法,用时间戳作为文件名:

private File getOutputMediaFile() {
    String state= Environment.getExternalStorageState();
    if(!state.equals(Environment.MEDIA_MOUNTED)) {
        return null;
    } else {
        File folder_gui= new File(Environment.getExternalStorageDirectory()+ File.separator + "GUI");
        if(!folder_gui.exists()) {
            folder_gui.mkdirs();
        }
        // 用时间戳命名避免覆盖
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File outputFile= new File(folder_gui,"IMG_"+timeStamp+".jpg");
        return  outputFile;
    }
}

调整跳转时机,确保图片写入完成后再操作

修改PictureCallback,图片写入完成后如果需要直接跳转相册可以在这里触发:

Camera.PictureCallback mpictureCallback=new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        File picture_file = getOutputMediaFile();
        if(picture_file== null) {
            return;
        } else {
            try {
                FileOutputStream fos=new FileOutputStream(picture_file);
                fos.write(data);
                fos.close();
                // 通知系统媒体库更新,方便其他应用识别到新图片
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(picture_file)));
                camera.startPreview();
                // 如果需要拍完照直接跳相册,在这里启动Intent
                Intent i=new Intent(MainActivity.this,CustomGallary.class);
                startActivity(i);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
};

2. 修复CustomGallary逻辑

扫描GUI文件夹获取所有图片路径

不要从Intent传单张路径,直接扫描目标文件夹下所有图片:

private ArrayList<String> getAllImagePaths() {
    ArrayList<String> imagePaths = new ArrayList<>();
    File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "GUI");
    if (folder.exists() && folder.isDirectory()) {
        File[] files = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".jpg") || name.toLowerCase().endsWith(".png"));
        if (files != null) {
            for (File file : files) {
                imagePaths.add(file.getAbsolutePath());
            }
        }
    }
    // 按时间倒序排列,最新的图片在最前面
    Collections.reverse(imagePaths);
    return imagePaths;
}

自定义GridView适配器

public class ImageGridAdapter extends BaseAdapter {
    private Context mContext;
    private ArrayList<String> mImagePaths;

    public ImageGridAdapter(Context context, ArrayList<String> paths) {
        mContext = context;
        mImagePaths = paths;
    }

    @Override
    public int getCount() {
        return mImagePaths.size();
    }

    @Override
    public Object getItem(int position) {
        return mImagePaths.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(300, 300));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        } else {
            imageView = (ImageView) convertView;
        }
        // 采样压缩加载图片,避免OOM
        Bitmap bitmap = decodeSampledBitmapFromPath(mImagePaths.get(position), 300, 300);
        imageView.setImageBitmap(bitmap);
        // 点击图片跳转下一页的逻辑,把路径传过去
        imageView.setOnClickListener(v -> {
            Intent intent = new Intent(mContext, NextActivity.class);
            intent.putExtra("image_path", mImagePaths.get(position));
            mContext.startActivity(intent);
        });
        return imageView;
    }

    // 图片采样压缩方法
    private Bitmap decodeSampledBitmapFromPath(String path, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(path, options);
    }

    private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
}

修改CustomGallary的onCreate逻辑

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.image_view);
    GridView mygrid=findViewById(R.id.gv);
    // 获取所有图片路径
    ArrayList<String> imagePaths = getAllImagePaths();
    // 设置自定义适配器
    ImageGridAdapter adapter = new ImageGridAdapter(this, imagePaths);
    mygrid.setAdapter(adapter);
}

3. 跨页面传图片路径的方法

直接在Intent中存入字符串类型的路径即可,下一页接收后再加载图片:

// 发送页
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);
intent.putExtra("image_path", 图片的绝对路径);
startActivity(intent);

// 接收页
String imagePath = getIntent().getStringExtra("image_path");
// 之后加载图片到ImageView即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 23:36:09