【问题标题】:Capture screen shot of GoogleMap Android API V2捕获 Google Map Android API V2 的屏幕截图
【发布时间】:2012-11-26 06:07:44
【问题描述】:

最终更新

Google 已满足功能请求。请看this answer below.

原始问题

使用旧版本的 Google Maps Android API,我能够截取谷歌地图的屏幕截图以通过社交媒体分享。我使用以下代码捕获屏幕截图并将图像保存到文件中,效果很好:

public String captureScreen()
{
    String storageState = Environment.getExternalStorageState();
    Log.d("StorageState", "Storage state is: " + storageState);

    // image naming and path  to include sd card  appending name you choose for file
    String mPath = this.getFilesDir().getAbsolutePath();

    // create bitmap screen capture
    Bitmap bitmap;
    View v1 = this.mapView.getRootView();
    v1.setDrawingCacheEnabled(true);
    bitmap = Bitmap.createBitmap(v1.getDrawingCache());
    v1.setDrawingCacheEnabled(false);

    OutputStream fout = null;

    String filePath = System.currentTimeMillis() + ".jpeg";

    try 
    {
        fout = openFileOutput(filePath,
                MODE_WORLD_READABLE);

        // Write the string to the file
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
        fout.flush();
        fout.close();
    } 
    catch (FileNotFoundException e) 
    {
        // TODO Auto-generated catch block
        Log.d("ImageCapture", "FileNotFoundException");
        Log.d("ImageCapture", e.getMessage());
        filePath = "";
    } 
    catch (IOException e) 
    {
        // TODO Auto-generated catch block
        Log.d("ImageCapture", "IOException");
        Log.d("ImageCapture", e.getMessage());
        filePath = "";
    }

    return filePath;
}

但是,API V2 使用的新 GoogleMap 对象没有 MapView 那样的“getRootView()”方法。

我尝试过这样做:

    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.basicMap);

    View v1 = mapFragment.getView();

但我得到的截图没有任何地图内容,看起来像这样:

有人知道如何截取新的 Google Maps Android API V2 的屏幕截图吗?

更新

我也试过这样获取rootView:

View v1 = getWindow().getDecorView().getRootView();

这会生成一个屏幕截图,其中包含屏幕顶部的操作栏,但地图仍然是空白的,就像我附上的屏幕截图一样。

更新

功能请求已提交给 Google。如果您希望 Google 将来添加此功能请求,请为功能请求添加星标:Add screenshot ability to Google Maps API V2

【问题讨论】:

  • 现在他们使用向量是我在某些地方读到的。不知道该怎么做

标签: android android-mapview google-maps-android-api-2


【解决方案1】:

