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

