简体   繁体   English

使用GDAA(适用于Android的Google Drive Api)创建/编辑/检索数据库文件

[英]Create / Edit / Retrieve DB file with GDAA (Google Drive Api for Android)

skilled friends. 熟练的朋友。

Could you someone help me with my problem, please? 有人可以帮我解决我的问题吗? I'm trying to use GDAA (Google Drive API for Android = https://developers.google.com/drive/android/appfolder ) for backup and restore my DB file. 我正在尝试使用GDAA(适用于Android的Google Drive API = https://developers.google.com/drive/android/appfolder )来备份和还原我的数据库文件。 Not REST API. 不是REST API。 I tried use their demo classes from here: https://github.com/googledrive/android-demos/ , but no positive result. 我尝试从这里使用他们的演示类: https : //github.com/googledrive/android-demos/ ,但是没有积极的结果。

I suceed with authentication and with save my DB file into App Folder in Google Drive, but I can not edit or retrieve this file. 我通过身份验证并将数据库文件保存到Google云端硬盘中的“应用程序文件夹”中,但无法编辑或检索此文件。 I only still create new and new files. 我仍然只创建新文件。 Could you help me, please? 请问你能帮帮我吗?

I call this Edit activity: 我称之为“编辑”活动:

public class EditContentsActivity extends BaseDemoActivity {

private static final String TAG = "EditContentsActivity";

@Override
public void onConnected(Bundle connectionHint) {
    super.onConnected(connectionHint);

    final ResultCallback<DriveIdResult> idCallback = new ResultCallback<DriveIdResult>() {
        @Override
        public void onResult(DriveIdResult result) {
            if (!result.getStatus().isSuccess()) {
                Intent intent = new Intent(getBaseContext(), CreateFileInAppFolderActivity.class);
                startActivity(intent);
                return;
            }

            DriveFile file = Drive.DriveApi.getFile(getGoogleApiClient(), result.getDriveId());
            new EditContentsAsyncTask(EditContentsActivity.this).execute(file);
        }
    };
    Drive.DriveApi.fetchDriveId(getGoogleApiClient(), EXISTING_FILE_ID)
            .setResultCallback(idCallback);
}

public class EditContentsAsyncTask extends ApiClientAsyncTask<DriveFile, Void, Boolean> {

    public EditContentsAsyncTask(Context context) {
        super(context);
    }

    @Override
    protected Boolean doInBackgroundConnected(DriveFile... args) {
        DriveFile file = args[0];
        try {
            DriveContentsResult driveContentsResult = file.open(
                    getGoogleApiClient(), DriveFile.MODE_WRITE_ONLY, null).await();
            if (!driveContentsResult.getStatus().isSuccess()) {
                return false;
            }
            DriveContents driveContents = driveContentsResult.getDriveContents();
            OutputStream outputStream = driveContents.getOutputStream();

            String dbpath = "/data/" + "com.myapp" + "/databases/" + DatabaseHelper.DB_NAME;
            FileInputStream fis = new FileInputStream(Environment.getDataDirectory() + dbpath);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
            }

            com.google.android.gms.common.api.Status status =
                    driveContents.commit(getGoogleApiClient(), null).await();

            outputStream.flush();
            outputStream.close();
            fis.close();

            return status.getStatus().isSuccess();
        } catch (IOException e) {
            Log.e(TAG, "IOException while appending to the output stream", e);
        }
        return false;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        if (!result) {
            showMessage("Error while editing contents");
            return;
        }
        showMessage("Successfully edited contents");
    }
}

If I get "!result.getStatus().isSuccess()" I want to call Create Activity: 如果得到“!result.getStatus()。isSuccess()”,我想调用“创建活动”:

