我试图将 sqlite 数据库备份到谷歌驱动器并在需要时恢复它。我收到以下错误。
这是我的 GdriveActivity 代码:
import static adapter.DBAdapter.DATABASE_NAME;
public class GdriveActivity extends AppCompatActivity {
private static final String TAG = "Google Drive Activity";
public static final int REQUEST_CODE_SIGN_IN = 0;
public static final int REQUEST_CODE_OPENING = 1;
private static final int REQUEST_CODE_OPEN_DOCUMENT = 2;
//variable for decide if i need to do a backup or a restore.
//True stands for backup, False for restore
private boolean isBackup = true;
private GdriveActivity activity;
private DriveServiceHelper mDriveServiceHelper;
private final Context context;
private String mOpenFileId;
public GdriveActivity() {
context = null;
}
public GdriveActivity(Context ctx) {
this.context = ctx;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
activity = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_backup_restore);
findViewById(R.id.backupdrive).setOnClickListener(View->createFile());
findViewById(R.id.restoredrive).setOnClickListener(View->query());
// setupUI(db);
// db.closeDB();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
switch (requestCode) {
case REQUEST_CODE_SIGN_IN:
if (resultCode == Activity.RESULT_OK && resultData != null) {
handleSignInResult(resultData);
}
break;
}
super.onActivityResult(requestCode, resultCode, resultData);
}
private void createFile() {
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(activity);
Log.e("account details: ", account.toString());
if (account == null) {
requestSignIn();
mOpenFileId= mQuery("pregnancy.db");
} else {
mOpenFileId= mQuery("pregnancy.db");
}
if(!TextUtils.isEmpty(mOpenFileId)){
mDriveServiceHelper.deleteFolderFile(mOpenFileId).addOnSuccessListener(v-> Log.d(TAG, "removed file ")).
addOnFailureListener(v-> Log.d(TAG, "File was not removed: "));
mDriveServiceHelper.saveFile();
}
else {
Drive mDriveService = null;
final String inFileName = activity.getDatabasePath(DATABASE_NAME).toString();
java.io.File dbFile = null;
try {
dbFile = new java.io.File(inFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// Transfer bytes from the inputfile to the outputfile
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file
FileOutputStream fos = new FileOutputStream(dbFile);
fos.write(bitmapdata);
fos.flush();
fos.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
java.io.File finalDbFile = dbFile;
File metadata = new File()
.setParents(Collections.singletonList("root"))
.setMimeType("application/db")
.setName("pregnancy.db");
FileContent fileContent = new FileContent("application/db", finalDbFile);
File googleFile = null;
try {
googleFile = mDriveService.files().create(metadata,fileContent).execute();
} catch (IOException e) {
e.printStackTrace();
}
if (googleFile == null) {
try {
throw new IOException("Null result when requesting file creation.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void query() {
final String inFileName = activity.getDatabasePath(DATABASE_NAME).toString();
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(activity);
if (account == null) {
requestSignIn();
mOpenFileId= mQuery("pregnancy.db");
} else {
mOpenFileId= mQuery("pregnancy.db");
}
if(!TextUtils.isEmpty(mOpenFileId)){
context.deleteDatabase(inFileName);
downloadFile(mOpenFileId);
Toast.makeText(this, "File restored", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(this, "No database file to restore", Toast.LENGTH_LONG).show();
}
}
private void requestSignIn() {
Log.d(TAG, "Requesting sign-in");
GoogleSignInOptions signInOptions =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(new Scope(DriveScopes.DRIVE_FILE))
.build();
GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions);
// The result of the sign-in Intent is handled in onActivityResult.
startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN);
}
private void handleSignInResult(Intent result) {
GoogleSignIn.getSignedInAccountFromIntent(result)
.addOnSuccessListener(googleAccount -> {
Log.d(TAG, "Signed in as " + googleAccount.getEmail());
// Use the authenticated account to sign in to the Drive service.
GoogleAccountCredential credential =
GoogleAccountCredential.usingOAuth2(
this, Collections.singleton(DriveScopes.DRIVE_FILE));
credential.setSelectedAccount(googleAccount.getAccount());
Drive googleDriveService =
new Drive.Builder(
AndroidHttp.newCompatibleTransport(),
new GsonFactory(),
credential)
.setApplicationName("Drive API Migration")
.build();
// The DriveServiceHelper encapsulates all REST API and SAF functionality.
// Its instantiation is required before handling any onClick actions.
mDriveServiceHelper = new DriveServiceHelper(googleDriveService, activity);
})
.addOnFailureListener(exception -> Log.e(TAG, "Unable to sign in.", exception));
}
public String mQuery(String name) {
if (mDriveServiceHelper != null) {
Log.d(TAG, "Querying for files.");
mDriveServiceHelper.queryFiles()
.addOnSuccessListener(fileList -> {
for (File file : fileList.getFiles()) {
if (file.getName().equals(name))
mOpenFileId = file.getId();
break;
}
});
}
return mOpenFileId;
}
public void downloadFile(String fileid) {
final String inFileName = activity.getDatabasePath(DATABASE_NAME).toString();
java.io.File file = new java.io.File(inFileName, "pregnancy");
mDriveServiceHelper.downloadFile(file, fileid)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "Downloaded the file");
long file_size = file.length() / 1024;
Log.i(TAG, "file Size :" + file_size);
Log.i(TAG, "file Path :" + file.getAbsolutePath());
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i(TAG, "Failed to Download the file, Exception :" + e.getMessage());
}
});
}
}
这是我的 DriveServiceHelper.java 代码
public class DriveServiceHelper {
private final Executor mExecutor = Executors.newSingleThreadExecutor();
private final Drive mDriveService;
private GdriveActivity activity;
public DriveServiceHelper(Drive driveService, GdriveActivity activity) {
mDriveService = driveService;
this.activity=activity;
}
/**
* Creates a text file in the user's My Drive folder and returns its file ID.
*/
public Task<String> saveFile() {
final String inFileName = activity.getDatabasePath(DATABASE_NAME).toString();
java.io.File dbFile = null;
try {
dbFile = new java.io.File(inFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// Transfer bytes from the inputfile to the outputfile
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file
FileOutputStream fos = new FileOutputStream(dbFile);
fos.write(bitmapdata);
fos.flush();
fos.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
java.io.File finalDbFile = dbFile;
return Tasks.call(mExecutor, () -> {
File metadata = new File()
.setParents(Collections.singletonList("root"))
.setMimeType("application/db")
.setName("pregnancy.db");
FileContent fileContent = new FileContent("application/db", finalDbFile);
File googleFile = mDriveService.files().create(metadata,fileContent).execute();
if (googleFile == null) {
throw new IOException("Null result when requesting file creation.");
}
return googleFile.getId();
});
}
public Task<Void> downloadFile(java.io.File targetFile, String fileId) {
return Tasks.call(mExecutor, () -> {
// Retrieve the metadata as a File object.
OutputStream outputStream = new FileOutputStream(targetFile);
mDriveService.files().get(fileId).executeMediaAndDownloadTo(outputStream);
return null;
});
}
/**
* Opens the file identified by {@code fileId} and returns a {@link Pair} of its name and
* contents.
*/
public Task<Pair<String, String>> readFile(String fileId) {
return Tasks.call(mExecutor, () -> {
// Retrieve the metadata as a File object.
File metadata = mDriveService.files().get(fileId).execute();
String name = metadata.getName();
// Stream the file contents to a String.
try (InputStream is = mDriveService.files().get(fileId).executeMediaAsInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
String contents = stringBuilder.toString();
return Pair.create(name, contents);
}
});
}
/**
* Updates the file identified by {@code fileId} with the given {@code name} and {@code
* content}.
*/
public Task<Void> saveFile1(String fileId, String name, String content) {
return Tasks.call(mExecutor, () -> {
// Create a File containing any metadata changes.
File metadata = new File().setName(name);
// Convert content to an AbstractInputStreamContent instance.
ByteArrayContent contentStream = ByteArrayContent.fromString("text/plain", content);
// Update the metadata and contents.
mDriveService.files().update(fileId, metadata, contentStream).execute();
return null;
});
}
/**
* Returns a {@link FileList} containing all the visible files in the user's My Drive.
*
* <p>The returned list will only contain files visible to this app, i.e. those which were
* created by this app. To perform operations on files not created by the app, the project must
* request Drive Full Scope in the <a href="https://play.google.com/apps/publish">Google
* Developer's Console</a> and be submitted to Google for verification.</p>
*/
public Task<FileList> queryFiles() {
return Tasks.call(mExecutor, () ->
mDriveService.files().list().setSpaces("drive").execute());
}
/**
* Returns an {@link Intent} for opening the Storage Access Framework file picker.
*/
public Intent createFilePickerIntent() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
return intent;
}
/**
* Opens the file at the {@code uri} returned by a Storage Access Framework {@link Intent}
* created by {@link #createFilePickerIntent()} using the given {@code contentResolver}.
*/
public Task<Pair<String, String>> openFileUsingStorageAccessFramework(
ContentResolver contentResolver, Uri uri) {
return Tasks.call(mExecutor, () -> {
// Retrieve the document's display name from its metadata.
String name;
try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
name = cursor.getString(nameIndex);
} else {
throw new IOException("Empty cursor returned for file.");
}
}
// Read the document's contents as a String.
String content;
try (InputStream is = contentResolver.openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
content = stringBuilder.toString();
}
return Pair.create(name, content);
});
}
public Task<Void> deleteFolderFile(String fileId) {
return Tasks.call(mExecutor, () -> {
// Retrieve the metadata as a File object.
if (fileId != null) {
mDriveService.files().delete(fileId).execute();
}
return null;
});
}
}
当我执行我得到这个错误:
java.lang.NullPointerException:尝试在 drivebackuprestore.GdriveActivity 的空对象引用上调用虚拟方法 'com.google.api.services.drive.Drive$Files com.google.api.services.drive.Drive.files()' .createFile(GdriveActivity.java:150) at drivebackuprestore.GdriveActivity.lambda$onCreate$0$GdriveActivity(GdriveActivity.java:75) at drivebackuprestore.-$$Lambda$GdriveActivity$pvZu_qquzakaJJsWZrA8BS6rMRs.onClick(Unknown Source:2) at android.view .View.performClick(View.java:7862) at android.widget.TextView.performClick(TextView.java:15004) at android.view.View.performClickInternal(View.java:7831) at android.view.View.access$3600 (View.java:879) 在 android.view.View$PerformClick.run(View.java:29359) 在 android.os.Handler.handleCallback(Handler.java:883) 在 android.os.Handler.dispatchMessage(Handler. java:100) 在 android.os.Looper。在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller 的 java.lang.reflect.Method.invoke(Native Method) 的 android.app.ActivityThread.main(ActivityThread.java:8167) 的循环(Looper.java:237)。在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100) 运行(RuntimeInit.java:496)