Android resumable upload to Google Drive - android

I am testing the Drive API for Android to upload a file that can show uploaded progress and be able to resume the upload if it fails (Files size > 30 MB.)
With the following questions:
Uploading Downloading of large size file to Google Drive giving error,
Upload progress listener not fired (Google drive API)
I was able to get the upload progress and they mention those are resumable uploads. However, I don't see any code that looks for an upload error and resume logic, thus if I kill the application and "resume" the upload, it simply starts from the beginning.
This is my code:
public class DriveScreen extends BaseDriveActivity {
private Drive service;
private Context context;
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
context = this;
//https://stackoverflow.com/questions/17429798/usingoauth2-deprecated
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(this, Arrays.asList(DriveScopes.DRIVE_FILE));
credential.setSelectedAccountName("accountNameHERE");
service = new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential).build();
UploadFile();
}
public void UploadFile() {
AsyncTask<Void, Long, String> task = new AsyncTask<Void, Long, String>() {
java.io.File fileContent;
FileContent mediaContent;
com.google.api.services.drive.model.File body;
com.google.api.services.drive.model.File file;
private ProgressDialog mDialog;
long mFileLen;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading ");
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton("Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
}
});
mDialog.show();
}
class FileUploadProgressListener implements MediaHttpUploaderProgressListener {
#Override
public void progressChanged(MediaHttpUploader uploader) throws IOException {
Log.d("Percent ", String.valueOf(uploader.getProgress()));
switch (uploader.getUploadState()) {
case INITIATION_STARTED:
System.out.println("Initiation Started");
break;
case INITIATION_COMPLETE:
System.out.println("Initiation Completed");
break;
case MEDIA_IN_PROGRESS:
System.out.println("Upload in progress");
System.out.println("Upload percentage: " + uploader.getProgress());
mDialog.setProgress((int) (uploader.getProgress()*100));
break;
case MEDIA_COMPLETE:
System.out.println("Upload Completed!");
break;
case NOT_STARTED:
System.out.println("Upload Not Started!");
break;
}
}
}
#Override
protected String doInBackground(Void... arg0) {
try {
File folder = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
);
File UPLOAD_FILE = new File(folder, "filePathHERE");
fileContent = new File(folder, "filePathHERE");
mFileLen = fileContent.length();
InputStreamContent mediaContent2 = new InputStreamContent("application/zip", new FileInputStream(UPLOAD_FILE));
mediaContent2.setLength(UPLOAD_FILE.length());
body = new com.google.api.services.drive.model.File();
body.setTitle(fileContent.getName());
body.setMimeType("application/zip");
//String parentId = null;
//int x = Files.List.setQ("mimeType = 'application/vnd.google-apps.folder' and title = 'ShareHim'");
//body.setParents(Arrays.asList(new ParentReference().setId(uploadFile.getFileHostFolderId())));
Files.Insert mInsert = service.files().insert(body, mediaContent2);
if(mFileLen > 5 * 1024 * 1024)
{
MediaHttpUploader uploader = mInsert.getMediaHttpUploader();
uploader.setDirectUploadEnabled(false);
uploader.setChunkSize(MediaHttpUploader.MINIMUM_CHUNK_SIZE);
uploader.setProgressListener(new FileUploadProgressListener());
file = mInsert.execute();
if (file != null) {
}
}
else {
mInsert.execute();
}
} catch (UserRecoverableAuthIOException e) {
System.out.println("login error");
Log.d("Error", "not login " + e);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result) {
mDialog.dismiss();
};
};
task.execute();
}
}
Now, it is uploading by chunks, but how can we resume the upload from the last chunk sent. My first impression after watching Google Drive talks on youtube was that the resumable upload was handled automatically, but it doesn't seem to be the case.
Am I approaching this the wrong way? Is it worth considering using a DriveSyncAdapter to upload a file as an alternative? (Sorry for the bad code, this is just a test)

It looks like you are using the Java REST-ful API. If you use the Android-specific API, this is all handled for you. Just hand over the file, and the API will do resumable upload as appropriate. See creating files.

Related

Using Google Drive to backup and restore SQLite Database

