3

I've tried both methods to save a MapView as a bitmap which I've found here and none seem to work for me. The first option,

Bitmap bitMap = mMapView.getDrawingCache();             
mMapView.setDrawingCacheEnabled(true);
bitMap = mMapView.getDrawingCache(true);

and the second,

Canvas offscreencanvas = new Canvas();
Bitmap bmap = Bitmap.createBitmap(mMapView.getWidth(), mMapView.getHeight(),
                    Bitmap.Config.ARGB_8888);
bmap.copy(Config.ARGB_4444, true);
offscreencanvas.setBitmap(bmap);
offscreencanvas.drawBitmap(bmap, 0, 0, null);

both result in a bitmap object with width and height of -1 so when I then try and use the bitmap as a texture, it doesn't show. I call the bitmap saving code in a button click, after the mapview has rendered but it still gives the same result.

Has anyone managed to do this?

John J Smith
  • 11,435
  • 9
  • 53
  • 72

2 Answers2

2

I encountered similar problems attempting to make use of the drawing cache. Some items I found that helped me:

  • Ensure you copy the drawing cache immediately. Android can and will recycle the bitmap that the cache is drawn too. I have had Android destroy the bitmap cache while I was drawing to a view with it.
  • For some reason, destroying the cache before retrieving it gave me more consistent results.

Here is the working code I am using:

// Disable caching, destroy the cache, and force a rebuild
imageView.setWillNotCacheDrawing(false);
imageView.destroyDrawingCache();
imageView.buildDrawingCache();

// Copy the drawing cache before the system recycles it
Bitmap cachedImage = Bitmap.createBitmap(imageView.getDrawingCache());

Also note that I am using an ImageView, but I would expect the code path to be the same for MapView.

Finally in the code sample that you posted, you are creating a bitmap the size of the map view. You copy this bitmap and then throw the result away. Then you set your canvas to be backed by this bitmap, and then you try to draw the bitmap to the bitmap. (Yes I typed that correctly.) Try something like this, in place of your canvas code

Bitmap mapCache = /* Get this using the previous code */
Bitmap bmap = Bitmap.createBitmap(mMapView.getWidth(), mMapView.getHeight(),
                        Bitmap.Config.ARGB_8888);
Canvas offscreencanvas = new Canvas(bmap);
offscreencanvas.drawBitmap(mapCache, 0, 0, null);
Sam
  • 2,579
  • 17
  • 27
  • Thanks for the response Sam. Although the mapView has the same method calls which you use in the imageView, this does not work for the mapView. At all stages, the mWidth and mHeight of the bitmap created are -1 which is why, I think, the bitmap is not useable. – John J Smith Jun 03 '11 at 21:25
  • Since you say the width and height of the image are -1 I am going to assume you got that value from the debugger. Are you sure you're looking at the right values? Some variables are used for layout and will read -1 if they are uninitialized. – Sam Jun 04 '11 at 06:38
1

i didn't work much with MapView, i'll assume that it exteneding the View class, thus, make sure to specify the layout before you build the cach, and you should do it as follow :

This is how i do it, you can change it or try something different if you preffer :

View v = new View(context)
{   public void onMeasure(int w, int h)
    {  setMeasuredDimension(width, height);//the desired width and height
    }}; //important
v.setDrawingCacheEnabled(true); //important
v.measure(width,height); //important the desired width and height
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); //important
v.setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
v.setLayoutParams(new LayoutParams(width,height)); //important
v.buildDrawingCache(true); //important
Bitmap b = v.getDrawingCache(true);
v.buildDrawingCache(false);

Hope this helps, Best regards.

Ben
  • 91
  • 1
  • 7
  • could you please make your code snippets readable the next time? – WarrenFaith Jun 02 '11 at 23:25
  • 1
    if this is productive code, you should think about some code style and some rules for variable naming :) I like the android style: http://source.android.com/source/code-style.html – WarrenFaith Jun 03 '11 at 00:59
  • well to be totaly honest i write everything in one line, that how i understand it the best, i split it here and added some comments to make it easier to understand, i'm sure that if i took some code snipet out of my code you wouldn't be able to understand anything,i write 3000 lines of code in about 500lines maybe even less, so i definitly don't have any code style, i had very nice code style till i figured that it's much eaiser for me to create a style that talks the best to me. my code looks like blocks.. – Ben Jun 03 '11 at 01:25
  • you should try it you might find it easier to read too, no need to scroll you have all the code one after the other, like reading a book just the same. – Ben Jun 03 '11 at 01:25
  • Than you are the contrast of my style. I need spaces after a comma or a bracket... Two things: 1. can you provide a sample activity/class where I can see your "block style"? (a http://pastebin.com/ link is ok) 2. What does your colleagues say about your code? – WarrenFaith Jun 03 '11 at 01:49
  • For the second question, not many people can write and read like that, many thinks it's a mess, but once you get used to it, any code become easier to read, for the first : – Ben Jun 03 '11 at 02:32
  • edv=new Button(con);edv.setBackgroundResource(R.drawable.edv);edv.setLayoutParams(new LayoutParams(50,50)); edv.setOnClickListener(new OnClickListener(){public void onClick(View v) {zo.setEnabled(false);zi.setEnabled(false);edv.setEnabled(false);wvi.setEnabled(true);main.removeView(ps.ww);main.addView(psv); ps.ww.clearView();ps.ww=null;}}); wvi=new Button(con);wvi.setBackgroundResource(R.drawable.wvi);wvi.setLayoutParams(new LayoutParams(50,50)); – Ben Jun 03 '11 at 02:33
  • Usually i handle each object on one line, this keeps some order in the code, also if there are several tasks connected to each other, i put them on the same line too, there is a relation between the code in the same line, i don't throw it all togather, i'm actually using the lines as dividers. – Ben Jun 03 '11 at 02:38
  • 5
    hm... I have to admit that your code is the best argument for me to stay with my style. Its barely readable for me, it will be a lot more messy when I use descriptive naming for variables and even a new OnClickListener definition in one line is, sorry but no offense, simply evil. Your code is for me not maintainable... I guess you work with 2560x1600 to get your line of code without scrollbars... – WarrenFaith Jun 03 '11 at 08:32
  • Thanks Ben. This code works fine but I've gone for Sam's answer as its a bit more concise and easy to use in my particular case. – John J Smith Jun 04 '11 at 20:00
  • For WarrenFaith, well i told you it's not easy, but i also said that once you get use to it, any code become easy to read, and yes my screen resolution is very high, but i don't mind for scrolling right if needed, i had an issue with it not to long ago, i didn't like the scrolling right, somehow i've changed, for maintaining, well it depends, each line handle one task kind of, so when you get use to this idea, it makes things simpler, i didn't expect you to change your style, i don't even think that it's good way to go, it's just my way, and you got to see it, not many saw my style... – Ben Jun 04 '11 at 20:52