public class CreateFileInAppFolderActivity extends BaseDemoActivity {

@Override
public void onConnected(Bundle connectionHint) {
    super.onConnected(connectionHint);
    // create new contents resource
    Drive.DriveApi.newDriveContents(getGoogleApiClient()).setResultCallback(driveContentsCallback);
}

final private ResultCallback<DriveContentsResult> driveContentsCallback =
        new ResultCallback<DriveContentsResult>() {
            @Override
            public void onResult(DriveContentsResult result) {
                if (!result.getStatus().isSuccess()) {
                    showMessage("Error while trying to create new file contents");
                    return;
                }

                String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db");
                MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                        .setTitle(EXISTING_FILE_ID)
                        .setMimeType(mimeType)
                        .build();
                OutputStream os  = result.getDriveContents().getOutputStream();
               try {
                    String dbpath = "/data/" + "com.myapp" + "/databases/" + DatabaseHelper.DB_NAME;
                    FileInputStream fis = new FileInputStream(Environment.getDataDirectory() + dbpath);
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = fis.read(buffer)) > 0) {
                        os.write(buffer, 0, length);
                    }
                   Drive.DriveApi.getAppFolder(getGoogleApiClient())
                           .createFile(getGoogleApiClient(), changeSet, result.getDriveContents())
                           .setResultCallback(fileCallback);

                   os.flush();
                   os.close();
                   fis.close();

                   throw new IOException("");
                } catch (IOException e) {
                    Log.e("IOExceptions=", e.toString());
                   Drive.DriveApi.getAppFolder(getGoogleApiClient()).delete(getGoogleApiClient());
                }

            }
        };

final private ResultCallback<DriveFileResult> fileCallback = new
        ResultCallback<DriveFileResult>() {
            @Override
            public void onResult(DriveFileResult result) {
                if (!result.getStatus().isSuccess()) {
                    showMessage("Error while trying to create the file");
                    return;
                }
                showMessage("Created a file in App Folder: "
                        + result.getDriveFile().getDriveId());
            }
        };

All extend this Base Demo Activity: 所有这些都扩展了此基本演示活动:

public abstract class BaseDemoActivity extends Activity implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {

private static final String TAG = "BaseDriveActivity";

/**
 * DriveId of an existing folder to be used as a parent folder in
 * folder operations samples.
 */
public static final String EXISTING_FOLDER_ID = "0B2EEtIjPUdX6MERsWlYxN3J6RU0";

/**
 * DriveId of an existing file to be used in file operation samples..
 */
public static final String EXISTING_FILE_ID = "0ByfSjdPVs9MZTHBmMVdSeWxaNTg";

/**
 * Extra for account name.
 */
protected static final String EXTRA_ACCOUNT_NAME = "account_name";

/**
 * Request code for auto Google Play Services error resolution.
 */
protected static final int REQUEST_CODE_RESOLUTION = 1;

/**
 * Next available request code.
 */
protected static final int NEXT_AVAILABLE_REQUEST_CODE = 2;

/**
 * Google API client.
 */
private GoogleApiClient mGoogleApiClient;

/**
 * Called when activity gets visible. A connection to Drive services need to
 * be initiated as soon as the activity is visible. Registers
 * {@code ConnectionCallbacks} and {@code OnConnectionFailedListener} on the
 * activities itself.
 */
@Override
protected void onResume() {
    super.onResume();
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Drive.API)
                .addScope(Drive.SCOPE_FILE)
                .addScope(Drive.SCOPE_APPFOLDER) // required for App Folder sample
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }
    mGoogleApiClient.connect();
}

/**
 * Handles resolution callbacks.
 */
@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_RESOLUTION && resultCode == RESULT_OK) {
        mGoogleApiClient.connect();
    }
}

/**
 * Called when activity gets invisible. Connection to Drive service needs to
 * be disconnected as soon as an activity is invisible.
 */
@Override
protected void onPause() {
    if (mGoogleApiClient != null) {
        mGoogleApiClient.disconnect();
    }
    super.onPause();
}

/**
 * Called when {@code mGoogleApiClient} is connected.
 */
@Override
public void onConnected(Bundle connectionHint) {
    Log.i(TAG, "GoogleApiClient connected");
}

