I am trying to upload an image from storage to server. Am I doing anything wrong here? Do I need to use a PHP script for this?
private class UploadImage extends AsyncTask{
File picPath;
String picName;
public UploadImage(File picPath, String picName){
this.picPath= picPath;
this.picName = picName;
}
#Override
protected Void doInBackground(Void... params) {
String uril = getResources().getString(R.string.ServerPath) + "MyFiles/" + picName;
AndroidNetworking.upload(uril)
.addMultipartFile(picName, picPath)
.addMultipartParameter("key","value")
.setPriority(Priority.MEDIUM)
.build()
.setUploadProgressListener(new UploadProgressListener() {
#Override
public void onProgress(long bytesUploaded, long totalBytes) {
if (bytesUploaded == totalBytes){
Toast.makeText(getApplicationContext(), "Image Uploaded!",Toast.LENGTH_SHORT).show();
}
}
});
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(getApplicationContext(), "Uploaded!",Toast.LENGTH_SHORT).show();
}
}
Please note the library which you have considers UPLOAD as POST, but if you need to use 'PUT' method your API call will fail and provide you 400, bad request.
Related
GetImages getImages = new GetImages();
getImages.execute(keys);
private class GetImages extends AsyncTask(String, Void, Void){
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(String... keys) {
for(String key : keys){
StorageReference referenceImage = FirebaseStorage.getInstance().getReference().child("images/"+key);
final long ONE_MB = 1024*1024;
referenceImage.getBytes(ONE_MB).addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(byte[] bytes) {
Toast.makeText(getApplicationContext(),"Success to Load Bitmap ....",Toast.LENGTH_LONG).show();
Bitmap bm = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
}
});
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
Toast.makeText(getApplicationContext(),"Completed All Tasks ............",Toast.LENGTH_LONG).show();
}
}
}
The problem with the code is that the AsyncTask executes onPostExecute() before completeing doInBackGround() . Completed All Tasks ... toast is showing before Success to load bitmap toast . I could not understand what the problem is .
Firebase method referenceImage.getBytes is asynchronous itself and you don't need to put it in an AsyncTask.For displaying Toast after getting images you can do:
referenceImage.getBytes(ONE_MB).addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(byte[] bytes) {
Toast.makeText(getApplicationContext(),"Success to Load
Bitmap....",Toast.LENGTH_LONG).show();
Bitmap bm = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
Toast.makeText(getApplicationContext(),"Completed All Tasks
............",Toast.LENGTH_LONG).show();
}
});
GetImages getImages = new GetImages();
getImages.execute(key);
Key must init in GetImages class
protected void onPostExecute(Void aVoid) {
Toast.makeText(getApplicationContext(),"Completed All Task .......",Toast.LENGTH_LONG).show();
}
Method run after doinbackground complete, you need return flag or data for mark complete method. Do not return NULL
I'm working on an Android app by adding a new functionality that fetch and save data with API calls.
These calls are made in a Fragment. There is a call made in an AsyncTask, and I don't want to create an AsyncTask for every call, so I just try send parameters to my controlles in some function, but when I debug every time I try to make a call without using an AsyncTask, I got an IOException "Cancelled". Is there a way to do this without using AsyncTasks in the same Fragment?
This is the AsyncTask:
private void validateUnit(#NonNull String unitCode, final int routeId, final boolean goodCondition) {
mUnitDetails = new UnitDetails();
if (mFindUnitAysncTask != null) {
mFindUnitAysncTask.cancel(true);
}
mFindUnitAysncTask = new AsyncTask<String, Void, FindUnitResponse>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgressDialog();
}
#Override
protected FindUnitResponse doInBackground(String... params) {
FindUnitResponse unitResponse = mUnitController.findUnit(params[0], routeId);
FindUnitDetailsResponse unitDetailsResponse = mUnitController.getUnitDetails(
unitResponse.getUnits().get(0), mUser);
if(unitDetailsResponse.isSuccess()) {
mUnitDetails.setBranchCode(unitDetailsResponse.getBranchCode());
mUnitDetails.setBranchName(unitDetailsResponse.getBranchName());
mUnitDetails.setCompanyId(unitDetailsResponse.getCompanyId());
mUnitDetails.setEconomicNumber(unitDetailsResponse.getEconomicNumber());
mUnitDetails.setFuelType(unitDetailsResponse.getFuelType());
mUnitDetails.setFuelTypeId(unitDetailsResponse.getFuelTypeId());
mUnitDetails.setFuelPrice(unitDetailsResponse.getFuelPrice());
mUnitDetails.setModel(unitDetailsResponse.getModel());
mUnitDetails.setBrand(unitDetailsResponse.getBrand());
mUnitDetails.setUnitType(unitDetailsResponse.getUnitType());
mUnitDetails.setRouteCode(unitDetailsResponse.getRouteCode());
mUnitDetails.setRealTrips(unitDetailsResponse.getRealTrips());
mUnitDetails.setMaximumMileageRange(unitDetailsResponse.getMaximumMileageRange());
}
else {
showMessage(unitDetailsResponse.getMessage());
}
return unitResponse;
}
#Override
protected void onPostExecute(FindUnitResponse response) {
super.onPostExecute(response);
dismissProgressDialog();
if (response != null && response.isSuccess()) {
//Unit unit = response.getUnits().get(0);
unit = response.getUnits().get(0);
finishChecklist(unit, goodCondition);
} else {
showMessage(response.getMessage());
saveChecklist();
}
}
#Override
protected void onCancelled() {
super.onCancelled();
dismissProgressDialog();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, unitCode);
}
With that I fetch the details of a vehicle. Then I have a method called validateMileage.
private void validateMileage(#NonNull Unit unit, #NonNull User user, #NonNull int mileage, int travels,
final boolean dayFinished) {
List<Incident> incidents = mIncidentController.getIncidentList();
Incident suspiciousMileageIncident = mIncidents.get(2);
List<Manager> managers = mManagersController.findByIncidentId(suspiciousMileageIncident.getId());
.....
}
If I just try to make calls like .getIncidentsList or .findByIncidentId I got an IOException when I wait for the response. But if I make the call in an AsyncTask, there is not errors.
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.
For my app I need to contact our API from our server which returns some JSON.
While downloading the JSON, it should display a progressbar.
I figured I should use Android's AsyncTask to handle the GUI while doing network operations, so I wrote the following within my Activity:
class DownloadManager extends AsyncTask<String, Void, Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mLoadingSpinner.setVisibility(View.VISIBLE);
}
#Override
protected Boolean doInBackground(String... params) {
String id = params[0];
downloadUtility.getId(id);
return true;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
mLoadingSpinner.setVisibility(View.INVISIBLE);
}
}
Basically, onPreExecute shows the loading spinner, the doInBackGround downloads some JSON, and onPostExecute stops the spinner.
The question is, within the downloadUtility.getId(id) I need to either:
Open a new intent if the download succeeded.
Stay on the same activity and display an error toast if the download failed.
The code for the getId:
public Future getId(final String id) {
// set url
String url = IPAddress.PRODUCTION + Variables.get_id+ id;
downloading = Ion.with(context)
.load("GET", url)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> response) {
//try catch here for null getHeaders
if (response != null) {
if (response.getHeaders().code() == 200) {
//SUCCESS !! Open new intent!
} else {
//FAIL!! Show TOAST!
}
}
}
});
return downloading;
}
As you can see, I'm returning a future object. How do I know from the future object if the onCompleted (void) either gave a success or fail, so I can handle the result (success: open new intent, fail: toast) in the asynctask?
Here you are running one asynctask inside another asyctask this is not a proper way you can call your getId method directly in your activity it won't be required another asynctask because the following code it self a asynctask.
downloading = Ion.with(context)
.load("GET", url)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> response) {
//try catch here for null getHeaders
if (response != null) {
if (response.getHeaders().code() == 200) {
//SUCCESS !! Open new intent!
} else {
//FAIL!! Show TOAST!
}
}
}
});
//Add new Answer
If you want to separate entire download code from your activity then you can create custom callBack in your download Utility class. It will acts like a communicator between activity and your Download class. I just give a way to do this task on bellow.
DownloadUtility class seams look like bellow
public class DownloadUtility {
//DO Your all other Stuff
/**
* Custom Callback
*/
public interface customCallBack {
void onCompleted(Exception e, Response<JsonObject> response);
}
/**
* Your getID code
*
* #param context
* #param id
* #param mLoadingSpinner
* #param callBack
*/
public static void getId(Activity context,final String id, Spinner mLoadingSpinner, final customCallBack callBack) {
// set url
mLoadingSpinner.setVisibility(View.VISIBLE);
String url = IPAddress.PRODUCTION + Variables.get_id + id;
downloading = Ion.with(context)
.load("GET", url)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> response) {
mLoadingSpinner.setVisibility(View.GONE);
if(callBack != null)
callBack.onCompleted(e,response);
}
}
});
}
}
make a call on your Activity
DownloadUtility.getId(this, "ID", spinnerObj, new DownloadUtility.customCallBack() {
#Override
public void onCompleted(Exception e, Response<JsonObject> response) {
if (response != null) {
if (response.getHeaders().code() == 200) {
//SUCCESS !! Open new intent!
} else {
//FAIL!! Show TOAST!
}
}
});
I don't think that you need AsyncTask for network operation because your ion library is already using asynctask internally.
you can do like this
mLoadingSpinner.setVisibility(View.VISIBLE);
downloading = Ion.with(context)
.load("GET", url)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> response) {
//try catch here for null getHeaders
if (response != null) {
if (response.getHeaders().code() == 200) {
//SUCCESS !! Open new intent!
mLoadingSpinner.setVisibility(View.INVISIBLE);
} else {
mLoadingSpinner.setVisibility(View.INVISIBLE);
}
}
}
});
return downloading;
let me know if some issue.
In my opinion the cleanest solution is to create a service that handles the dirty download logic and returns a future of your custom response class, that contains the success info and the json object.
// in e.g JsonResponse.java
public class JsonResponse() {
public boolean ok;
public JsonObject json;
}
// in Service.java
public Future<JsonResponse> getId(final String id) {
final SimpleFuture<JsonResponse> jsonFuture = new SimpleFuture<>();
String url = IPAddress.PRODUCTION + Variables.get_id + id;
Ion.with(context)
.load("GET", url)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> response) {
JsonResponse jsonResponse = new JsonResponse();
if (response != null) {
if (response.getHeaders().code() != 200) {
jsonResponse.ok = false;
} else {
jsonResponse.ok = true;
jsonResponse.json = response.getResult();
}
}
jsonFuture.setComplete(jsonResponse);
}
});
return jsonFuture;
}
// in Activity.java
private void loadUser(String userId) {
mLoadingSpinner.setVisibility(View.VISIBLE);
service.getId(userId)
.setCallback(new FutureCallback<JsonResponse>() {
// onCompleted is executed on ui thread
#Override
public void onCompleted(Exception e, JsonResponse jsonResponse) {
mLoadingSpinner.setVisibility(View.GONE);
if (jsonResponse.ok) {
// Show intent using info from jsonResponse.json
} else {
// Show error toast
}
}
});
}
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.