读取驱动器中的sqlite db并将其写入本地db-Android
我正在开发一个应用程序,需要将sqlite数据库备份到GoogleDrive(我完成了这项工作)。现在,我想将该数据库恢复到我的应用程序中,并在运行时从SD卡加载它 我正在使用GitHub上的android demo/RetrieveContentsActivity从Google Drive读取数据库内容,并使用以下代码将其写回数据库 ListView-McClickListener读取驱动器中的sqlite db并将其写入本地db-Android,android,sqlite,google-drive-api,google-drive-android-api,Android,Sqlite,Google Drive Api,Google Drive Android Api,我正在开发一个应用程序,需要将sqlite数据库备份到GoogleDrive(我完成了这项工作)。现在,我想将该数据库恢复到我的应用程序中,并在运行时从SD卡加载它 我正在使用GitHub上的android demo/RetrieveContentsActivity从Google Drive读取数据库内容,并使用以下代码将其写回数据库 ListView-McClickListener Drive.DriveApi .getFi
Drive.DriveApi
.getFile(api,
mResultsAdapter.getItem(position).getDriveId())
.openContents(api, DriveFile.MODE_READ_ONLY, null)
.setResultCallback(contentsOpenedCallback);
ResultCallBack
final private ResultCallback<ContentsResult> contentsOpenedCallback = new ResultCallback<ContentsResult>() {
@Override
public void onResult(ContentsResult result) {
if (!result.getStatus().isSuccess()) {
return;
}
if (GetFileFromDrive(result)) {
Toast.makeText(getApplicationContext(), "File restored",
Toast.LENGTH_LONG).show();
}
}
};
问题是它删除了sqlite中已经存在的数据,并完全清空了sqlite。我曾试图在谷歌上找到这个问题,但没有一个能帮到我
这家伙--正试图做同样的事情,但他说他用open
取代了openContents
。我试过了,但是它给出了一个错误,未定义DriveFile类型的open方法(GoogleApiClient,int,null)
任何形式的帮助都将不胜感激。我已经被困在这个问题上将近一个星期了,我感到很恼火 没有人会运行和调试你的代码。以下是几点帮助:
1/假设你的应用程序上传了你的DB文件(GooDrive不在乎它是DB还是其他任何东西——只是一个字节流)。记录/保存它的DriveId-它应该看起来像“DriveId:CAES…”
2/检查GooDrive(drive.google.com)中的文件是否具有您期望的大小。您还可以使用第三方SQLite web app检查驱动器中DB文件的状态(确保创建/上载的文件具有正确的MIME类型)
3/在Android应用程序中,将保存的DriveId传递给此方法:
private static GoogleApiClient mGAC;
...
/*******************************************************************
* get file contents
* @param dId file driveId
*/
static void read(DriveId dId) {
byte[] buf = null;
if (mGAC != null && mGAC.isConnected() && dId != null) {
DriveFile df = Drive.DriveApi.getFile(mGAC, dId);
df.open(mGAC, DriveFile.MODE_READ_ONLY, null)
.setResultCallback(new ResultCallback<DriveContentsResult>() {
@Override
public void onResult(DriveContentsResult rslt) {
if ((rslt != null) && rslt.getStatus().isSuccess()) {
DriveContents cont = rslt.getDriveContents();
byte[] buf = UT.is2Bytes(cont.getInputStream());
int size = buf.length;
cont.discard(mGAC); // or cont.commit(); they are equiv if READONLY
}
}
});
}
}
私有静态GoogleapClient mGAC;
...
/*******************************************************************
*获取文件内容
*@param dId file driveId
*/
静态无效读取(DriveId dId){
字节[]buf=null;
if(mGAC!=null&&mGAC.isConnected()&&dId!=null){
DriveFile df=Drive.DriveApi.getFile(mGAC,dId);
df.open(mGAC,DriveFile.MODE\u只读,空)
.setResultCallback(新的ResultCallback(){
@凌驾
公共void onResult(DriveContentsResult rslt){
if((rslt!=null)&&rslt.getStatus().issucess()){
DriveContents cont=rslt.getDriveContents();
字节[]buf=UT.is2Bytes(cont.getInputStream());
int size=buf.length;
cont.discard(mGAC);//或cont.commit();如果为只读,则它们是等价的
}
}
});
}
}
4/检查下载的字节缓冲区的大小/状态/内容。您也可以将其写回DB文件
这些步骤将使您更接近于解决错误
祝你好运假设你下载了DB来驱动。
现在,我们如何在你的应用程序中获得它:
此示例包含带有GUI的FragmentActivity。但是,您可以轻松地将其调整为静默下载
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_SUCCESS:
// Called after a file is saved to Drive.
if (resultCode == RESULT_OK) {
finish();
} else {
finish();
}
break;
case REQUEST_CODE_OPENER:
if (resultCode == RESULT_OK){
//Toast.makeText(this, R.string.pref_data_drive_import_success, Toast.LENGTH_LONG).show();
DriveId driveId = data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
DriveFile file = driveId.asDriveFile();
processDriveFile(file);
} else {
Toast.makeText(this, R.string.pref_data_drive_import_error, Toast.LENGTH_LONG).show();
finish();
}
break;
}
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()){
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
finish();
} catch (IntentSender.SendIntentException e){
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
@Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
//.setMimeType(new String[] { "application/x-sqlite3" })
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.w(TAG, "Unable to send intent", e);
}
}
@Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
现在,我们检查所选文件是否是我们的数据库,并重新使用它
private void processDriveFile(DriveFile file){
Log.i(TAG, "processDriveFile started");
file.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null)
.setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
@Override
public void onResult(@NonNull DriveApi.DriveContentsResult driveContentsResult) {
if (!driveContentsResult.getStatus().isSuccess()){
Log.i(TAG, "Failed to create new contents.");
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
return;
}
Log.i(TAG, "New contents created.");
DriveContents driveContents = driveContentsResult.getDriveContents();
InputStream inputStream = driveContents.getInputStream();
String dbDir = context.getDatabasePath("oldDbName.db").getParent();
String newFileName = "newDbName.db";
Log.i(TAG, "dbDir = " + dbDir);
// Deletion previous versions of new DB file from drive
File file = new File(dbDir + "/" + newFileName);
if (file.exists()){
Log.i(TAG, "newDbName.db EXISTS");
if (file.delete()){
Log.i(TAG, "newDbName.db DELETING old file....");
} else {
Log.i(TAG, "newDbName.db Something went wrong with deleting");
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
try {
OutputStream output = new FileOutputStream(file);
try {
try {
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} finally {
output.close();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
// Check if file really match our DB
// Connection it to custom SqliteOpenHelper
ImportDBManager importDBManager = new ImportDBManager(context);
importDBManager.open();
// We have some System table in DB with 1 row in it for this goal
// So, we check if there is data in it
List<DataModelSystem> dataModelSystem = importDBManager.getSystemSingleRow(1);
importDBManager.close();
if (dataModelSystem.size() > 0){
Log.i(TAG, "DB MATCH!");
String mainDbName = context.getDatabasePath(DatabaseHelper.DB_NAME).toString();
String newDbName = context.getDatabasePath(ImportDatabaseHelper.DB_NAME).toString();
File oldDbFile = new File(mainDbName);
File newDbFile = new File(newDbName);
if (newDbFile.exists()){
Log.i(TAG, "newDbName.db EXISTS");
if (oldDbFile.delete()){
Log.i(TAG, "newDbName.db DELETING old file....");
try {
copyFile(newDbFile, oldDbFile);
Log.i(TAG, "success! New database");
Toast.makeText(getApplicationContext(), "Import OK!!!!1", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
Log.i(TAG, "fail! old database will remain");
e.printStackTrace();
finish();
}
} else {
Log.i(TAG, "newDbName.db Something went wrong with deleting");
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
} else {
Log.i(TAG, "db not Match!");
Toast.makeText(getApplicationContext(),"Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
});
finish();
}
// Replacing old file
private static void copyFile(File src, File dst) throws IOException {
Log.i(TAG, "src = " + src.getAbsolutePath());
Log.i(TAG, "dst = " + dst.getAbsolutePath());
FileInputStream var2 = new FileInputStream(src);
FileOutputStream var3 = new FileOutputStream(dst);
byte[] var4 = new byte[1024];
int var5;
while((var5 = var2.read(var4)) > 0) {
var3.write(var4, 0, var5);
}
var2.close();
var3.close();
}
private void processDriveFile(驱动文件文件){
i(标记“processDriveFile已启动”);
file.open(mGoogleApiClient,DriveFile.MODE\u只读,null)
.setResultCallback(新的ResultCallback(){
@凌驾
public void onResult(@NonNull DriveApi.DriveContentsResult DriveContentsResult){
如果(!driveContentsResult.getStatus().isSuccess()){
Log.i(标记“未能创建新内容”);
Toast.makeText(getApplicationContext(),“导入数据库错误”,Toast.LENGTH_LONG.show();
完成();
返回;
}
Log.i(标记“创建的新内容”);
DriveContents-DriveContents=driveContentsResult.getDriveContents();
InputStream InputStream=driveContents.getInputStream();
字符串dbDir=context.getDatabasePath(“oldDbName.db”).getParent();
字符串newFileName=“newDbName.db”;
Log.i(标签,“dbDir=”+dbDir);
//从驱动器中删除新DB文件的早期版本
File File=新文件(dbDir+“/”+newFileName);
if(file.exists()){
Log.i(标记“newDbName.db存在”);
if(file.delete()){
Log.i(标记“newDbName.db删除旧文件…”);
}否则{
i(标记“newDbName.db删除时出错”);
Toast.makeText(getApplicationContext(),“导入数据库错误”,Toast.LENGTH_LONG.show();
完成();
}
}
试一试{
OutputStream output=新文件OutputStream(文件);
试一试{
试一试{
字节[]缓冲区=新字节[4*1024];//或其他缓冲区大小
int-read;
而((读取=输入流。读取(缓冲区))!=-1){
输出。写入(缓冲区,0,读取);
}
output.flush();
}最后{
output.close();
}
}捕获(例外e){
e、 printStackTrace();
Toast.makeText(getApplicationContext(),“导入数据库错误”,Toast.LENGTH_LONG.show();
完成();
}
}catch(filenotfounde异常){
e、 printStackTrace();
Toast.makeText(getApplicationContext(),“导入数据库错误”,Toast.LENGTH_LONG.show();
完成();
}最后{
试一试{
inputStream.close();
}捕获(IO)
private void processDriveFile(DriveFile file){
Log.i(TAG, "processDriveFile started");
file.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null)
.setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
@Override
public void onResult(@NonNull DriveApi.DriveContentsResult driveContentsResult) {
if (!driveContentsResult.getStatus().isSuccess()){
Log.i(TAG, "Failed to create new contents.");
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
return;
}
Log.i(TAG, "New contents created.");
DriveContents driveContents = driveContentsResult.getDriveContents();
InputStream inputStream = driveContents.getInputStream();
String dbDir = context.getDatabasePath("oldDbName.db").getParent();
String newFileName = "newDbName.db";
Log.i(TAG, "dbDir = " + dbDir);
// Deletion previous versions of new DB file from drive
File file = new File(dbDir + "/" + newFileName);
if (file.exists()){
Log.i(TAG, "newDbName.db EXISTS");
if (file.delete()){
Log.i(TAG, "newDbName.db DELETING old file....");
} else {
Log.i(TAG, "newDbName.db Something went wrong with deleting");
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
try {
OutputStream output = new FileOutputStream(file);
try {
try {
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} finally {
output.close();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
// Check if file really match our DB
// Connection it to custom SqliteOpenHelper
ImportDBManager importDBManager = new ImportDBManager(context);
importDBManager.open();
// We have some System table in DB with 1 row in it for this goal
// So, we check if there is data in it
List<DataModelSystem> dataModelSystem = importDBManager.getSystemSingleRow(1);
importDBManager.close();
if (dataModelSystem.size() > 0){
Log.i(TAG, "DB MATCH!");
String mainDbName = context.getDatabasePath(DatabaseHelper.DB_NAME).toString();
String newDbName = context.getDatabasePath(ImportDatabaseHelper.DB_NAME).toString();
File oldDbFile = new File(mainDbName);
File newDbFile = new File(newDbName);
if (newDbFile.exists()){
Log.i(TAG, "newDbName.db EXISTS");
if (oldDbFile.delete()){
Log.i(TAG, "newDbName.db DELETING old file....");
try {
copyFile(newDbFile, oldDbFile);
Log.i(TAG, "success! New database");
Toast.makeText(getApplicationContext(), "Import OK!!!!1", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
Log.i(TAG, "fail! old database will remain");
e.printStackTrace();
finish();
}
} else {
Log.i(TAG, "newDbName.db Something went wrong with deleting");
Toast.makeText(getApplicationContext(), "Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
} else {
Log.i(TAG, "db not Match!");
Toast.makeText(getApplicationContext(),"Import DB error", Toast.LENGTH_LONG).show();
finish();
}
}
});
finish();
}
// Replacing old file
private static void copyFile(File src, File dst) throws IOException {
Log.i(TAG, "src = " + src.getAbsolutePath());
Log.i(TAG, "dst = " + dst.getAbsolutePath());
FileInputStream var2 = new FileInputStream(src);
FileOutputStream var3 = new FileOutputStream(dst);
byte[] var4 = new byte[1024];
int var5;
while((var5 = var2.read(var4)) > 0) {
var3.write(var4, 0, var5);
}
var2.close();
var3.close();
}