1
votes

I am using the below code for downloading an already uploaded sqlite db file from google drive to the data/data/packagename/databases folder, but when the method completes, I am seeing a db corruption warning message logged in logcat and also all the data on the device for the app is overwritten and shows up blank, upon opening the app.

mfile = Drive.DriveApi.getFile(mGoogleApiClient, mResultsAdapter.getItem(0).getDriveId());
                    mfile.openContents(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null).setResultCallback(contentsOpenedCallback);

--mfile is an instance of DriveFile

final private ResultCallback<ContentsResult> contentsOpenedCallback = new ResultCallback<ContentsResult>()
{
    @Override
    public void onResult(ContentsResult result)
    {
        if (!result.getStatus().isSuccess())
        {
            FileUtils.appendLog(getApplicationContext(), Tag + "-onResult", "Error opening file");
            return;
        }

        try
        {
            if (GetFileFromDrive(result))
            {
                        //FileUtils.Restore(getApplicationContext());
                        SharedPrefHelper.EditSharedPreference(getApplicationContext(), Constants.PREFS_DO_RESTORE, false);
            }

        }
        catch (FileNotFoundException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
};

private boolean GetFileFromDrive(ContentsResult result)
{
    Contents contents = result.getContents();
    //InputStreamReader rda = new InputStreamReader(contents.getInputStream());
    BufferedReader reader = new BufferedReader(new InputStreamReader(contents.getInputStream()));
    FileOutputStream outStream;
    String currLine;
    boolean restoreSuccess = false;

    File sourceDbFile = BackupDBBeforeDeletion();

    if(sourceDbFile != null)
        sourceDbFile.delete();

    try
    {
        outStream = new FileOutputStream(getApplicationContext().getDatabasePath(Constants.DB_NAME));
        while ((currLine = reader.readLine()) != null)
        {
            outStream.write(currLine.getBytes());
        }

        outStream.flush();

        reader.close();
        outStream.close();
        restoreSuccess = true;
    }
    catch (FileNotFoundException e)
    {
        // TODO: Log exception
    }
    catch (IOException e)
    {
        // TODO: Log Exception
    }

    return restoreSuccess;
}

When the method GetFileFromDrive completes, a db corruption shows up on LogCat and all the existing data on the app's datanase file (sqlite db) is gone.

Please help, as I have verified that the drive uploaded sqlite db file is correct and well formed, by downloading the same and opening it up in Sqlite Browser. It's the download from drive that is not working.

2
Try writing the file to a local file first (not the DB file path) and make sure that's not corrupt. Then copying the file into place. Maybe SQLite is corrupting it - it's trying to be read/write while you're writing the file. Just a thought. - Randy
Yes, that is part of my problem, as when I tried doing exactly what you have suggested, the db file formed on that other path, but the db was blank, even though I know there is data in there on the drive version. - omkar.ghaisas

2 Answers

1
votes

This solution is not working for me. The sqlite files I got from google drive is more longer than I saved in google drive. That, probably, happen because you are using a Buffereader class and the method readline that reads data in char. In my project and experience this solutions does not work, I got a corrupted sqlite db. So... I save sqlite db in google drive in byte so **I read from google drive the same sqlite db in byte, using BufferedInputStream. This works perfectly for me:

DriveContents contents = result.getDriveContents();
                BufferedInputStream bis = new BufferedInputStream(contents.getInputStream());
                byte[] buffer = new byte[1024];
                int bytesread = 0;
                FileOutputStream outStream;

                /*if(currentDB != null)
                    currentDB.delete();*/

                try
                {
                    outStream = new FileOutputStream(currentDB);
                    while( (bytesread = bis.read(buffer)) != -1)
                    {
                        outStream.write(buffer,0,bytesread);
                    }

                    outStream.flush();
                    bis.close();
                    outStream.close();
                }
                catch (FileNotFoundException e)
                {
                    Log.i(TAG,e.getMessage());
                }
                catch (IOException e)
                {
                    Log.i(TAG,e.getMessage());
                }
                finally {
                    Toast.makeText(getActivity().getBaseContext(),"Data from Google Drive restored successfully." , Toast.LENGTH_LONG).show();
                }
                contents.discard(mGoogleApiClient);
0
votes

I was able to finally fix my own issue, by replacing the file.openContents with file.open and setting a result call back with DriveContents result back rather than ContentsResult.

Also, used the DriveContents to set an InputStream on the same (initially opened in Mode_Read_Only in open method) and then writing it out into a physical ".db" file on the data base path location.

Now, the database doesn't get corrupted and restores data successfully.