谷歌MapAndroid v2:快照失败,位图大小为零

dfuffjeb  于 2022-11-27  发布在  Android
关注(0)|答案(2)|浏览(120)

我想使用Google Map v2快照填充ImageView。

简短总结:
我是否仍需要膨胀Maps XML示例?
我需要使用“Map”片段吗?
我是否希望以编程方式创建“Map”示例并只拍摄快照?
我的想法是通过编程创建一个Maps示例,适当地调整它的大小(比如200 x200),然后拍摄快照。但是,我的快照例程总是崩溃,并显示**“Bitmap must be〉0 in height and width”**。
这是错误的方法吗?
XML应该是这样的:

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:orientation="vertical" >
        <ImageView android:id="@+id/location_card_map"
            android:layout_width="match_parent" 
            android:layout_height="match_parent" 
            android:contentDescription="Location"
            android:clickable="true"/>
    </LinearLayout>

Map类别:

private ManagerMaps(Context context)
    {
        mContext = context;
        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        initializeMaps();
    }
...
            private void initializeMaps()
            {
                LinearLayout layout = new LinearLayout(mContext);
                layout.setOrientation(LinearLayout.HORIZONTAL);
                layout.setLayoutParams(new  LinearLayout.LayoutParams(200,200));//(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
                GoogleMapOptions options = new GoogleMapOptions();
                options.camera(new CameraPosition(new LatLng(0, 0), 1, 0, 0));

                // Create the MapView programmatically
                mMapView = new MapView(mContext, options);
                layout.addView(mMapView);
                    mMapView.setLayoutParams(new LayoutParams(200,200));        
                mMapView.onCreate(null);
                mMapView.onResume();
        //      setContentView(layout);        

                // Gets to GoogleMap from the MapView and does initialization stuff
                mMap = mMapView.getMap();
                if(mMap == null)
                {
                    Log.d("AppDebug", "MAP IS NULL ********");
                    return;
                }
                mMap.getUiSettings().setMyLocationButtonEnabled(true);
                mMap.setMyLocationEnabled(true);

                // Needs to call MapsInitializer before doing any CameraUpdateFactory calls
                try {
                    MapsInitializer.initialize(mContext);
                } catch (GooglePlayServicesNotAvailableException e) {
                    e.printStackTrace();
                }

            }

            public void captureMapScreen() 
            {
                SnapshotReadyCallback callback = new SnapshotReadyCallback() {

                    @Override
                    public void onSnapshotReady(Bitmap snapshot) {
                        try {
                            FileOutputStream out = new FileOutputStream(
                                    Environment.getExternalStorageDirectory()
                                            + "/MapScreenShot"
                                            + System.currentTimeMillis() + ".png");

                            snapshot.compress(Bitmap.CompressFormat.PNG, 90, out);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                };
                mMap.snapshot(callback);  // crashes in bitmap thread here with height/width zero
            }

调用方法:

ManagerMaps maps = ManagerMaps.getInstance(getActivity());
                maps.captureMapScreen();

编辑:
崩溃发生在:mMap.snapshot(回调);

日志类别

10-22 01:36:44.300: E/AndroidRuntime(29292): FATAL EXCEPTION: Thread-3366
10-22 01:36:44.300: E/AndroidRuntime(29292): java.lang.IllegalArgumentException: width and height must be > 0
10-22 01:36:44.300: E/AndroidRuntime(29292):    at android.graphics.Bitmap.createBitmap(Bitmap.java:695)
10-22 01:36:44.300: E/AndroidRuntime(29292):    at android.graphics.Bitmap.createBitmap(Bitmap.java:674)
10-22 01:36:44.300: E/AndroidRuntime(29292):    at android.graphics.Bitmap.createBitmap(Bitmap.java:641)
10-22 01:36:44.300: E/AndroidRuntime(29292):    at maps.ag.ca.a(Unknown Source)
10-22 01:36:44.300: E/AndroidRuntime(29292):    at maps.ag.av.run(Unknown Source)
10-22 01:36:44.300: E/AndroidRuntime(29292):    at java.lang.Thread.run(Thread.java:841)
ilmyapht

ilmyapht1#

谷歌Map(在2022年)仍然抛出一个无意义的createBitmap(),而不是一些错误,如“Map视图大小0,请推迟快照,直到布局后...”

Crash: java.lang.IllegalArgumentException: width and height must be > 0
    at android.graphics.Bitmap.createBitmap(Bitmap.java:969)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:948)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:915)
    at com.google.maps.api.android.lib6.impl.a.d(:com.google.android.gms.dynamite_mapsdynamite@224312019@22.43.12 (040400-0):2)
    at com.google.maps.api.android.lib6.impl.bh.run(:com.google.android.gms.dynamite_mapsdynamite@224312019@22.43.12 (040400-0):1)
    at java.lang.Thread.run(Thread.java:762)