I've managed to create a backup of my database on an SD card and restore from there but realized that the purpose of my backup is to ensure the safety of the data and in this case if the physical device itself is damaged, lost, or spontaneously combusts so will the backup on the SD card. So having the backup in the same place as the original in this case, quite frankly defeats the purpose of having a backup.
So I thought of using Google Drive as a safer place to keep the db file, that and it's free. I've taken a peek into Google's quickstart demo which I got working just fine. But I still have no idea how to get this done for my case.
I've found some code to fiddle with but it's still using some deprecated methods and so far I've only managed to run it when omitting the deprecated area but it only creates a blank binary file in my Google Drive so I think that deprecated area is where it actually uploads the DB backup content. If anyone could help out that would be greatly appreciated.
I'll leave it down below in case anyone can use it to explain things to me better. I've also marked the deprecated method below, it's near the end.
public class ExpectoPatronum extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
private static final String TAG = "MainActivity";
private GoogleApiClient api;
private boolean mResolvingError = false;
private DriveFile mfile;
private static final int DIALOG_ERROR_CODE =100;
private static final String DATABASE_NAME = "demodb";
private static final String GOOGLE_DRIVE_FILE_NAME = "sqlite_db_backup";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create the Drive API instance
api = new GoogleApiClient.Builder(this).addApi(Drive.API).addScope(Drive.SCOPE_FILE).
addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
}
#Override
public void onStart() {
super.onStart();
if(!mResolvingError) {
api.connect(); // Connect the client to Google Drive
}
}
#Override
public void onStop() {
super.onStop();
api.disconnect(); // Disconnect the client from Google Drive
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.v(TAG, "Connection failed");
if(mResolvingError) { // If already in resolution state, just return.
return;
} else if(result.hasResolution()) { // Error can be resolved by starting an intent with user interaction
mResolvingError = true;
try {
result.startResolutionForResult(this, DIALOG_ERROR_CODE);
} catch (SendIntentException e) {
e.printStackTrace();
}
} else { // Error cannot be resolved. Display Error Dialog stating the reason if possible.
ErrorDialogFragment fragment = new ErrorDialogFragment();
Bundle args = new Bundle();
args.putInt("error", result.getErrorCode());
fragment.setArguments(args);
fragment.show(getFragmentManager(), "errordialog");
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == DIALOG_ERROR_CODE) {
mResolvingError = false;
if(resultCode == RESULT_OK) { // Error was resolved, now connect to the client if not done so.
if(!api.isConnecting() && !api.isConnected()) {
api.connect();
}
}
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.v(TAG, "Connected successfully");
/* Connection to Google Drive established. Now request for Contents instance, which can be used to provide file contents.
The callback is registered for the same. */
Drive.DriveApi.newDriveContents(api).setResultCallback(contentsCallback);
}
final private ResultCallback<DriveApi.DriveContentsResult> contentsCallback = new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.v(TAG, "Error while trying to create new file contents");
return;
}
String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db");
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(GOOGLE_DRIVE_FILE_NAME) // Google Drive File name
.setMimeType(mimeType)
.setStarred(true).build();
// create a file on root folder
Drive.DriveApi.getRootFolder(api)
.createFile(api, changeSet, result.getDriveContents())
.setResultCallback(fileCallback);
}
};
final private ResultCallback<DriveFileResult> fileCallback = new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
Log.v(TAG, "Error while trying to create the file");
return;
}
mfile = result.getDriveFile();
mfile.open(api, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(contentsOpenedCallback);
}
};
final private ResultCallback<DriveApi.DriveContentsResult> contentsOpenedCallback = new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.v(TAG, "Error opening file");
return;
}
try {
FileInputStream is = new FileInputStream(getDbPath());
BufferedInputStream in = new BufferedInputStream(is);
byte[] buffer = new byte[8 * 1024];
DriveContents content = result.getDriveContents();
BufferedOutputStream out = new BufferedOutputStream(content.getOutputStream());
int n = 0;
while( ( n = in.read(buffer) ) > 0 ) {
out.write(buffer, 0, n);
}
in.close();
commitAndCloseContents is DEPRECATED -->/**mfile.commitAndCloseContents(api, content).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status result) {
// Handle the response status
}
});**/
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private File getDbPath() {
return this.getDatabasePath(DATABASE_NAME);
}
#Override
public void onConnectionSuspended(int cause) {
// TODO Auto-generated method stub
Log.v(TAG, "Connection suspended");
}
public void onDialogDismissed() {
mResolvingError = false;
}
public static class ErrorDialogFragment extends DialogFragment {
public ErrorDialogFragment() {}
public Dialog onCreateDialog(Bundle savedInstanceState) {
int errorCode = this.getArguments().getInt("error");
return GooglePlayServicesUtil.getErrorDialog(errorCode, this.getActivity(), DIALOG_ERROR_CODE);
}
public void onDismiss(DialogInterface dialog) {
((ExpectoPatronum) getActivity()).onDialogDismissed();
}
}
}
Both APIs used to access Google Drive deal with a binary content. So the only thing you have to do is to upload your binary DB file, give it a proper MIME type and a NAME (title).
The selection of API depends on you, GDAA behaves like a 'local' entity with uploads / downloads handled by Google Play Services, REST Api is more low-level, giving you more control, but you have to take care of networking issues (wifi on/off, etc), i.e. you usually have to build a sync service to do so. With GDAA it is done for you by GooPlaySvcs. But I digress.
I can point you to this GitHub demo, fairly recent (GooPlaySvcs 7.00.+), I use to test different REST / GDAA issues.
The MainActivity is a bit complicated by the fact that it allows for switching between different Google accounts, but if you get through these hurdles, you can use either REST or GDAA CRUD wrappers.
Take look at this line. The byte[] buffer contains binary JPEG data and it goes with "image/jpeg" mime type (and a time-based name). The only thing you have to do if is load your DB file into a byte[] buffer using a construct like this:
private static final int BUF_SZ = 4096;
static byte[] file2Bytes(File file) {
if (file != null) try {
return is2Bytes(new FileInputStream(file));
} catch (Exception ignore) {}
return null;
}
static byte[] is2Bytes(InputStream is) {
byte[] buf = null;
BufferedInputStream bufIS = null;
if (is != null) try {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
bufIS = new BufferedInputStream(is);
buf = new byte[BUF_SZ];
int cnt;
while ((cnt = bufIS.read(buf)) >= 0) {
byteBuffer.write(buf, 0, cnt);
}
buf = byteBuffer.size() > 0 ? byteBuffer.toByteArray() : null;
} catch (Exception e) {le(e);}
finally {
try {
if (bufIS != null) bufIS.close();
} catch (Exception e) {le(e);}
}
return buf;
}
I don't remember the MIME type for SQLite DB now, but I am sure it can be done since I was doing exactly that once (the code is gone now, unfortunately). And I remember I could actually access and modify the SQLite DB 'up in the cloud' using some web app.
Good Luck
UPDATE:
After I wrote the rant above I looked at the demo you're talking about. If you have it working, the easiest way is actually to plug your DB file right here, set the correct MIME and you're good to go. Take you pick.
And to address your 'deprecated' issue. GDAA is still being developed and the quickstart is over a year old. That's the world we live in :-)
You need to replace the deprecated code with:
contents.commit(api, null);
See https://developer.android.com/reference/com/google/android/gms/drive/DriveContents.html

