问题
I am making an app which works with google drive.
I need to get a list of ALL files inside a folder, but it seems that it isnt possible: when I call listFiles method() i cant get all files inside a DriveFolder. But not only that, in the list of files I get, there are some files which I deleted previously.
I have read that it may be caused by a sync delay because of google play services, but I had selected 'Sync now' option in my account settings so I think that the problem is not caused by that delay.
This is the method I am talking about http://developer.android.com/reference/com/google/android/gms/drive/DriveFolder.html#listChildren(com.google.android.gms.common.api.GoogleApiClient)
And this is the code I have written:
public class ServicePull extends IntentService implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private GoogleApiClient mApiClient;
public static void startPull(Context context) {
Intent intent = new Intent(context, ServicePull.class);
context.startService(intent);
}
public ServicePull() {
super("ServicePull");
}
@Override
protected void onHandleIntent(Intent intent) {
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mApiClient.connect();
}
@Override
public void onConnected(Bundle bundle) {
NotificationStatus.notify(this, "On Connected", "mApiClient Connected");
DriveFolder driveFolder = Drive.DriveApi.getRootFolder(mApiClient);
driveFolder.listChildren(mApiClient).setResultCallback(rootFolderCallback);
}
@Override
public void onConnectionSuspended(int i) {
NotificationStatus.notify(this, "On Suspended", "mApiClient Suspended");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
NotificationStatus.notify(this, "On failed", "mApiClient failed");
}
final private ResultCallback<DriveApi.MetadataBufferResult> rootFolderCallback =
new ResultCallback<DriveApi.MetadataBufferResult>() {
@Override
public void onResult(DriveApi.MetadataBufferResult metadataBufferResult) {
log("got root folder");
MetadataBuffer buffer = metadataBufferResult.getMetadataBuffer();
log("Buffer count " + buffer.getCount());
for(Metadata m : buffer){
log("Metadata name " + m.getTitle() + "(" + (m.isFolder() ? "folder" : "file") + ")");
if (m.isFolder() && m.getTitle().equals("Neewie"))
Drive.DriveApi.getFolder(mApiClient, m.getDriveId())
.listChildren(mApiClient)
.setResultCallback(fileCallback);
}
}
};
final private ResultCallback<DriveApi.MetadataBufferResult> fileCallback =
new ResultCallback<DriveApi.MetadataBufferResult>() {
@Override
public void onResult(DriveApi.MetadataBufferResult metadataBufferResult) {
log("got file children");
MetadataBuffer buffer = metadataBufferResult.getMetadataBuffer();
//for(Metadata m : buffer){
log("Buffer count " + buffer.getCount());
for(int i =0;i<buffer.getCount();i++){
Metadata m = buffer.get(i);
log(m.toString());
Drive.DriveApi.getFile(mApiClient, m.getDriveId())
.openContents(mApiClient, DriveFile.MODE_READ_ONLY,
new DriveFile.DownloadProgressListener() {
@Override
public void onProgress(long bytesDownloaded, long bytesExpected) {
// Update progress dialog with the latest progress.
int progress = (int) (bytesDownloaded * 100 / bytesExpected);
Log.wtf("TAG", String.format("Loading progress: %d percent", progress));
}
}
)
.setResultCallback(contentsCallback);
}
}
};
final private ResultCallback<DriveApi.ContentsResult> contentsCallback =
new ResultCallback<DriveApi.ContentsResult>() {
@Override
public void onResult(DriveApi.ContentsResult contentsResult) {
log("got file contents");
File file = new File("storage/emulated/0/Downtests/tessing.txt");
file.mkdirs();
try {
InputStream input = contentsResult.getContents().getInputStream();
OutputStream output = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = input.read(buf)) > 0) {
output.write(buf, 0, len);
}
input.close();
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
private void log(String s){
Log.wtf("ServicePull", s);
}
}
Obviously, I have created a folder called 'Neewie' and inside it a file. I have got a DriveFolder pointing to Neewie folder, but when listChildren it, I receive a MetadataBuffer with count 0.
Do I need to do something to list ALL files? Is something wrong with gms library?
回答1:
It would take me long time to re-run your example, but I may have a few points to get you ahead.
First, since there is no DELETE functionality in Google Drive Android API yet, you are probably referring to the "remove" action in the web Drive interface. The status Metadata.isTrashed() does not reflect the status correctly as discussed here. And using requestSync() did not help. But I let this issue go since I expect them to fix it with the implementation of DELETE in GDAA. More on DELETE can be found here.
Second, I use the "await" version of the calls in my test environment (wrapped in AsyncTask) to test things. It is much easier to step through. I have experienced some "weird" behavior once a while, but could not pinpoint it. Fixed it by clearing the Google Play Services cache.
Third, there is a Google Api Client wrapper class GooApiClnt in this code (at the bottom) that seems to produce stable results - you may try it. You may test the 'findAll'(i.e. DriveApi.query) versions instead of 'listAll'(i.e. listChildren) since it allows you to filter the TRASHED state upfront. BTW, I noticed that you're not logging the Metadata.isTrashed() status in your example. It would give a better view of what files were deleted. But again, it would only confirm the sync latency issues.
The last, minor issue - and I don't know if it wasn't fixed on the GDAA level already - the release/closing of the of the 'getMetadataBuffer'. It was causing resource leaks in my code. Again, see the Github code referenced above, grep 'mdb.close()'.
Happy coding and good luck
回答2:
I've tried this approach and I've also found that not all files are returned. Unfortunately, this behaviour is intentional =(
I quote from the documentation:
"The Google Drive Android API currently only supports drive.file and drive.appfolder"
drive.file (Drive.SCOPE_FILE) means: "Per-file access to files created or opened by the app"
"This means that only files which a user has opened or created with your application can be matched by a query"
See:
https://developers.google.com/drive/android/auth
https://developers.google.com/drive/android/queries
来源:https://stackoverflow.com/questions/22408579/drivefolder-listchildren-not-showing-all-its-children