1

I'm asking for suggestions on how you would go about capturing and saving what is currently displayed in an Android application compiled with Phonegap, by pressing a button.

I've done hours and hours of research into possible ways to do this:

  1. Creating a Phonegap plugin that finds the current view, converts it to a bitmap then saves this to the devices SDcard. As seen here.

  2. Uses the HTML5 Canvas tag and converts this and any child elements to a PNG file, using the toDataURL method as seen here.

I'm at a loose end and would really appreciate any suggestions, tutorials or links to anything that may help. There are hundreds of SO posts saying this cannot be done in Android, but I can't believe that considering i've found two links that may be possible.

I have tried the links above, however there are some outstanding issues that prevent me from getting them to work. I was looking for alternatives.

Edit: Below is the plugin code I am using, together with the code from the first link on how to record a screenshot of a view.

package com.company.msgbox;

//imports

@Override
public PluginResult execute(String arg0, final JSONArray arg1, String arg2) {
if ( arg0.equals(SHOW) )
{
this.ctx.runOnUiThread(new Runnable()
{
public void run()
{
// try/catch generated by editor
try {
msg = arg1.getString(MSG_INDEX);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

AlertDialog alertDialog = new AlertDialog.Builder(ctx).create();
alertDialog.setTitle("Title");
alertDialog.setMessage(msg);
alertDialog.show();

//screen shot
View content = findViewById(R.id.rootlayout);
Bitmap bitmap = content.getDrawingCache();
File file = new File("/sdcard/test.png");
try 
{
    file.createNewFile();
    FileOutputStream ostream = new FileOutputStream(file);
    bitmap.compress(CompressFormat.PNG, 100, ostream);
    ostream.close();
} 
catch (Exception e) 
{
    e.printStackTrace();
}


}//end of scope
});
}

return new PluginResult(Status.OK);
}

}

I get a Null Pointer Exception at this line:

View content = findViewById(R.id.rootlayout);

My question would be, does Phonegap create views in Android and if so, how do you select them using the findViewById method?

Community
  • 1
  • 1
jcrowson
  • 4,290
  • 12
  • 54
  • 77
  • 1
    "There are hundreds of SO posts saying this cannot be done in Android, but I can't believe that considering i've found two links that may be possible." -- most of those posts are for people trying to capture screenshots of any application's activities, not just their own. That is not supported. Your approaches will only work for your activities, and they are supported, just not especially well. :-) – CommonsWare Nov 14 '11 at 21:06
  • @LordSnoutimus: `findViewById()` is a method on `Activity`. I don't know the PhoneGap plugin architecture. Possibly `ctx` is your `Activity`. If not, contact the PhoneGap folk to see how you might get access to your `Activity` from your plugin. I would hope that this would be possible. – CommonsWare Nov 15 '11 at 11:44
  • @CommonsWare: If ctx is indeed the Activity, could I still use the findViewById method? – jcrowson Nov 15 '11 at 12:00
  • 1
    @LordSnoutimus: You'd have to cast it to be an `Activity`, if it isn't already an `Activity`. Java is strongly-typed, unlike JavaScript. But then you'd call `ctx.findViewById(R.id.rootlayout)` (if `ctx` is an `Activity`) or `((Activity)ctx).findViewById(R.id.rootlayout)` (if `ctx` is really an `Activity` but is handed to you as a more generic `Context`). If that fails with a `ClassCastException`, then `ctx` is some other type of `Context` than an `Activity`, and you're back to square one. – CommonsWare Nov 15 '11 at 12:30
  • @CommonsWare: Excellent! that seems to have worked, the error is no longer showing in Eclipse, thank you very much. However, it is now returned a Null Pointer Exception at Bitmap bitmap = content.getDrawingCache();. I take it this means that the view is empty? – jcrowson Nov 15 '11 at 12:56
  • 1
    @LordSnoutimus: Beats me -- I've never accessed the drawing cache. I suggest that you open up a fresh question on this topic. – CommonsWare Nov 15 '11 at 13:00
  • @CommonsWare: I think i've found the issue with the null pointer, however you mentioned that Phonegap creates a WebView when it compiles? is there anyway I can reference that in the findViewById method? – jcrowson Nov 15 '11 at 17:27
  • 1
    @LordSnoutimus: Try `R.id.appView`, based on https://github.com/callback/callback-android/blob/master/framework/res/layout/main.xml – CommonsWare Nov 15 '11 at 17:38
  • @CommonsWare: Thank you for your reply, really appreciate the help. Unfortunately my application has not generated that WebView in the main.xml layout. I've added it but it still does not reference it. – jcrowson Nov 15 '11 at 17:56

2 Answers2

1

What issues are you having with #1? That should work, in theory. Another more complex option would be creating a custom ViewGroup, putting the web view for phonegap inside it, and overriding the drawing methods to produce images that can be saved. That conceptually the same thing as #1, but a whole lot more work.

Kevin Galligan
  • 16,159
  • 5
  • 42
  • 62
  • Hello Kevin, thanks for your reply. Well, I've created a Phonegap plugin to display an alert as a test which works, the problem comes when trying to find the root view of the main Phonegap activity using FindByViewId. Does phonegap create web views natively? – jcrowson Nov 14 '11 at 20:08
  • 1
    @LordSnoutimus: Not sure what you mean by "natively". PhoneGap has an activity with a `WebView` in it. You can see the Java source for it in your PhoneGap project, IIRC. – CommonsWare Nov 14 '11 at 21:04
  • @CommonsWare: I'll update my original post to include some code and the errors i'm getting. Thanks. – jcrowson Nov 15 '11 at 09:32
  • @Kevin Galligan: Please see the updated code in my original post. – jcrowson Nov 15 '11 at 10:27
1

This post might help :http://uihacker.blogspot.com/2011/01/android-phonegap-scale-webview-to-fit.html This post hints that the webview of the whole application can get through appView attribute of your Activity object. For example in my code:

public class SampleActivity extends DroidGap implements OnTouchListener{
   public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.loadUrl("file:///android_asset/www/index.html");
        this.appView.setOnTouchListener((OnTouchListener)this);
   //   this.appView is the biggest view that wrap the whole android application 
   }

  ...implement other methods...
}