我想部分阅读Google云端硬盘上的文件(Range request或Partial download)。此外,我想要串行执行 - 仅在读取前一个间隔(使用CountDownLatch)并在单独的线程(Android禁止主线程中的HTTP请求)之后读取下一个间隔。为此,我想实现ByteChannel方法:
@Override
public int read(final ByteBuffer dst) {
final com.google.api.services.drive.model.File googleFile = mFile.getImpliedFile();
final int bufferLength = dst.capacity();
final int[] bytesReceived = {-1};
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable(){
public void run() {
byte[] receivedByteArray = getByteArrayGoogle(mService, googleFile, position, bufferLength);
// byte[] receivedByteArray = getByteArrayApache(googleFile, position, bufferLength);
dst.put(receivedByteArray, 0, receivedByteArray.length);
bytesReceived[0] = receivedByteArray.length;
position += receivedByteArray.length;
latch.countDown();
}
}).start();
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return bytesReceived[0];
}
如果我使用谷歌推荐的谷歌google-api-services-drive-v2-rev151-1.18.0-rc.jar和google-api-client-assembly-1.18.0-rc-1.18.0-rc.zip:
private byte[] getByteArrayGoogle(Drive drive, File file, long position, int byteCount) {
String downloadUrl = file.getDownloadUrl();
byte[] receivedByteArray = null;
if (downloadUrl != null && downloadUrl.length() > 0) {
try {
com.google.api.client.http.HttpRequest httpRequestGet = drive.getRequestFactory().buildGetRequest(new GenericUrl(downloadUrl));
httpRequestGet.getHeaders().setRange("bytes=" + position + "-" + (position + byteCount - 1));
com.google.api.client.http.HttpResponse response = httpRequestGet.execute();
InputStream is = response.getContent();
receivedByteArray = IOUtils.toByteArray(is);
response.disconnect();
System.out.println("google-http-client-1.18.0-rc response: [" + position + ", " + (position + receivedByteArray.length - 1) + "]");
} catch (IOException e) {
e.printStackTrace();
}
}
return receivedByteArray;
}
我永远不会读超过六个间隔!但是,如果我使用Apache HTTP客户端:
private byte[] getByteArrayApache(File file, long position, int byteCount) {
String downloadUrl = file.getDownloadUrl();
byte[] receivedByteArray = null;
if (downloadUrl != null && downloadUrl.length() > 0) {
try {
org.apache.http.client.methods.HttpGet httpRequestGet = new HttpGet(downloadUrl);
httpRequestGet.addHeader("Authorization", "Bearer " + GoogleDriveActivity.getAccessToken(mContext));
httpRequestGet.addHeader("Range", "bytes=" + position + "-" + (position + byteCount - 1));
org.apache.http.HttpResponse response = new DefaultHttpClient().execute(httpRequestGet);
InputStream is = response.getEntity().getContent();
receivedByteArray = IOUtils.toByteArray(is);
System.out.println("apache-http-client response: [" + position + ", " + (position + receivedByteArray.length - 1) + "]");
} catch (IOException e) {
e.printStackTrace();
}
}
return receivedByteArray;
}
我可以阅读所有需要的时间间隔。
问题似乎出现在com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential。RequestHandler
public void intercept(HttpRequest request) throws IOException {
try {
token = getToken();
request.getHeaders().setAuthorization("Bearer " + token);
} catch (GooglePlayServicesAvailabilityException e) {
throw new GooglePlayServicesAvailabilityIOException(e);
} catch (UserRecoverableAuthException e) {
throw new UserRecoverableAuthIOException(e);
} catch (GoogleAuthException e) {
throw new GoogleAuthIOException(e);
}
}
因为我无法获得token第七个请求,并且应用程序在调试时总是冻结。
token = getToken();
1。这种奇怪的行为是什么原因以及如何使用Google API发出六个以上的请求?
2。是否有其他方法可以使用Google API进行部分下载?
P.S。顺便说一句,类RequestHandler有注释@Beta ...
COMMENT: 似乎问题出在Google Play服务专有类com.google.android.gms.auth.GoogleAccountCredential used for getting a token中:
GoogleAuthUtil.getToken(context, accountName, scope)
由于我怀疑GoogleAuthUtil.getToken必须使用主线程验证身份验证,但主要线程在等待请求结果时被CountDownLatch阻止。因此,我此时已陷入僵局。前六个请求是从AsyncTask执行的,它们不会阻塞主线程。