使用mapcalback获取地图截图

 GoogleMap.SnapshotReadyCallback callback = new GoogleMap.SnapshotReadyCallback() {
                    Bitmap bitmap=null;
                    @Override
                    public void onSnapshotReady(Bitmap snapshot) {
                        // TODO Auto-generated method stub
                        bitmap = snapshot;
                        try {
                            saveImage(bitmap);
                            Toast.makeText(getActivity().getApplicationContext(), "Successful.Screenshot Saved.", Toast.LENGTH_LONG).show();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    private void saveImage(Bitmap bitmap) throws IOException {
                        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

                        Date date = new Date();
                        CharSequence format = android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", date);
                        String dirpath = Environment.getExternalStorageDirectory() + "";
                        File file = new File(dirpath);
                        if (!file.exists()) {
                            boolean mkdir = file.mkdir();
                        }
                        String path1 = dirpath + "/Documents/SCREENSHOT/";
                        File imageurl1 = new File(path1);
                        imageurl1.mkdirs();
                        File f = new File(path1 +"/"+ format + ".png");
                        f.createNewFile();
                        FileOutputStream fo = new FileOutputStream(f);
                        fo.write(bytes.toByteArray());
                        fo.close();
                    }
                };
                mMap.snapshot(callback);

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

我截取了地图截图,会有帮助的

  private GoogleMap map;
 private static LatLng latLong;

`

public void onMapReady(GoogleMap googleMap) {
           map = googleMap;
           setMap(this.map);
           animateCamera();
            map.moveCamera (CameraUpdateFactory.newLatLng (latLong));
            map.setOnMapLoadedCallback (new GoogleMap.OnMapLoadedCallback () {
                @Override
                public void onMapLoaded() {
                    snapShot();
                }
            });
        }

`

snapShot() 方法截取地图

 public void snapShot(){
    GoogleMap.SnapshotReadyCallback callback=new GoogleMap.SnapshotReadyCallback () {
        Bitmap bitmap;
        @Override
        public void onSnapshotReady(Bitmap snapshot) {
            bitmap=snapshot;

            try{
                file=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"map.png");
                FileOutputStream fout=new FileOutputStream (file);
                bitmap.compress (Bitmap.CompressFormat.PNG,90,fout);
                Toast.makeText (PastValuations.this, "Capture", Toast.LENGTH_SHORT).show ();

            }catch (Exception e){
                e.printStackTrace ();
                Toast.makeText (PastValuations.this, "Not Capture", Toast.LENGTH_SHORT).show ();
            }


        }
    };map.snapshot (callback);
}

我的输出低于

【讨论】:

  • 这很好,它正在将图片保存在图片文件夹中..
【解决方案3】:
private GoogleMap mMap;
SupportMapFragment mapFragment;
LinearLayout linearLayout;
String jobId="1";

文件文件;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate (savedInstanceState);
    setContentView (R.layout.activity_maps);

    linearLayout=(LinearLayout)findViewById (R.id.linearlayout);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
     mapFragment = (SupportMapFragment)getSupportFragmentManager ()
            .findFragmentById (R.id.map);
    mapFragment.getMapAsync (this);
    //Taking Snapshot of Google Map


}



