简体   繁体   English

GoogleMap截屏 Android API V2

[英]Capture screen shot of GoogleMap Android API V2

Final Update最后更新

The feature request has been fulfilled by Google. Google 已满足功能请求。 Please see this answer below.在下面查看此答案。

Original Question原问题

Using the old version of the Google Maps Android API, I was able to capture a screenshot of the google map to share via social media.使用旧版谷歌地图 Android API,我能够截取谷歌 map 的屏幕截图并通过社交媒体分享。 I used the following code to capture the screenshot and save the image to a file and it worked great:我使用以下代码捕获屏幕截图并将图像保存到文件中,效果很好:

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;
}

However, the new GoogleMap object used by V2 of the api does not have a "getRootView()" method like MapView does.但是,api 的 V2 使用的新 GoogleMap object 没有像 MapView 那样的“getRootView()”方法。

I tried to do this:我试图这样做:

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

    View v1 = mapFragment.getView();

But the screenshot that I get does not have any map content and looks like this:但是我得到的屏幕截图没有任何 map 内容,看起来像这样:空白地图截图

Has anyone figured out how to take a screenshot of the new Google Maps Android API V2?有没有人想出如何截取新的谷歌地图 Android API V2 的截图?

Update更新

I also tried to get the rootView this way:我也尝试通过这种方式获取 rootView:

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

This results in a screenshot that includes the action bar at the top of the screen, but the map is still blank like the screenshot I attached.这会生成屏幕顶部包含操作栏的屏幕截图,但 map 仍然像我附上的屏幕截图一样空白。

Update更新

A feature request has been submitted to Google.已向 Google 提交功能请求。 Please go star the feature request if this is something you want google to add in the future:Add screenshot ability to Google Maps API V2请 go 星标功能请求,如果这是你希望谷歌在未来添加的东西:Add screenshot ability to Google Maps API V2

Update - Google has added a snapshot method**!: 更新 - 谷歌添加了快照方法**!:

The feature request for a method to take a screen shot of the Android Google Map API V2 OpenGL layer has been fulfilled. 已完成针对Android Google Map API V2 OpenGL图层的屏幕截图的方法的功能请求。

To take a screenshot, simply implement the following interface: 要截取屏幕截图,只需实现以下界面:

public abstract void onSnapshotReady (Bitmap snapshot)

and call: 并致电:

public final void snapshot (GoogleMap.SnapshotReadyCallback callback)

Example that takes a screenshot, then presents the standard "Image Sharing" options: 截取屏幕截图的示例,然后显示标准的“图像共享”选项:

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);
    }

Once the image is finished being captured, it will trigger the standard "Share Image" dialog so the user can pick how they'd like to share it: 一旦图像完成捕获,它将触发标准的“共享图像”对话框,以便用户可以选择他们想要共享的方式:

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);
}
}

Documentation is here 文档在这里

Below are the steps to capture screen shot of Google Map V2 with example 以下是捕获Google Map V2屏幕截图的步骤

Step 1. open Android Sdk Manager (Window > Android Sdk Manager) then Expand Extras now update/install Google Play Services to Revision 10 ignore this step if already installed 步骤1.打开Android Sdk Manager (Window > Android Sdk Manager)然后Expand Extras现在update/install Google Play Services to Revision 10忽略此步骤(如果已经installed

Read Notes here https://developers.google.com/maps/documentation/android/releases#august_2013 在此处阅读说明https://developers.google.com/maps/documentation/android/releases#august_2013

Step 2. Restart Eclipse 步骤2. Restart Eclipse

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

Step 4. Make Method to Capture/Store Screen/image of Map like below 步骤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();
}

Step 5. Now call this CaptureMapScreen() method where you want to capture the image 步骤5.现在调用此CaptureMapScreen()方法来捕获图像

in my case i am calling this method on Button click in my onCreate() which is working fine 在我的情况下,我calling this method on Button click in my onCreate() ,这是正常的

like: 喜欢:

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();
            }

        }
    });

Check Doc here and here 在这里这里检查Doc

Edit : this answer is no longer valid - the feature request for screenshots on Google Maps Android API V2 has been fulfilled. 编辑 :此答案不再有效 - 已完成Google Maps Android API V2上的屏幕截图功能请求。 See this answer for an example . 请参阅此答案以获取示例

Original Accepted Answer 原始接受的答案

Since the new Android API v2 Maps are displayed using OpenGL, there are no possibilities to create a screenshot. 由于使用OpenGL显示新的Android API v2 Maps,因此无法创建屏幕截图。

I capctured Map screenshot.It will be helpful 我制作了地图截图。它会很有帮助

  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() method for taking screenshot of map 用于截取地图截图的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);
}

My output is below 我的输出如下 在此输入图像描述

Since the top voted answer doesnt work with polylines and other overlays on top of the map fragment (What I was looking for), I want to share this solution. 由于最高投票的答案不适用于地图片段顶部的折线和其他叠加(我在寻找什么),我想分享这个解决方案。

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);
        }
private GoogleMap mMap;
SupportMapFragment mapFragment;
LinearLayout linearLayout;
String jobId="1";

File file; 文件文件;

@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) {

        }
    });

}

} }

I hope this would help to capture the screenshot of your map 我希望这有助于捕获地图的屏幕截图

Method call: 方法调用:

gmap.setOnMapLoadedCallback(mapLoadedCallback);

Method declaration: 方法声明:

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);
        }
};

Use mapcalback for get screenshot of map使用 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);

Eclipse DDMS can capture the screen even it's google map V2. Eclipse DDMS可以捕获屏幕,即使它是谷歌地图V2。

Try to call /system/bin/screencap or /system/bin/screenshot if you have the "root". 如果你有“root”,请尝试调用/ system / bin / screencap或/ system / bin / screenshot。 I learned that from How Eclipse android DDMS implement "screen capture" 我从Eclipse android DDMS如何实现“屏幕截图”中了解到

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM