可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Final Update
The feature request has been fulfilled by 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. 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.
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:
Has anyone figured out how to take a screenshot of the new Google Maps Android API V2?
Update
I also tried to get the rootView this way:
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.
Update
A feature request has been submitted to 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
回答1:
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.
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
回答2:
Below are the steps to capture screen shot of Google Map V2 with example
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
Read Notes here https://developers.google.com/maps/documentation/android/releases#august_2013
Step 2. Restart Eclipse
Step 3. import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback;
Step 4. Make Method to Capture/Store Screen/image of Map like below
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
in my case i am calling this method on Button click in my onCreate()
which is working fine
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
回答3:
Edit: this answer is no longer valid - the feature request for screenshots on Google Maps Android API V2 has been fulfilled. 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.
回答4:
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);
}
回答5:
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) {
}
});
}
}
回答6:
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);
}
};
回答7:
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
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
回答8:
Eclipse DDMS can capture the screen even it's google map V2.
Try to call /system/bin/screencap or /system/bin/screenshot if you have the "root". I learned that from How Eclipse android DDMS implement "screen capture"