Create folder in using dropbox api for android

Does anyone know how to create folder programatically using dropbox api for android??I am not using sync api.I have managed to upload images and files but I am unable to create folder.
This is my upload asynctask:
public class UploadFile extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private ProgressDialog mDialog;
final static private String ACCOUNT_PREFS_NAME = "prefs";
private String mErrorMsg;
public UploadFile(Context context, DropboxAPI<?> api, String dropboxPath,
File file) {
mContext = context;
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + file.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mRequest.abort();
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + mFile.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
if (mRequest != null) {
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
e.printStackTrace();
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int) (100.0 * (double) progress[0] / mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Successfully uploaded");
// mApi.getSession().unlink();
//
// // Clear our stored keys
// clearKeys();
} else {
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
private void clearKeys() {
SharedPreferences prefs = mContext.getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
}
Please help.
According to dropbox documentation
try {
// creating folder
val fo = client.files().createFolderV2(File.separator + folderPath)
} catch (ex: CreateFolderErrorException) {
if (ex.errorValue.isPath && ex.errorValue.pathValue.isConflict) {
// folder already exist
}
}
You can simply give like this for creating a folder! its very simple
dropbox.putFile("Mynumber2/myregion2/"+"/"+"A"+"/"+"B"+"/"+"ENTRY.db", fileInputStream,file.length(), null, null);
if you do, mynumber2-->myregion2-->A-->B will be your folder structure created on dropbox!
You want the createFolder method of DropboxAPI. See https://www.dropbox.com/static/developers/dropbox-android-sdk-1.6.1-docs/com/dropbox/client2/DropboxAPI.html#createFolder(java.lang.String).
Use the following for DIR:
"/your_folder_name/"

How to replace file in Google Drive?

Using the following code, which is take from android-quickstart, this code can produce multiple files with same name if you take multiple pictures. How can it be modified to ensure the file with the same name is replaced?
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "android-drive-quickstart";
private static final int REQUEST_CODE_CAPTURE_IMAGE = 1;
private static final int REQUEST_CODE_CREATOR = 2;
private static final int REQUEST_CODE_RESOLUTION = 3;
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;
/**
* Create a new file and save it to Drive.
*/
private void saveFileToDrive() {
// Start by creating a new contents, and setting a callback.
Log.i(TAG, "Creating new contents.");
final Bitmap image = mBitmapToSave;
Drive.DriveApi.newContents(mGoogleApiClient).setResultCallback(new ResultCallback<ContentsResult>() {
#Override
public void onResult(ContentsResult result) {
// If the operation was not successful, we cannot do anything
// and must
// fail.
if (!result.getStatus().isSuccess()) {
Log.i(TAG, "Failed to create new contents.");
return;
}
// Otherwise, we can write our data to the new contents.
Log.i(TAG, "New contents created.");
// Get an output stream for the contents.
OutputStream outputStream = result.getContents().getOutputStream();
// Write the bitmap data from it.
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
try {
outputStream.write(bitmapStream.toByteArray());
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.");
}
// Create the initial metadata - MIME type and title.
// Note that the user will be able to change the title later.
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("image/jpeg")
.setTitle("Android Photo.png")
.build();
// Create an intent for the file chooser, and start it.
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialContents(result.getContents())
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.");
}
}
});
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Connect the client. Once connected, the camera is launched.
mGoogleApiClient.connect();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_CAPTURE_IMAGE:
// Called after a photo has been taken.
if (resultCode == Activity.RESULT_OK) {
// Store the image data as a bitmap for writing later.
mBitmapToSave = (Bitmap) data.getExtras().get("data");
}
break;
case REQUEST_CODE_CREATOR:
// Called after a file is saved to Drive.
if (resultCode == RESULT_OK) {
Log.i(TAG, "Image successfully saved.");
mBitmapToSave = null;
// Just start the camera again for another photo.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
}
break;
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
if (mBitmapToSave == null) {
// This activity has no UI of its own. Just start the camera.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
return;
}
saveFileToDrive();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
}
We can use the Google Drive API to:
- Find the existing file
- Get its ID
- Delete the file
- Write a new file
I open the drive file for writing as follows:
writeDriveFile(DriveFile file, Handler handler){
//see query task below to get a drive file by its name. Be careful you can get multiple data elements in the MetadataBuffer below if you have uploaded multiple files with the same name.
Task<DriveContents> openFileTask = myDriveResourceClient.openFile(file, DriveFile.MODE_WRITE_ONLY);
Then with that task write some object bytes to the stream someObject.getBytes(), no magic here. Then commit the results.
openFileTask
.continueWithTask(task -> {
DriveContents contents = task.getResult();
// Process contents...
try (OutputStream writer = contents.getOutputStream()) {
writer.write(someObject.getBytes());
writer.close();
}
//Add whatever metadata you want here
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setLastViewedByMeDate(new Date())
.build();
//commit the file to Google Drive
Task<Void> commitTask = myDriveResourceClient.commitContents(contents, changeSet);
handler.onWriteResults();
return commitTask;
})
.addOnFailureListener(e -> {
// Handle failure
Log.e(TAG, "Unable to read contents", e);
handler.onDriveError(e);
});
The handler is just an interface I defined for errors or results that I want to process after Drive API execution. You could also add an addOnCompleteListener() to process something once the writing was complete.
file is an instance of DriveFile that can be acquired by a query task. The metadata that come to you in the task code block has a getDriveId() method which has a asDrivefFile() method to get the Drive file you need above.
Query query = new Query.Builder()
.addFilter(Filters.eq(SearchableField.TITLE, "file name"))
.build();
Task<MetadataBuffer> queryTask = mDriveResourceClient.query(query);
Then process the MetadataBuffer
queryTask.continueWithTask(
task -> {
MetadataBuffer metadataBuffer = task.getResult() ;
//I have this loop because I wanted to know if there were other versions of the file on the drive
for(Metadata data : metadataBuffer) {
Log.d(TAG, "******************* metadataBuffer title is " + data.getTitle());
if(data.getTitle().equals("file name")){
//this is just a method I defined that encapsulates the drive writing code above.
writeDriveFile(data.getDriveId().asDriveFile(), jsonContent, handler);
}
}
return task;
})
.addOnCompleteListener(task -> {
//some complete tasks
}
})
.addOnFailureListener(e -> {
Log.e(TAG, "************************** Error searching for " + fileName, e);
handler.onDriveError(e);
});
This code was all for writing to the App folder but you just need to set the right scope when you create you resource client.
Deleting a drive file can be done as follows.
public void deleteDriveFile(DriveResource file){
Task<Void> deleteTask = mDriveResourceClient.delete(file);
deleteTask
.continueWith(task -> {
Log.d(TAG, "************* Deleted drive file: " + file.getDriveId().toInvariantString());
return task;
})
.addOnFailureListener(e -> {
//log some sort of error for yourself
});
}

ProgressDialog is not showing when .3gp file converting to a .zip

I am working on Android app.
I need to show a progress dialog box when I click on button.
In that button I am converting video file to .zip file and calculating that file size.
In this process I need to show a ProgressDialog, but it is not showing.
Screen get struck while calculating and after calculation it shows ProgressDialog and then screen navigating to the next screen.
My Code:
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaCheck.this.runOnUiThread(new Runnable() {
public void run() {
pd = ProgressDialog.show(MediaCheck.this, "",
"Checking the video compatability. Please wait", true);
}
});
video_Path= makeZip(video_Path);
if (video_Path.equalsIgnoreCase("File size is too large")) {
pd.dismiss();
Toast.makeText(getApplicationContext(),
"Large video", Toast.LENGTH_LONG)
.show();
return;
}
pd.dismiss();
// Doing screen navigation here.
}
});
Code to make a zip and know the size
private static String makeZip(String videoPath) {
byte[] buffer = new byte[1024];
String[] videoFileName = videoPath.split("/");
File directory = null;
try {
ContextWrapper cw = new ContextWrapper(context_this);
// path to /data/data/yourapp/app_data/imageDir
directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
FileOutputStream fos = new FileOutputStream(directory
+ "/IRCMS_Video.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze = null;
ze = new ZipEntry(videoFileName[5]);
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(videoPath);
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
File videoZip = new File(directory + "/IRCMS_Video.zip");
videoLength = videoZip.length() / (1024 * 1024);
if (videoLength > 3)
return "File size is too large";
in.close();
zos.closeEntry();
// remember close it
zos.close();
System.out.println("Done");
} catch (IOException ex) {
ex.printStackTrace();
}
return directory.toString() + "/IRCMS_Video.zip";
}
}
Please help...
then you should try ASYNCTASK to easily perform your operation and reduce the complexity of using threads
private class Converter extends AsyncTask<String, Void, Void> { //Converter is class name
protected String doInBackground(String... urls) {
//THIS METHOD WILL BE CALLED AFTER ONPREEXECUTE
//YOUR NETWORK OPERATION HERE
return null;
}
protected void onPreExecute() {
super.onPreExecute();
//THIS METHOD WILL BE CALLED FIRST
//DO OPERATION LIKE SHOWING PROGRESS DIALOG PRIOR TO BEGIN NETWORK OPERATION
}
protected void onPostExecute(String result) {
super.onPostExecute();
//TNIS METHOD WILL BE CALLED AT LAST AFTER DOINBACKGROUND
//DO OPERATION LIKE UPDATING UI HERE
}
}
You are doing calculation on UI thread therfore it hangs your app. Do calculation on background thread. You can resolve this by-
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pd = ProgressDialog.show(MediaCheck.this, "",
"Checking the video compatability. Please wait", true);
Thread background = new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
video_Path= makeZip(video_Path);
MediaCheck.this.runOnUiThread(new Runnable()
{
public void run()
{
if (video_Path.equalsIgnoreCase("File size is too large")) {
pd.dismiss();
Toast.makeText(getApplicationContext(),
"Large video", Toast.LENGTH_LONG)
.show();
pd.dismiss();
return;
}
}
});
}
});
background.start();
// Doing screen navigation here.
}
});

