2

I am trying to copy my pre-populated database to a writable directory (I am thinking SD card), this needs to basically copy my whole assets folder within my phonegap android app.

I have done days of research and due to my very limited knowledge of java, I cannot seem to create this java plugin to do the simple copy and then from there I am not entirly certain how to actually call this plugin from my HTML/ Javascript.

Below is the current java plugin I have been working on using sample code found on the net, can someone please help guide me in the right direction.

JAVA PLUGIN:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.json.JSONArray;

import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;

    public class DataBaseHelper extends Plugin 
    {
    @Override
    public PluginResult execute(String arg0, JSONArray arg1, String arg2) 
    {
        try
        {
            String pName = this.getClass().getPackage().getName();
            this.copy("Databases.db","/data/data/"+pName+"/app_database/");
            this.copy("0000000000000001.db","/data/data/"+pName+"/app_database/file__0/");
            }
                catch (IOException e)
            {
            e.printStackTrace();
        }
        // TODO Auto-generated method stub
        String value = "OK";
        return new PluginResult(PluginResult.Status.OK, value);
    }

    //Copy Paste this function in the class where you used above part
     void copy(String file, String folder) throws IOException 
     {
         File CheckDirectory;
         CheckDirectory = new File(folder);
         if (!CheckDirectory.exists())
         { 
            CheckDirectory.mkdir();
         }

         InputStream in = this.ctx.getAssets().open(file);
         OutputStream out = new FileOutputStream(folder+file);

        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len; while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
        in.close(); out.close();            
    }
}

JAVASCRIPT PLUGIN CALL:

<script type="text/javascript" charset="utf-8" src="taxapp.js"></script>
function onDeviceReady() // CALLING THIS ON BODY LOAD
{
    dataCapture();
    window.plugins.DataBaseHelper.copy("",function(data)
    {
        alert("plugin called part 1");
        // nothing to do here
    },
    function()
    {
        alert("plugin called part 2");
        console.warn("Error calling plugin");
    }); 
}

Any help would be much appreciated as I need to get this fixed today. Thanks in advance.

SingleWave Games
  • 2,618
  • 9
  • 36
  • 52

1 Answers1

2

Try using this.ctx instead of this and getApplicationContext(), the Plugin isn't a Context in itself, but it holds the 'real' context in its ctx field.

Add a .js file with the content below:

var DataBaseHelper = function() {};

DataBaseHelper.prototype.copy = function(params, success, fail) 
{
    return PhoneGap.exec(function(args) 
    {
        success(args);
    }, 
    function(args) 
    {
        fail(args);
    }, 'DataBaseHelper', 'copy', [params]);
};



PhoneGap.addConstructor(function() 
{
    PhoneGap.addPlugin('DataBaseHelper', new DataBaseHelper());
    PluginManager.addService("DataBaseHelper","full.package.name.DataBaseHelper");
});

Then call the plugin anytime after PhoneGap is initialized:

window.plugins.DataBaseHelper.copy("",function(data)
{
    // nothing to do here
},
function()
{
    console.warn("Error calling plugin");
});

Also, after phonegap-1.0.0, you need a plugins.xml file in your res/xml directory, where you need to add:

<plugin name="DataBaseHelper" value="full.package.name.DataBaseHelper"/>

The best way to know if phonegap has initialized is by calling this method in javascript:

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() 
{
    //call your plugin here
}
Demonick
  • 2,116
  • 3
  • 30
  • 40
  • Thanks, this seems to fix the that error, however I am not entirly sure how to call and execute this plugin within my HTML page. I add the javascript plugin section within the HTML page, and then need to call the plugin. How can this be done? – SingleWave Games Mar 21 '12 at 12:01
  • I have implemented your changed however it seems my database is still not copied across. I have edited my above code so you can see how I call the plugin. Thanks – SingleWave Games Mar 21 '12 at 12:37
  • As a side note I can manually push my database files within the simulator using DDMS and this works fine. – SingleWave Games Mar 21 '12 at 12:38
  • Is your execute method in the java Plugin called? Does it throw any errors? Maybe you need to add write permission to the manifest. – Demonick Mar 21 '12 at 12:40
  • I believe it is called. I have edited my above code adding 2 lines within PluginResult. How can I check to see if any errors occur (The app loaded and installed error free ont he simulator and device). As for the permissions I already have WRITE_EXTERNAL_STORAGE. your help is much appreciated, feel like im so close! – SingleWave Games Mar 21 '12 at 12:47
  • 1 other think to note, my 2 database files sit within my assets folder, so this basically contains ('www folder with all html js etc', '0000000000000001.db' and 'Databases.db'). – SingleWave Games Mar 21 '12 at 12:52
  • I edited my post about onDeviceReady function, also add a try ... catch block and some log message to your copy method to see if it gets executed at all. – Demonick Mar 21 '12 at 12:56
  • You are right about the plugin not loading have added loads of Log.d("PLUGIN WORKED", "it actually worked"); throughout my java. I for some reason cannot get the onDeviceReady to trigger, that is the reason that i was calling it from onLoad. I have noticed that the html javascript is not even being called (added alerts within both sections). Any other ideas? – SingleWave Games Mar 21 '12 at 13:26
  • See the last lines of my answer, maybe try adding it in this way, instead of calling onDeviceReady in the onLoad method. – Demonick Mar 21 '12 at 13:32
  • That is exactly what i had used before, it seems to work fine on iOS and blackberry but not with Android, am I missing something? – SingleWave Games Mar 21 '12 at 13:38
  • I'm using it on Android, make sure you add phonegap to your page first, then your plugin .js file. – Demonick Mar 21 '12 at 13:52
  • I worked out why onDeviceReady was not working, I was using the iOS .js file ... durgh. However, it seems the plugin is not being called, it is called from the index.html page, but then I am not getting any messages or anything within Eclipses LogCat. Thanks – SingleWave Games Mar 21 '12 at 14:27
  • Thanks the above code works, however not for my scenario. This is due to my database being more than 1mb and running a OS older than 2.3.3. Therefore, I need to either upgrade my firmware or truncate the database. Thanks for the help. – SingleWave Games Mar 26 '12 at 18:11