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

Android端Google Maps长按拍照后无法将图片设为点位标记如何解决

问题根因排查
  • 核心问题1:onActivityResult 方法位置错误
    你当前把onActivityResult定义在了OnMapLongClickListener匿名内部类中,这是你自行新增的自定义方法,安卓系统只会回调宿主Activity/Fragment层级的onActivityResult,所以拍照返回后你的添加标记逻辑完全没有执行,自然不会生成标记也不会抛出报错。
  • 核心问题2:长按点位参数未持久化存储
    你没有把长按触发时得到的LatLng点位信息保存为全局成员变量,拍照返回后无法获取之前点击的点位坐标。
  • 核心问题3:类型转换异常隐患
    GetImageThumbnail的getThumbnail方法中直接把OnMapLongClickListener实例强转为Context,会抛出类型转换异常,导致Bitmap生成失败。
  • 其他潜在问题:
    1. 每次拍照保存的文件名都是test.png,会覆盖上一次的照片
    2. 高版本安卓系统中直接使用Environment.getExternalStorageDirectory会受分区存储限制,导致图片保存/读取失败
    3. 未做Bitmap空值判断,如果Bitmap生成失败直接传给BitmapDescriptorFactory会引发崩溃
修复方案

步骤1:声明全局成员变量

在你的Activity/Fragment类中添加如下成员变量:

private LatLng mLastLongClickLatLng; // 保存上次长按的点位
private Uri mCameraImageUri; // 保存拍照输出的Uri
private static final int TAKE_PICTURE = 1001; // 自行与原有请求码保持统一

步骤2:修改长按监听逻辑

不要在监听器内部写onActivityResult,长按的时候只保存点位和启动相机:

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    // 原有初始化逻辑保留
    LatLng mylocation = new LatLng(-xx.xxxx, xx.xxxx);
    mMap.addMarker(new MarkerOptions().position(mylocation).title("Marker in mylocation"));
    CameraPosition cameraPosition = new CameraPosition.Builder().target(mylocation).zoom(12).build();
    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    
    googleMap.setOnMapLongClickListener(latLng -> {
        // 保存长按的点位
        mLastLongClickLatLng = latLng;
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        String root = Environment.getExternalStorageDirectory().toString() + "/My Folder/saved_images";
        File imagesFolder = new File(root);
        if (!imagesFolder.exists()) {
            imagesFolder.mkdirs();
        }
        // 用时间戳命名避免覆盖
        String imageName = System.currentTimeMillis() + ".png";
        File image = new File(imagesFolder, imageName);
        mCameraImageUri = Uri.fromFile(image);
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraImageUri);
        startActivityForResult(takePictureIntent, TAKE_PICTURE);
    });
}

步骤3:在Activity/Fragment层级重写onActivityResult

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == TAKE_PICTURE && resultCode == RESULT_OK) {
        if (mLastLongClickLatLng == null || mCameraImageUri == null) {
            return;
        }
        try {
            GetImageThumbnail getImageThumbnail = new GetImageThumbnail();
            // 传入当前Activity的Context作为参数
            Bitmap bitmap = getImageThumbnail.getThumbnail(mCameraImageUri, this);
            if (bitmap != null) {
                MarkerOptions markerOptions = new MarkerOptions()
                        .position(mLastLongClickLatLng)
                        .icon(BitmapDescriptorFactory.fromBitmap(bitmap));
                mMap.addMarker(markerOptions);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

步骤4:修改GetImageThumbnail方法参数

public Bitmap getThumbnail(Uri uri, Context context) throws IOException {
    InputStream input = context.getContentResolver().openInputStream(uri);
    // 原有逻辑全部保留即可
    BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
    onlyBoundsOptions.inJustDecodeBounds = true;
    onlyBoundsOptions.inDither = true;
    onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
    BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
    input.close();
    if ((onlyBoundsOptions.outWidth == -2) || (onlyBoundsOptions.outHeight == -2))
        return null;

    int originalSize = Math.max(onlyBoundsOptions.outHeight, onlyBoundsOptions.outWidth);
    double ratio = (originalSize > 200) ? (originalSize / 175) : 0.5;

    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
    bitmapOptions.inDither = true;
    bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
    input = context.getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
    input.close();
    return bitmap;
}
额外优化建议
  • 安卓7.0及以上版本禁止应用暴露file://类型的Uri,建议替换StrictMode的绕过方案,使用FileProvider生成content://类型的Uri传递给相机
  • 安卓6.0及以上需要动态申请WRITE_EXTERNAL_STORAGE权限,安卓10及以上适配分区存储,可将图片存到应用专属外部目录避免权限申请
  • 生成Bitmap后可以做适当的压缩,避免图片过大导致标记加载异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 05:24:07