/**
 * Called when {@code mGoogleApiClient} is disconnected.
 */
@Override
public void onConnectionSuspended(int cause) {
    Log.i(TAG, "GoogleApiClient connection suspended");
}

/**
 * Called when {@code mGoogleApiClient} is trying to connect but failed.
 * Handle {@code result.getResolution()} if there is a resolution is
 * available.
 */
@Override
public void onConnectionFailed(ConnectionResult result) {
    Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
    if (!result.hasResolution()) {
        // show the localized error dialog.
        GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
        return;
    }
    try {
        result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
    } catch (SendIntentException e) {
        Log.e(TAG, "Exception while starting resolution activity", e);
    }
}

/**
 * Shows a toast message.
 */
public void showMessage(String message) {
    Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}

/**
 * Getter for the {@code GoogleApiClient}.
 */
public GoogleApiClient getGoogleApiClient() {
  return mGoogleApiClient;
}

Retrieve Activity: 检索活动:

public class RetrieveContentsActivity extends BaseDemoActivity {

private static final String TAG = "RetrieveContentsActivity";

@Override
public void onConnected(Bundle connectionHint) {
    super.onConnected(connectionHint);
    Drive.DriveApi.fetchDriveId(getGoogleApiClient(), EXISTING_FILE_ID)
            .setResultCallback(idCallback);
}

final private ResultCallback<DriveIdResult> idCallback = new ResultCallback<DriveIdResult>() {
    @Override
    public void onResult(DriveIdResult result) {
        new RetrieveDriveFileContentsAsyncTask(
                RetrieveContentsActivity.this).execute(result.getDriveId());
    }
};

final private class RetrieveDriveFileContentsAsyncTask
        extends ApiClientAsyncTask<DriveId, Boolean, String> {

    public RetrieveDriveFileContentsAsyncTask(Context context) {
        super(context);
    }

    @Override
    protected String doInBackgroundConnected(DriveId... params) {
        String contents = null;
        DriveFile file = Drive.DriveApi.getFile(getGoogleApiClient(), params[0]);
        DriveContentsResult driveContentsResult =
                file.open(getGoogleApiClient(), DriveFile.MODE_READ_ONLY, null).await();
        if (!driveContentsResult.getStatus().isSuccess()) {
            return null;
        }
        DriveContents driveContents = driveContentsResult.getDriveContents();
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(driveContents.getInputStream()));
        StringBuilder builder = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
            contents = builder.toString();
        } catch (IOException e) {
            Log.e(TAG, "IOException while reading from the stream", e);
        }

        driveContents.discard(getGoogleApiClient());
        return contents;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        if (result == null) {
            showMessage("Error while reading from the file");
            return;
        }
        showMessage("File contents: " + result);
    }
}

And there is Authentication code: 并且有验证码:

public abstract class ApiClientAsyncTask<Params, Progress, Result>
    extends AsyncTask<Params, Progress, Result> {

private GoogleApiClient mClient;

public ApiClientAsyncTask(Context context) {
    GoogleApiClient.Builder builder = new GoogleApiClient.Builder(context)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE);
    mClient = builder.build();
}

@Override
protected final Result doInBackground(Params... params) {
    Log.d("TAG", "in background");
    final CountDownLatch latch = new CountDownLatch(1);
    mClient.registerConnectionCallbacks(new ConnectionCallbacks() {
        @Override
        public void onConnectionSuspended(int cause) {
        }

        @Override
        public void onConnected(Bundle arg0) {
            latch.countDown();
        }
    });
    mClient.registerConnectionFailedListener(new OnConnectionFailedListener() {
        @Override
        public void onConnectionFailed(ConnectionResult arg0) {
            latch.countDown();
        }
    });
    mClient.connect();
    try {
        latch.await();
    } catch (InterruptedException e) {
        return null;
    }
    if (!mClient.isConnected()) {
        return null;
    }
    try {
        return doInBackgroundConnected(params);
    } finally {
        mClient.disconnect();
    }
}