我通过延迟快照,直到布局发生并且通过onMapReady设置Map后,才解决了我这边的问题:

import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import androidx.core.view.doOnNextLayout
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import dk.bnr.androidbooking.extensions.iterateAndClear

class Map : SupportMapFragment(), OnMapReadyCallback {
    private val pendingOnAvailableBeforeRendering = mutableListOf<() -> Unit>()
    private var isLaidOut: Boolean = false // we have a size for the map - this is required for camera changes
    private var isMapAvailable: Boolean = false // available (onMapReady) but possibly not loaded yet, don't do animation stuff yet
    private lateinit var googleMap: GoogleMap    
    
    private inline val isMapReadyForCameraChange
        get() = isMapAvailable && isLaidOut // maybe also include isMapLoaded

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.doOnNextLayout {
            isLaidOut = true
            // GoogleMap may not be ready yet, so this also waits for GoogleMap ready
            executePendingActions()
        }
    }

    override fun onMapReady(googleMap: GoogleMap) {
        executePendingActions()
    }

    private fun executePendingActions() {
        if (isMapReadyForCameraChange) {
            pendingOnAvailableBeforeRendering.iterateAndClear {
                it()
            }
        }
    }

    private fun executeWhenReady(action: () -> Unit) {
        if (isMapReadyForCameraChange) action()
        else pendingOnAvailableBeforeRendering.add(action)
    }

    fun snapshot(action: (Bitmap?) -> Unit) {
        executeWhenReady {
            val view = this.view
            // This is hopefully not necessary, but I want to be sure, so we avoid createBitmap crash. It would make sense to log error if this view isn't ready
            if (view != null && view.width != 0 && view.height != 0) {
                googleMap.snapshot { bitmap: Bitmap? ->
                    action(bitmap)
                }
            } else {
                // TODO Log error
                action(null)
            }
        }
    }
}
oprakyz7

oprakyz72#

这个问题是由Android中可绘制资源的自动缩放和非常小的可绘制资源的不幸组合引起的。
例如,如果您的应用只提供drawable-xhpdi资源,则需要缩小这些资源以适应低密度屏幕。如果您自己不提供这些资源,Android会自动执行此操作。
显示密度的比例设置如下:
x高分辨率:2.0高分辨率:1.5百万像素/英寸:1.0百万像素/英寸:0.75
有时很遗憾,当以xhdpi格式提供这些资源并将其缩小时,像素大小可能会被截断为0。对此没有任何保护措施,Android将无法创建具有该尺寸的位图,并崩溃显示IllegalArgumentException: width and height must be > 0
但我不确定你的情况。所以请更新您的问题与日志猫。
更新它lyk:

public void captureMapScreen() {
        SnapshotReadyCallback callback = new SnapshotReadyCallback() {

            @Override
            public void onSnapshotReady(Bitmap snapshot) {
                try {
                    mView.setDrawingCacheEnabled(true);
                    Bitmap backBitmap = mView.getDrawingCache();
                    Bitmap bmOverlay = Bitmap.createBitmap(
                            backBitmap.getWidth(), backBitmap.getHeight(),
                            backBitmap.getConfig());
                    Canvas canvas = new Canvas(bmOverlay);
                    canvas.drawBitmap(snapshot, new Matrix(), null);
                    canvas.drawBitmap(backBitmap, 0, 0, null);
                    FileOutputStream out = new FileOutputStream(
                            Environment.getExternalStorageDirectory()
                                    + "/MapScreenShot"
                                    + System.currentTimeMillis() + ".png");

                    bmOverlay.compress(Bitmap.CompressFormat.PNG, 90, out);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        mMap.snapshot(callback);

    }

使用snapshot.compress(Bitmap.CompressFormat.PNG, 90, out);获取Map截图并避免代码

mView.setDrawingCacheEnabled(true);
Bitmap backBitmap = mView.getDrawingCache();
Bitmap bmOverlay = Bitmap.createBitmap(
backBitmap.getWidth(), backBitmap.getHeight(),
backBitmap.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(snapshot, new Matrix(), null);
canvas.drawBitmap(backBitmap, 0, 0, null);

相关问题