/**
 * Manipulates the map once available.
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    // Add a marker in Sydney and move the camera
    LatLng sydney = new LatLng (-26.888033, 75.802754);
    mMap.addMarker (new MarkerOptions ().position (sydney).title ("Kailash Tower"));
    mMap.moveCamera (CameraUpdateFactory.newLatLng (sydney));
    mMap.setOnMapLoadedCallback (new GoogleMap.OnMapLoadedCallback () {
        @Override
        public void onMapLoaded() {
            snapShot();
        }
    });
}

// Initializing Snapshot Method
public void snapShot(){
    GoogleMap.SnapshotReadyCallback callback=new GoogleMap.SnapshotReadyCallback () {
        Bitmap bitmap;
        @Override
        public void onSnapshotReady(Bitmap snapshot) {
            bitmap=snapshot;
            bitmap=getBitmapFromView(linearLayout);
            try{
               file=new File (getExternalCacheDir (),"map.png");
                FileOutputStream fout=new FileOutputStream (file);
                bitmap.compress (Bitmap.CompressFormat.PNG,90,fout);
                Toast.makeText (MapsActivity.this, "Capture", Toast.LENGTH_SHORT).show ();
                sendSceenShot (file);
            }catch (Exception e){
                e.printStackTrace ();
                Toast.makeText (MapsActivity.this, "Not Capture", Toast.LENGTH_SHORT).show ();
            }


        }
    };mMap.snapshot (callback);
}
private Bitmap getBitmapFromView(View view) {
    Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas (returnedBitmap);
    Drawable bgDrawable =view.getBackground();
    if (bgDrawable!=null) {
        //has background drawable, then draw it on the canvas
        bgDrawable.draw(canvas);
    }   else{
        //does not have background drawable, then draw white background on the canvas
        canvas.drawColor(Color.WHITE);
    }
    view.draw(canvas);
    return returnedBitmap;
}

//Implementing Api using Retrofit
private void sendSceenShot(File file) {
    RequestBody job=null;

    Gson gson = new GsonBuilder ()
            .setLenient ()
            .create ();

    Retrofit retrofit = new Retrofit.Builder ()
            .baseUrl (BaseUrl.url)
            .addConverterFactory (GsonConverterFactory.create (gson))
            .build ();

    final RequestBody requestBody = RequestBody.create (MediaType.parse ("image/*"),file);
    job=RequestBody.create (MediaType.parse ("text"),jobId);


    MultipartBody.Part  fileToUpload = MultipartBody.Part.createFormData ("name",file.getName (), requestBody);

    API service = retrofit.create (API.class);
    Call<ScreenCapture_Pojo> call=service.sendScreen (job,fileToUpload);
    call.enqueue (new Callback<ScreenCapture_Pojo> () {
        @Override
        public void onResponse(Call <ScreenCapture_Pojo> call, Response<ScreenCapture_Pojo> response) {
            if (response.body ().getMessage ().equalsIgnoreCase ("Success")){
                Toast.makeText (MapsActivity.this, "success", Toast.LENGTH_SHORT).show ();
            }
        }

        @Override
        public void onFailure(Call <ScreenCapture_Pojo> call, Throwable t) {

        }
    });

}

}

【讨论】:

  • 你好,成功的代码。
  • 我希望这将有助于捕获您的地图的屏幕截图,并且您可以使用改造在服务器上发送而无需保存到外部存储中。请发表评论。
  • 截图示例,然后呈现标准的“图像发送。这个完整的源代码。请订阅我的页面。
  • 如果特定视图包含 ImageView、TextView 和 mapView(都带有值),我会截屏吗?
【解决方案4】:

我希望这将有助于捕获您的地图的屏幕截图

方法调用:

gmap.setOnMapLoadedCallback(mapLoadedCallback);

方法声明:

final SnapshotReadyCallback snapReadyCallback = new SnapshotReadyCallback() {
        Bitmap bitmap;
        @Override
        public void onSnapshotReady(Bitmap snapshot) {
            bitmap = snapshot;

            try {

                //do something with your snapshot

                imageview.setImageBitmap(bitmap);

            } catch (Exception e) {
                e.printStackTrace();
            }


        }
    };

GoogleMap.OnMapLoadedCallback mapLoadedCallback = new GoogleMap.OnMapLoadedCallback() {
        @Override
        public void onMapLoaded() {
            gmap.snapshot(snapReadyCallback);
        }
};

【讨论】:

    【解决方案5】:

    由于投票最多的答案不适用于地图片段顶部的折线和其他叠加层(我在寻找什么),我想分享这个解决方案。

    public void captureScreen()
            {
                GoogleMap.SnapshotReadyCallback callback = new GoogleMap.SnapshotReadyCallback()
                {
    
    
                    @Override
                    public void onSnapshotReady(Bitmap snapshot) {
                        try {
                            getWindow().getDecorView().findViewById(android.R.id.content).setDrawingCacheEnabled(true);
                            Bitmap backBitmap = getWindow().getDecorView().findViewById(android.R.id.content).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);
    
                            OutputStream fout = null;
    
                            String filePath = System.currentTimeMillis() + ".jpeg";
    
                            try
                            {
                                fout = openFileOutput(filePath,
                                        MODE_WORLD_READABLE);
    
                                // Write the string to the file
                                bmOverlay.compress(Bitmap.CompressFormat.JPEG, 90, fout);
                                fout.flush();
                                fout.close();
                            }
                            catch (FileNotFoundException e)
                            {
                                // TODO Auto-generated catch block
                                Log.d("ImageCapture", "FileNotFoundException");
                                Log.d("ImageCapture", e.getMessage());
                                filePath = "";
                            }
                            catch (IOException e)
                            {
                                // TODO Auto-generated catch block
                                Log.d("ImageCapture", "IOException");
                                Log.d("ImageCapture", e.getMessage());
                                filePath = "";
                            }
    
                            openShareImageDialog(filePath);
    
    
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                };
    
               ;
    
    
                map.snapshot(callback);
            }
    

    【讨论】:

    • 公认的答案绝对适用于折线和叠加层——这就是共享地图图像的全部意义所在,因为我画了一堆折线、标记和叠加层,并想捕捉它。您将折线添加到地图的方式可能存在问题?
    【解决方案6】:

    编辑:此答案不再有效 - Google Maps Android API V2 上的屏幕截图功能请求已得到满足。见this answer for an example

    接受的原始答案

    由于新的 Android API v2 地图使用 OpenGL 显示,因此无法创建屏幕截图。

    【讨论】:

    • 你能引用这个答案的来源吗?
    • 我主要从官方API docs得到这个,另外还有this post
    • 我见过这样的问题:stackoverflow.com/questions/3310990/… 不过,这似乎表明可以截取 OpenGL 层的屏幕截图......虽然我对 OpenGL 几乎一无所知,所以这就是为什么我我正在寻求帮助...
    • 问题是用于显示地图的OpenGL SurfaceView通过MapView/MapFragment被黑盒化掉了...
    • 您可以为以下功能请求点赞/加注星标,以便 Google 在 API 中添加屏幕截图支持:code.google.com/p/gmaps-api-issues/issues/detail?id=4898
    【解决方案7】:

    更新 - Google 添加了快照方法**!:

    对获取 Android Google Map API V2 OpenGL 层屏幕截图的方法的功能请求已完成。

    要截屏,只需实现以下接口:

    public abstract void onSnapshotReady (Bitmap snapshot)
    

    然后调用:

    public final void snapshot (GoogleMap.SnapshotReadyCallback callback)

    截取屏幕截图,然后显示标准“图像共享”选项的示例:

    public void captureScreen()
        {
            SnapshotReadyCallback callback = new SnapshotReadyCallback() 
            {
    
                @Override
                public void onSnapshotReady(Bitmap snapshot) 
                {
                    // TODO Auto-generated method stub
                    bitmap = snapshot;
    
                    OutputStream fout = null;
    
                    String filePath = System.currentTimeMillis() + ".jpeg";
    
                    try 
                    {
                        fout = openFileOutput(filePath,
                                MODE_WORLD_READABLE);
    
                        // Write the string to the file
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
                        fout.flush();
                        fout.close();
                    } 
                    catch (FileNotFoundException e) 
                    {
                        // TODO Auto-generated catch block
                        Log.d("ImageCapture", "FileNotFoundException");
                        Log.d("ImageCapture", e.getMessage());
                        filePath = "";
                    } 
                    catch (IOException e) 
                    {
                        // TODO Auto-generated catch block
                        Log.d("ImageCapture", "IOException");
                        Log.d("ImageCapture", e.getMessage());
                        filePath = "";
                    }
    
                    openShareImageDialog(filePath);
                }
            };
    
            mMap.snapshot(callback);
        }
    

    图像捕获完成后,它将触发标准的“共享图像”对话框,以便用户选择他们想要共享的方式:

    public void openShareImageDialog(String filePath) 
    {
    File file = this.getFileStreamPath(filePath);
    
    if(!filePath.equals(""))
    {
        final ContentValues values = new ContentValues(2);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
        final Uri contentUriFile = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    
        final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
        intent.setType("image/jpeg");
        intent.putExtra(android.content.Intent.EXTRA_STREAM, contentUriFile);
        startActivity(Intent.createChooser(intent, "Share Image"));
    }
    else
    {
                //This is a custom class I use to show dialogs...simply replace this with whatever you want to show an error message, Toast, etc.
        DialogUtilities.showOkDialogWithText(this, R.string.shareImageFailed);
    }
    }
    

    文档是here

    【讨论】:

    • 你能举个例子吗!
    • @David - 提供示例。
    • 嗨@DiscDev,这段代码非常有用。但我想要一个解决方案:假设有一个包含地图和一些 UI 组件的活动。见:i57.tinypic.com/iglyef.png 现在我需要一张截图。这个怎么做 ?提前致谢
    • @Vrajesh - 我看不到你的图片,但我认为你不能捕捉地图中没有的 UI 元素......我认为你必须做的是捕获地图图像,然后分别捕获整个屏幕(整个屏幕捕获时地图将是空白的),然后稍后通过一些代码将 2 个图像重新组合在一起。
    • @Disc 开发。谢谢你的答复...!你说的对。我必须做两个单独的图像来截屏。一个用于整个屏幕,第二个仅显示地图。然后合并它们。这里有点混乱..!我怎样才能做到这一点 ?你有这样做的一些想法或参考..?更新图片位置 :: s13.postimg.org/5r99pibx3/test.png
    【解决方案8】:

    以下是通过示例捕获 Google Map V2 屏幕截图的步骤

    第一步打开Android Sdk Manager (Window &gt; Android Sdk Manager)然后Expand Extras现在update/install Google Play Services to Revision 10如果已经installed忽略这一步

    在此处阅读注释https://developers.google.com/maps/documentation/android/releases#august_2013

    第 2 步。 Restart Eclipse

    第 3 步。 import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback;

    步骤 4. 制作方法来捕获/存储地图的屏幕/图像,如下所示

    public void CaptureMapScreen() 
    {
    SnapshotReadyCallback callback = new SnapshotReadyCallback() {
                Bitmap bitmap;
    
                @Override
                public void onSnapshotReady(Bitmap snapshot) {
                    // TODO Auto-generated method stub
                    bitmap = snapshot;
                    try {
                        FileOutputStream out = new FileOutputStream("/mnt/sdcard/"
                            + "MyMapScreen" + System.currentTimeMillis()
                            + ".png");
    
                        // above "/mnt ..... png" => is a storage path (where image will be stored) + name of image you can customize as per your Requirement
    
                        bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
    
            myMap.snapshot(callback);
    
            // myMap is object of GoogleMap +> GoogleMap myMap;
            // which is initialized in onCreate() => 
            // myMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_pass_home_call)).getMap();
    }
    

    第 5 步。 现在在您要捕获图像的位置调用此 CaptureMapScreen() 方法

    在我的情况下,我是 calling this method on Button click in my onCreate(),它工作正常

    喜欢:

    Button btnCap = (Button) findViewById(R.id.btnTakeScreenshot);
        btnCap.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                try {
                    CaptureMapScreen();
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
    
            }
        });
    

    检查文档herehere

    【讨论】:

    • 我知道这是一个很老的帖子,但我有一个类似的问题,想看看你是否可以帮助解决它。我正在像这样初始化 myMap: myMap = ((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();我收到以下错误:txs.io/JBS,这是我拥有的 map_pass_home_call.xml 文件:txs.io/KBS。我不确定我哪里出错了。我总是收到空指针异常。
    【解决方案9】:

    即使是谷歌地图 V2,Eclipse DDMS 也可以捕获屏幕。

    如果您有“root”权限,请尝试调用 /system/bin/screencap 或 /system/bin/screenshot。我从How Eclipse android DDMS implement "screen capture"了解到这一点

    【讨论】:

    • 是的,我知道这一点,但我希望能够在非根设备上以编程方式(即在代码中)截取屏幕截图。这在 Maps API for Android 的第一个版本中是可能的,但不是第二个版本(由于接受的答案中提到的原因)。
    • 是的,这也是我的问题。但是如果谷歌地图V2似乎不可能。 DDMS 使用通过具有必要权限的进程(adb pull)提供的screencap 或screensnap android。但是普通的android应用程序没有权限(我昨天从stackoverflow找到)。希望下个版本的谷歌地图能加强它。
    • 是的,令人沮丧的是他们没有提供 OpenGL 层,但我想这与版权或安全有关。
    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多