/**
 * Override this method to perform a computation on a background thread, while the client is
 * connected.
 */
protected abstract Result doInBackgroundConnected(Params... params);

/**
 * Gets the GoogleApliClient owned by this async task.
 */
protected GoogleApiClient getGoogleApiClient() {
    return mClient;
}

Do you know the right approach with this demo, please? 请问您知道此演示的正确方法吗?

Unfortunately, I don't have time to dig through all of the code above, but I can (at least) give you some general pointers. 不幸的是,我没有时间深入研究上面的所有代码,但是我可以(至少)为您提供一些通用的指针。

First, the demos you mention do work, I've tested it and have it running. 首先,您提到的演示可以正常工作,我已经对其进行了测试并使其运行。 But since the demos cover just about any scenario, it is difficult to trace your possible error. 但是,由于演示几乎涵盖了所有情况,因此很难跟踪您可能的错误。

Now, the pointers: 现在,指针:

  1. When you create a file, you get back a DriveId. 创建文件时,您将获得一个DriveId。
  2. You use that DriveId to retrieve the file 您使用该DriveId检索文件
  3. The content of the file is a binary byte array or stream 文件的内容是二进制字节数组或流

I've put together a basic CRUD wrapper for the GDAA, you can find it here . 我为GDAA整理了一个基本的CRUD包装器,您可以在这里找到它。

In the GDAA.java class, you'll find ' createFile() ' method. GDAA.java类中,您将找到“ createFile() ”方法。 I think you have to give it the ' result.getDriveFile().getDriveId() ' that you received in your ' fileCallback ' above (as a parent). 我认为您必须给它在您的“ fileCallback ”中作为父母收到的“ result.getDriveFile()。getDriveId() ”。 The content is passed in as a standard java.io.File 内容作为标准java.io.File传入

That method returns DriveId (in String form so I can easily cache it) and you can pass that DriveId to the 'read()' method that will give you a byte array (stream) back. 该方法返回DriveId(以String形式,因此我可以轻松地对其进行缓存),并且您可以将该DriveId传递给“ read()”方法,该方法将为您提供一个字节数组(流)。 Dump it to a java.io.File and you're done (don't forget to run it off-UI thread, they are blocking methods). 将其转储到java.io.File中,您就可以完成操作(不要忘记在非UI线程中运行它,它们是阻塞方法)。

I would recommend to test it first using Drive's root (not app folder), so you can actually see the file in drive.google.com 我建议先使用云端硬盘的根目录(而不是应用程序文件夹)对其进行测试,以便您可以实际在drive.google.com中看到该文件

Good Luck 祝好运

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Google Drive Android API(GDAA)getResourceId()返回null(计时问题) - Google Drive Android API (GDAA) getResourceId() returning null (timing issue) GDAA(Google Drive Android API):使用fileId从AppDataFolder下载文件 - GDAA(Google Drive Android API): download file from AppDataFolder by using fileId 新的Google Drive Android API(GDAA)创建的文件未显示 - Files created by the NEW Google Drive Android API (GDAA) not showing up Android Google Drive API创建和编辑Excel文件 - Android google drive api create and edit excel file 如何强制Android应用程序仅使用某个帐户来使用Google Drive API(GDAA)? - How can I force an android app to use only a certain account to use google drive api (GDAA)? Google Drive Android API-从驱动器下载数据库文件 - Google Drive Android api - Downloading db file from drive 谷歌驱动器 api 用于 android 延迟检索创建的文件 - google drive api for android delay retrieve created file Google Drive Android API无法检索文件内容 - Google drive android API unable to retrieve file content 如何使用 API 在 Google Drive 上创建文件夹和文件? 安卓 - How to create a folder and a file on Google Drive using API? Android 无法使用Google Drive Android API创建电子表格文件 - Cannot create a spreadsheet file using Google Drive Android API
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM