I have implemented the file upload to Amazon S3 following the Amazon guide and I have noticed that it is too slow. It takes around 10 sec to upload a simple png file around 20kb.
Initially I thought that the problem was related with threads and I have implemented an AsyncTask to upload the image, but the problem is still there. Following is the code employed to upload the image.
private class UploadFileTask extends AsyncTask<String, Integer, String> {
String remotePath;
String remoteFileName;
File file;
Context context;
S3UploadInterface listener;
public UploadFileTask(Context context,String remotePath,String remoteFileName, File file, S3UploadInterface listener){
this.context=context;
this.remotePath=remotePath;
this.remoteFileName=remoteFileName;
this.file=file;
this.listener=listener;
}
protected String doInBackground(String... params) {
credentialsProvider = new CognitoCachingCredentialsProvider(context,
"MY_PRIVATE_CREDENTIAL",
Regions.US_EAST_1);
TransferManager transferManager = new TransferManager(credentialsProvider);
Upload upload = transferManager.upload(remotePath, remoteFileName, file);
TransferProgress transferred = upload.getProgress();
while (!upload.isDone()) {
try {
publishProgress((int) transferred.getPercentTransferred());
} catch (Exception e) {
listener.uploadFailed(e);
}
}
return "uploaded";
}
protected void onProgressUpdate(Integer... progress) {
if (listener!=null)
listener.currentUploadProgress(progress[0]);
}
protected void onPostExecute(String result) {
if (listener!=null)
listener.uploadCompleted();
}
}
Any idea to solve this problem?
Thanks :)
This is going to hammer your CPU
while (!upload.isDone()) {
try {
publishProgress((int) transferred.getPercentTransferred());
} catch (Exception e) {
listener.uploadFailed(e);
}
}
Try adding Thread.sleep to give other threads time to run.
Related
I am trying to compress the video but not able to compress fast way....using follow dependency also silicompressor /Video Compressor and Compressor..
The above list of compressor working fine but taking too much of time based on the video selection (For ex : if i select 2 MB video ~3 to 4 minute taking for compression)
class VideoCompressAsyncTask extends AsyncTask<String, String, String> {
Context mContext;
String path = File path;
File directory = new File(path);
public VideoCompressAsyncTask(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgress();
}
#Override
protected String doInBackground(String... paths) {
String filePath = null;
try {
filePath = SiliCompressor.with(mContext).compressVideo(myUrl, directory.getPath(), 0, 0, 0);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return filePath;
}
#Override
protected void onPostExecute(String compressedFilePath) {
super.onPostExecute(compressedFilePath);
File imageFile = new File(compressedFilePath);
}
}
Taking to much of time for video compression
I am using Azure mobile service to upload images from android device.
I have followed the documentation to upload images successfully.
But I can't find any documentation to download the blobs.
Code i used to upload blob is here..
public void uploadPhoto() {
if (MainActivity.mClient == null) {
return;
}
final Assignment_Attachment item = new Assignment_Attachment();
item.setAttachementIdentifier(attachmentUniqueIdentifier);
item.setFilename(MAP_FILE_NAME_KEY);
item.setContainerName("schoolonlineblobattachment");
// Use a unigue GUID to avoid collisions.
UUID uuid = UUID.randomUUID();
String uuidInString = uuid.toString();
item.setResourceName(uuidInString);
// Send the item to be inserted. When blob properties are set this
// generates a SAS in the response.
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
final Assignment_Attachment entity = addItemInTable(item);
Log.d("sasquerystring", "sasquerystring" + entity.getSasQueryString());
// If we have a returned SAS, then upload the blob.
if (entity.getSasQueryString() != null) {
// Get the URI generated that contains the SAS
// and extract the storage credentials.
StorageCredentials cred = new StorageCredentialsSharedAccessSignature(entity.getSasQueryString());
URI imageUri = new URI(entity.getImageUri());
// Upload the new image as a BLOB from a stream.
CloudBlockBlob blobFromSASCredential = new CloudBlockBlob(imageUri, cred);
blobFromSASCredential.uploadFromFile(DATA_FOR_UPLOAD);
}
runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
} catch (final Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//other logic here
}
};
runAsyncTask(task);
}
I can see a "downloadToFile()" method, but still searching a way to use the SAS thing for download process.
Has anybody done this? Any help is appreciated.
To use the SAS, you need a sharedAccessPolicy:
var sharedAccessPolicy = {
AccessPolicy: {
Permissions: 'w',
Expiry: azure.date.minutesFromNow(5)
}
}
The sharedAccessPolicy.AccessPolicy.Permissions w' is for uploading while 'r' is for downloading.
Not verified myself yet, but you can try http://inessential.com/2014/04/22/mobile_services_and_blob_storage. See also the code at https://code.msdn.microsoft.com/windowsapps/Upload-File-to-Windows-c9169190.
Hope it will help.
I'm currently downloading and save some pictures in my Android app.
Here is the class which do the work :
public class BitmapPersist extends AsyncTask<String, Void, Boolean> {
private ArrayList<String> photosNotDownloaded;
private File pointDir;
private KickstartrGeolocPoint point;
private OnBitmapPersistedListener onBitmapPersistedListener;
public BitmapPersist(ArrayList<String> photosNotDownloaded, File pointDir, KickstartrGeolocPoint point, OnBitmapPersistedListener onBitmapPersistedListener) {
this.photosNotDownloaded=photosNotDownloaded;
this.pointDir=pointDir;
this.point=point;
this.onBitmapPersistedListener=onBitmapPersistedListener;
}
#Override
protected Boolean doInBackground(String... params) {
Bitmap bmp;
FileOutputStream out = null;
for(String url : photosNotDownloaded) {
//download the picture synchronously
bmp = ImageLoader.getInstance().loadImageSync(url);
try {
out = new FileOutputStream(pointDir.getPath() + File.separator + FileUtils.getPointPhotoPrefix(point) + FileUtils.getFileNameFromUrl(url));
bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (Throwable ignore) {
}
}
//send notification to the UI in order to scan again the directory and update the carousel
publishProgress();
}
return true;
}
#Override
protected void onPostExecute(Boolean success) {
if (success)
onBitmapPersistedListener.persistedSuccessfully(this.point, this.pointDir);
else
onBitmapPersistedListener.errorInPersistance();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
onBitmapPersistedListener.onProgress();
}
}
This class take an ArrayList of urls in parameter, and for each photo, it download it and save it.
Each time a photo is persisted, a notification is sent to the view to update a carousel (thanks to publishProgress(); )
The problem is that publishProgress() does not work, and every photos are displayed at the same time when every photos are downloaded.
Here is the call of my asynctask :
private void persistImageforPoint(ArrayList<String> photosNotDownloaded, KickstartrGeolocPoint point, File pointDir) {
// Create a subfolder for each point with its id
if (!pointDir.exists()) {
if (!pointDir.mkdirs()) {
LogWrapper.debug(FileUtils.class, "Failed to create directory");
return;
}
}
//save the file. Asynchronous task --> do not block the UI
new BitmapPersist(photosNotDownloaded, pointDir, point, new OnBitmapPersistedListener() {
#Override
public void persistedSuccessfully(KickstartrGeolocPoint point, File pointDir) {
if(currentPoint!=null) {
File pointDirectory = FileUtils.getPointPhotoDir(getActivity(), currentPoint);
loadCarousel(currentPoint, pointDirectory);
}
}
#Override
public void errorInPersistance() {
LogWrapper.error(getClass(),"Error persisting image");
}
#Override
public void onProgress() {
if(currentPoint!=null) {
final File pointDir = FileUtils.getPointPhotoDir(getActivity(), currentPoint);
loadCarousel(currentPoint, pointDir);
}
}
}).execute();
}
I don't have any errors in my logcat.
Thanks for your help ;)
I'm having difficulties keeping track of my queue and uploading them at a later moment.
The upload image is a asynctask and in the postexecute a mail is going out to send the uploaded picture.
This is my UploadImage AsyncTask. I think i'm doing way too difficult and that it can be done much easier than it is right now.
private class UploadImageTask extends AsyncTask<Void, Void, Integer> {
ProgressDialog dialog;
/**
* Private integer which counts how many times we've tried to upload the
* Image.
*/
private int _counter = 0;
private List<String> imageUploadList = new ArrayList<String>();
#Override
protected void onPreExecute() {
super.onPreExecute();
if(AppStatus.haveNetworkConnection(_context)){
if(isPhotoTaken()){
dialog = new ProgressDialog(Step4.this);
dialog.setCancelable(false);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(getString(R.string.uploadingMessage));
dialog.setTitle(getString(R.string.uploadingTitle));
dialog.show();
}
}
}
protected Integer doInBackground(Void... params) {
init();
postData();
return null;
}
public void init(){
_counter = 0;
_beenHere = true;
for(String path : imageUploadList){
Debug.out("Path: "+path);
}
}
public void postData() {
if (isPhotoTaken()) {
if(AppStatus.haveNetworkConnection(_context)){
if(_beenHere){
ImageUploader.uploadFile(getPhotoPath(),
"http://obo.nl/android-upload-image.php", Step4.this);
} else {
for(String path : imageUploadList){
Debug.out(path);
ImageUploader.uploadFile(path,
"http://obo.nl/android-upload-image.php", Step4.this);
}
}
} else {
if (_counter == 0) {
_counter++;
_activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(_context,
getString(R.string.noInternetImageNotUploaded),
Toast.LENGTH_LONG).show();
}
});
imageUploadList.add(getPhotoPath());
}
try {
if(_beenHere){
_beenHere = false;
goToNextIntent();
}
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
postData();
}
}
}
private void goToNextIntent(){
Intent intent = new Intent(Step4.this, Step5.class);
intent.putExtra(EXTRA_MESSAGE, (Serializable) _user);
intent.putExtra(EXTRA_MESSAGE2, _isRepairable);
intent.putExtra(EXTRA_MESSAGE3, _injury);
intent.putExtra(EXTRA_MESSAGE4, _category);
intent.putExtra(EXTRA_MESSAGE5, _inch);
intent.putExtra(EXTRA_MESSAGE6, _size);
startActivity(intent);
}
protected void onPostExecute(Integer result) {
if(isPhotoTaken()){
if(dialog != null){
dialog.dismiss();
}
}
mailing(_isRepairable);
new MyAsyncTask().execute(_mail);
}
}
The line:
if(AppStatus.haveNetworkConnection(_context))
returns a boolean true if the user has a working internet connection. false otherwise.
What I want is to queue all the image paths (and mails sent afterwards) in the desired ArrayList so i can send them all at a later moment when the user has a working internet Connection. Please help me out!
You could store your image paths in a list (or something similar) and persist the list, let's say in Shared Preferences. As you finish uploading a picture, you will remove it from that list and continue to the next one, and so on until your list is empty.
While uploading, if the internet connection drops it will not affect you, you will always have persisted the list of images that are still to be uploaded.
Register a broadcast receiver to listen for wi-fi connection, when it gets connected it could automatically continue the upload - this is just a suggestion.
I have some problem with AsyncTask in my application.
There is AsyncTask which takes File from sd card and makes operations with it.
It is actually giving me a proper result, but while doing the task there are a black screen and a blocked user interface about 3 seconds that obviously would make a user annoyed. I'm wondering how to get rid of this problem.
So here is the code:
ParseXMLTask.java:
public ParseXMLTask(Context context, IPostParse iPostParse, ProgressBar progressBar) {
this.context = context;
this.iPostParse = iPostParse;
this.progressBar = progressBar;
}
#Override
protected Intent doInBackground(File... params) {
File file = params[0];
Intent pack = new Intent(context, PackActivity.class);
/* some heavy parsing task */
return pack;
}
#Override
protected void onPreExecute() {
progressBar.setIndeterminate(true);
}
#Override
protected void onPostExecute(Intent result) {
iPostParse.postParse(result);
}
LoadingActivity.java:
The executing task code:
private void parseXML() {
File file = new File(PATH + fileName + ".xml");
ParseXMLTask parseTask = new ParseXMLTask(this, this, loadingBar);
parseTask.execute(file);
}
And the implemented method of the interface, nothing special:
public void postParse(Intent result) {
result.putExtra("name", packName);
result.putExtra("author", packAuthor);
result.putExtra("date", packDate);
result.putExtra("file", fileName);
result.putExtra("votes", votes);
startActivity(result);
}
Hope you help me to solve this problem, thanks!
This can happen if you are putting too much data into your Intent's extras.