Resumable YouTube uploads with YouTube Data API v3 in Android

I'm uploading videos to my YouTube account from my Android application using YouTube Data API v3. Uploading process works perfectly. What I need is, if my upload got interrupted (eg. because of Internet connection) I need to start upload next time where it left.
private void uploadVideo(UploadInfo videoInfo) {
Insert videoInsert = prepareUpload( new File(videoInfo.getFilePath()) );
new VideoUploadAsyncTask(videoInfo, getActivity(), videoUploadAsyncTaskInterface).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, videoInsert);
}
public Insert prepareUpload( File videoFile ) {
try {
Video videoObjectDefiningMetadata = new Video();
VideoStatus status = new VideoStatus();
status.setPrivacyStatus("public");
videoObjectDefiningMetadata.setStatus(status);
VideoSnippet snippet = new VideoSnippet();
snippet.setTitle(videoFile.getName());
snippet.setDescription("Uploaded via AnujAroshA Android app");
List<String> tags = new ArrayList<String>();
tags.add("AnujAroshA");
snippet.setTags(tags);
videoObjectDefiningMetadata.setSnippet(snippet);
InputStreamContent mediaContent = new InputStreamContent(VIDEO_FILE_FORMAT, new BufferedInputStream(new FileInputStream(videoFile)));
mediaContent.setLength(videoFile.length());
YouTube.Videos.Insert videoInsert = youtube.videos().insert("snippet,status", videoObjectDefiningMetadata, mediaContent);
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();
uploader.setDirectUploadEnabled(false);
uploader.setChunkSize(MediaHttpUploader.MINIMUM_CHUNK_SIZE);
return videoInsert;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
}
How can I do that?
Update with VideoUploadAsyncTask class doInBackground method
#Override
protected String doInBackground( Insert... inserts ) {
try{
Insert videoInsert = inserts[0];
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();
MediaHttpUploaderProgressListener progressListener = new MediaHttpUploaderProgressListener() {
#Override
public void progressChanged(MediaHttpUploader uploader) throws IOException {
switch (uploader.getUploadState()) {
case INITIATION_STARTED:
Log.d(TAG, "# INITIATION_STARTED ");
break;
case INITIATION_COMPLETE:
Log.d(TAG, "# INITIATION_COMPLETE ");
break;
case MEDIA_IN_PROGRESS:
int progress = (int) Math.round(uploader.getProgress() * 100);
Log.d(TAG, "# MEDIA_IN_PROGRESS : progress = " + progress + "%");
publishProgress(progress);
break;
case MEDIA_COMPLETE:
Log.d(TAG, "# MEDIA_COMPLETE ");
publishProgress(100);
break;
case NOT_STARTED:
Log.d(TAG, "# NOT_STARTED ");
break;
default:
break;
}
}
};
uploader.setProgressListener(progressListener);
Video returnedVideo = videoInsert.execute();
return returnedVideo.getId();
}catch(GooglePlayServicesAvailabilityIOException gpsaioe){
}catch(UserRecoverableAuthIOException uraioe){
}catch(GoogleAuthIOException gaioe){
}catch(IOException ioe){
}
return null;
}
Have you seen this question?
The answer suggests that you should use;
youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
credential.initialize(request);
request.setIOExceptionHandler(new HttpBackOffIOExceptionHandler(new ExponentialBackOff()));
}
});
when you initialise your YouTube object.

Categories

Resources