I have a file with about 1700 markers that I am trying to load onto a gmap v2. On my galaxy nexus running 4.2.2 it loads no problem, but some folks with 4.0.x and 4.1.x are not having the same results. They get the map, but no points or the app crashes after about 30 seconds. I am loading a local file...
Here is my method:
public void BuildMap() {
FileInputStream fXmlFile;
markerInfo = new HashMap<Marker, MapMarkers>();
try {
fXmlFile = new FileInputStream(
"/storage/emulated/0/snoteldata/kml/snotelwithlabels.kml");
XmlDom xml = new XmlDom(fXmlFile);
List<XmlDom> locations = xml.tags("Placemark");
String Name, Description, Lat, Lon;
markerInfo = new HashMap<Marker, MapMarkers>();
for (XmlDom location : locations) {
MapMarkers marks = new MapMarkers();
Name = location.tag("name").text();
Description = location.tag("description").text();
Lat = location.tag("latitude").text();
Lon = location.tag("longitude").text();
la = Float.parseFloat(Lat);
lo = Float.parseFloat(Lon);
marks.setTitle(Name);
marks.setDesc(Description);
Marker m = map.addMarker(new MarkerOptions()
.position(new LatLng(la, lo))
.title(marks.getTitle())
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.snotel_marker)));
markerInfo.put(m, marks);
map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
MapMarkers markInfo = markerInfo.get(marker);
Intent i = new Intent(MainActivity.this,
MarkerInformation.class);
i.putExtra("name", markInfo.getTitle()).putExtra(
"description", markInfo.getDesc());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
});
}
} catch (SAXException e) {
// TODO Auto-generated catch block
Log.e("SAXException", e.getMessage());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
Log.e("FileNotFoundException", e.getMessage());
}
}
I have tried putting this in a AsyncTask, but get the Not on Main Thread error each time... so I am not sure how to run it in the background to keep it loading for folks until the parsing has completely happened.
Why does this show for my Gnex and a Nexus 7 tablet, but not for 4.0.x etc??? How can I figure out where the issue is on others devices?
There are two problems with your code.
First, you are reading file on the main thread. Do this part in background, e.g. using AsyncTask which returns a list of MarkerOptions. Iterate over returned list in onPostExecute to add those to the map.
Second issue might be the amount of Markers. There are a few ways to handle this. Check this answer: Add markers dynamically on Google Maps v2 for Android
Do this way
public void BuildMap() {
final Handler mHandler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
FileInputStream fXmlFile;
markerInfo = new HashMap<Marker, MapMarkers>();
try {
fXmlFile = new FileInputStream("/storage/emulated/0/snoteldata/kml/snotelwithlabels.kml");
XmlDom xml = new XmlDom(fXmlFile);
List<XmlDom> locations = xml.tags("Placemark");
String Name, Description, Lat, Lon;
markerInfo = new HashMap<Marker, MapMarkers>();
for (XmlDom location : locations) {
final MapMarkers marks = new MapMarkers();
Name = location.tag("name").text();
Description = location.tag("description").text();
Lat = location.tag("latitude").text();
Lon = location.tag("longitude").text();
la = Float.parseFloat(Lat);
lo = Float.parseFloat(Lon);
marks.setTitle(Name);
marks.setDesc(Description);
mHandler.post(new Runnable() {
#Override
public void run() {
Marker m = map.addMarker(new MarkerOptions().position(new LatLng(la, lo)).title(marks.getTitle())
.icon(BitmapDescriptorFactory.fromResource(R.drawable.snotel_marker)));
markerInfo.put(m, marks);
map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
MapMarkers markInfo = markerInfo.get(marker);
Intent i = new Intent(MainActivity.this, MarkerInformation.class);
i.putExtra("name", markInfo.getTitle()).putExtra("description", markInfo.getDesc());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
});
}
});
}
} catch (SAXException e) {
// TODO Auto-generated catch block
Log.e("SAXException", e.getMessage());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
Log.e("FileNotFoundException", e.getMessage());
}
}
}).start();
}
Related
StreetViewPanoramaFragment streetViewFragment = (StreetViewPanoramaFragment) getFragmentManager().findFragmentById(R.id.g_map_street);
streetViewFragment.getStreetViewPanoramaAsync(this);
#Override
public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
streetView = streetViewPanorama;
streetViewPanorama.setPosition(new LatLng(Latitude, Longtitude));
}
I have a value of Heading which returns angle.
https://maps.googleapis.com/maps/api/streetview?size=800x800&location=%s,%s&heading=%s
Using it , I can get Streetview Image properly but not working in StreetViewPanoramaFragment.
Finally , after lots of R&D I found this solution.. and its works for me.
#Override
public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
streetViewPanorama.setPosition(new LatLng(Latitude, Longtitude));
try {
//Change angle of street view
final int DURATION = 1000;
StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera.Builder()
.zoom(streetViewPanorama.getPanoramaCamera().zoom)
.tilt(streetViewPanorama.getPanoramaCamera().tilt)
.bearing(streetViewPanorama.getPanoramaCamera().bearing + angle) // angle value by Maps Api
.build();
streetViewPanorama.animateTo(camera, DURATION);
} catch (Exception e) {
e.printStackTrace();
}
}
I am trying to snapshot the Google Map image AFTER I set the map to the bounds of the Polyline. I have used separate code samples found on StackExchange to do both the moveToBounds() and Snapshot which work fine individually, but when run in sequence the Snapshot is of the map image BEFORE the map was updated. I assume I need to insert a OnCameraChangeListener but I cannot make it work. Do I need to somehow nest Callbacks? Please advise.
public void mapCapture() {
moveToBounds(gpsTrackingPolyline);
mMap.snapshot(new GoogleMap.SnapshotReadyCallback() {
public void onSnapshotReady(Bitmap bitmap) {
// Write image to disk
try {
File bmpFile = new File(getApplicationContext().getExternalFilesDir(null), DEFAULT_BMP_FILENAME);
FileOutputStream out = new FileOutputStream(bmpFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void moveToBounds(Polyline p)
{
LatLngBounds.Builder builder = new LatLngBounds.Builder();
List<LatLng> arr = p.getPoints();
for(int i = 0; i < arr.size();i++){
builder.include(arr.get(i));
}
LatLngBounds bounds = builder.build();
int padding = 40; // offset from edges of the map in pixels
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
mMap.animateCamera(cu);
}
Don't know if you have found solution or if you still need it. But still here it goes. Yes you need a callback which will let you know when map has finished animation. Do something like this:
mMap.animateCamera(cu, new GoogleMap.CancelableCallback() {
#Override
public void onFinish() {
//your code related to snapshot
mMap.snapshot(new GoogleMap.SnapshotReadyCallback() {
public void onSnapshotReady(Bitmap bitmap) {
// Write image to disk
//rest of your code
});
}
#Override
public void onCancel() {
// TODO Auto-generated method stub
}
});
I would like to retrieve some positions (Latitude and Longitude) which are contained in a TXT file, and show them on my Map.
I know how to show my actual position, through the GPS of my tablet. I can update my position following this example.
public class MainActivity extends FragmentActivity implements LocationListener
{
private LocationManager locationmanager;
private GoogleMap googlemap;
private Marker marker;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeMap();
}
private void initializeMap()
{
if(googlemap==null)
{
googlemap=((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();
marker=googlemap.addMarker(new MarkerOptions().title("Vous etes la").position(new LatLng(0,0)));
if(googlemap==null)
{
Toast.makeText(getApplicationContext(), "Failed to create map",Toast.LENGTH_SHORT).show();
}
}
}
protected void onResume()
{
super.onResume();
locationmanager=(LocationManager)this.getSystemService(LOCATION_SERVICE);
if(locationmanager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
abonnementGps();
}
initializeMap();
}
public void onPause()
{
super.onPause();
desabonnementGps();
}
public void abonnementGps()
{
locationmanager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 19, this);
}
public void desabonnementGps()
{
locationmanager.removeUpdates(this);
}
#Override
public void onLocationChanged(Location location)
{
final StringBuilder msg=new StringBuilder("Lati :");
msg.append(location.getLatitude());
msg.append("\nLogi :");
msg.append(location.getLongitude());
Toast.makeText(this, msg.toString(),Toast.LENGTH_SHORT).show();
final LatLng latilongi=new LatLng(location.getLatitude(), location.getLongitude());
googlemap.moveCamera(CameraUpdateFactory.newLatLngZoom(latilongi,19));
marker.setPosition(latilongi);
}
#Override
public void onProviderDisabled(String provider)
{
if("gps".equals(provider))
{
desabonnementGps();
}
}
#Override
public void onProviderEnabled(String provider) {
if("gps".equals(provider))
{
abonnementGps();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
I also know how to read a text file :
// METHODE POUR LIRE UN FICHIER TEXTE
public String readText(String filepath) throws Exception
{
String text="";
try
{
InputStream inputs=new FileInputStream(filepath);
InputStreamReader inputsreader=new InputStreamReader(inputs);
BufferedReader buffer=new BufferedReader(inputsreader);
String line;
while((line=buffer.readLine())!=null)
{
System.out.println(line);
text+=line+"\n";
}
buffer.close();
}
catch(FileNotFoundException e)
{
System.out.println(e);
}
return text;
}
For each line, I'd like to update my position, through the onLocationChanged(). But when I tried to call the method onLocationChanged() from readText(), my application was crashing.
NB : I changed the method public void onLocationChanged() to public void onLocationChanged(LatLng latlong) and the method public String readText(String str) to public LatLng readText(String str).
I think my ideas are not clear and I mix everything I've just learned.
Can someone guide me please ?
Thank you in advance for your help.
Best regards,
Tofuw
you dont call onLocationChanged manually, it gets called when your location changes so if you want to write to a file when a new location comes in you should do it in onLocationChanged
also you cannot change the method onLocationChanged to onLocationChanged(LatLng latlong) that is not how it works and you will not get the callbacks to the method. you need to keep it as is, you cant just go changing API methods like that
You need to add a new function to do the location change using the lat/lng from your text file:
public void MyLocationChanged(string slatlng )
{
string[] coord = slatlng.Split(',');
final LatLng latilongi=new LatLng( Double.parseDouble( coord[ 0 ] ), Double.parseDouble( coord[ 1 ] ) );
googlemap.moveCamera(CameraUpdateFactory.newLatLngZoom(latilongi,19));
marker.setPosition(latilongi);
}
Then just call this function from your text reading function, passing it the read line (assuming it is in the form: latitude,longitude.
I succeeded in solve my problem thanks to #Andrew-OpenGeoCode and #tyczj !
Here is my simple example, for those who are searching to retrieve and show positions from a files containing coordinates.
public class MainActivity extends FragmentActivity
{
// GoogleMaps
private GoogleMap googlemap;
private Marker marker;
private TCPClient tcpclient;
private Button bNavigation;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Connect to server - See innerClass connectTask below
try{ initializeMap(); }
catch(Exception e){ e.printStackTrace(); }
bNavigation=(Button)findViewById(R.id.bNavigation);
bNavigation.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String filepath="/storage/sdcard0/TrameGPS/tramegps.txt";
String texttosend="";
// Reading the TXT
try
{
texttosend=readText(filepath);
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
});
}
public void initializeMap()
{
if(googlemap==null)
{
LatLng startposition=new LatLng(48.853,2.35);
googlemap=((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();
marker=googlemap.addMarker(new MarkerOptions().title("You are here !").position(startposition));
googlemap.moveCamera(CameraUpdateFactory.newLatLngZoom(startposition, 19));
if(googlemap==null)
Toast.makeText(getApplicationContext(), "Failed to load map !", Toast.LENGTH_SHORT).show();
}
}
// READING A TEXT FILE WHICH CONTAINS COORDINATES
public String readText(String filepath) throws Exception
{
String text="";
try
{
InputStream inputs=new FileInputStream(filepath);
InputStreamReader inputsreader=new InputStreamReader(inputs);
BufferedReader buffer=new BufferedReader(inputsreader);
String line;
while((line=buffer.readLine())!=null)
{
String[]coordinates=line.split(",");
if(coordinates[0].equals("$GPRMC"))
{
String coord=coordinates[3]+","+coordinates[5];
changePosition(Double.parseDouble(coordinates[3]),Double.parseDouble(coordinates[5]));
}
}
buffer.close();
}
catch(FileNotFoundException e)
{
System.out.println(e);
}
return text;
}
public void changePosition(Double a,Double b)
{
final StringBuilder notification=new StringBuilder("Latitude : ");
notification.append(a);
notification.append("\nLongitude : ");
notification.append(b);
Toast.makeText(this, notification, Toast.LENGTH_SHORT).show();
// UPDATE THE COORDINATES !!!! UPDATE THE COORDINATES !!!
final LatLng latilongi=new LatLng(a, b);
googlemap.moveCamera(CameraUpdateFactory.newLatLngZoom(latilongi, 19));
marker.setPosition(latilongi);
}
}
I hope it will help you.
Once again, thanks to tyczj and Andrew-OpenGeoCode !
Best regards,
Tofuw
i have to solve this with the new "snapshot maker" which is implemented in the google maps release august but i dont' know how to do this.
Can somone give me a simple example?
here is my code:
public class MainActivity extends Activity {
static LatLng HAMBURG = new LatLng(47.524749, 21.632745);
GoogleMap map;
File dbFile;
private File imageFile;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PolylineOptions line = new PolylineOptions();
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
.getMap();
/*
* Adatbázis
*/
try {
dbFile = getDatabasePath("/mnt/sdcard/Download/TeleSensors.db");
} catch (Exception e) {
}
SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase(
dbFile.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY);
Cursor curTAB = myDataBase.rawQuery("SELECT * FROM GPS_Values;", null);
Integer count = 0;
while (curTAB.moveToNext()) {
String s_latitude = curTAB.getString(1);
String s_longitude = curTAB.getString(2);
count++;
double latitude = Double.parseDouble(s_latitude);
double longitude = Double.parseDouble(s_longitude);
line.add(new LatLng(latitude, longitude));
Log.i("Coordinates",
s_latitude.toString() + " --- " + s_longitude.toString());
}
curTAB.close();
myDataBase.close();
// adatbázis vége
map.addPolyline(line);
// map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// map.setMapType(GoogleMap.MAP_TYPE_NONE);
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
// map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
// Move the camera instantly to hamburg with a zoom of 15.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));
// Zoom in, animating the camera.
map.animateCamera(CameraUpdateFactory.zoomTo(15), 2000, null);
}
}
Thank you very mouch!
You have to call the Google maps snapshot method in a button listener because if you should take it too early, it will give you error bitmap width has to be larger than 0 or something like this.
Here is the code
private void button_listener() {
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SnapshotReadyCallback callback = new SnapshotReadyCallback() {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
bitmap = snapshot;
try {
FileOutputStream out = new FileOutputStream("/mnt/sdcard/Download/TeleSensors.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
};
map.snapshot(callback);
}
});
}
This one is better, it waits for your Map to be fully rendered, before taking the snapshot.
It was updated on 31-Oct-2013.
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
public void onMapLoaded() {
mMap.snapshot(new GoogleMap.SnapshotReadyCallback() {
public void onSnapshotReady(Bitmap bitmap) {
// Write image to disk
FileOutputStream out = new FileOutputStream("/mnt/sdcard/map.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
}
});
}
});
Extracted from http://googlegeodevelopers.blogspot.sg/2013/10/ghost-markers-in-your-neighborhood-new.html
Try for Kotlin Android like this when click on button to take google map snapshot:
val snapshotReadyCallback : GoogleMap.SnapshotReadyCallback = GoogleMap.SnapshotReadyCallback { selectedScreenShot ->
ivMapPreview.setImageBitmap(selectedScreenShot);
}
val onMapLoadedCallback : GoogleMap.OnMapLoadedCallback = GoogleMap.OnMapLoadedCallback {
mMap!!.snapshot(snapshotReadyCallback)
}
mMap!!.setOnMapLoadedCallback(onMapLoadedCallback)
Be successful.
I' ve tried the accepted answer but it didn't work then tried another approach that worked for me.
private void CaptureScreen() {
if(initMap()){
SnapshotReadyCallback callback = new SnapshotReadyCallback() {
Bitmap bitmap=null;
#Override
public void onSnapshotReady(Bitmap snapshot) {
// TODO Auto-generated method stub
bitmap = snapshot;
try {
saveImage(bitmap);
Toast.makeText(getApplicationContext(), "Image 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.PNG, 40, bytes);
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
}
};
mMap.snapshot(callback);
}
else{
Toast.makeText(this, "Map is not Initialized yet", Toast.LENGTH_LONG).show();
return ;
}
}
https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/GoogleMap#snapshot(com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback, android.graphics.Bitmap)
public final void snapshot (GoogleMap.SnapshotReadyCallback callback)
Takes a snapshot of the map. You can use snapshots within your application when an interactive map would be difficult, or impossible,
to use. For example, images produced with the snapshot() method can be
used to display a thumbnail of the map in your app, or a snapshot in
the notification center.
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
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
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
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
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.
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);
}
};
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"