I have a group of images that users upload in my app. I store the image path in an sqlite database and the image in the internal storage of the app.
I was able to go around deleting a single image if the user selects it and chooses to delete it. My problem now is that I have a clear all button sort of, that is meant to clear a particular group of images. How do I loop around this?
Here I have made a asynTask class for deleting multiple files at once.
private class DeleteFilesAsync extends AsyncTask<String, Integer, Integer> {
ProgressDialog mProgressDialog;
ArrayList<String> fileNames = new ArrayList<String>();
public DeleteFilesAsync(ArrayList<String> fileNames) {
this.fileNames = fileNames;
}
#Override
protected void onPreExecute() {
try {
mProgressDialog = new ProgressDialog(
SavedImageListingActivity.this);
mProgressDialog.setMessage("deleting...");
mProgressDialog.show();
} catch (Exception e) {
// TODO: handle exception
}
super.onPreExecute();
}
#Override
protected Integer doInBackground(String... params) {
for (int i = 0; i < fileNames.size(); i++) {
String fileName = fileNames.get(i);
File file = new File(fileName);
if (file.exists()) {
if (file.isFile()) {
file.delete();
onProgressUpdate(i);
}
}
}
return null;
}
#Override
protected void onPostExecute(Integer result) {
try {
mProgressDialog.dismiss();
} catch (Exception e) {
// TODO: handle exception
}
// Do more here after deleting the files
super.onPostExecute(result);
}
}
How to use it
new DeleteFilesAsync(imgFilesSelected).execute("");
Where imgFilesSelected is type ArrayList<String>
Add all files path in imgFilesSelected list like
imgFilesSelected.add("my_path_dir/filename.jpg");
imgFilesSelected.add("my_path_dir/filename2.png");
imgFilesSelected.add("my_path_dir/filename3.png"); // etc
then pass it to DeleteFilesAsync() class contructor as shown above.
All done.
Related
what i have is a grid view and i open the images online . but what i need to do is when the user open the app .. all of those images to be downloaded in the mobile phone automatically so when the user open the app again it will show up from the memory not online ..
please any help?? and what i have is 250 images maybe
and is there any other so i can call my images dynamically instead of calling them one by one??
here is an example of how i call my images:
private String urls[] = {
"http://transition-se.com/training_may/foodribbons.JPG",
"http://transition-se.com/training_may/clothribbon.JPG",
"http://transition-se.com/training_may/shoesribbon.JPG",
"http://transition-se.com/training_may/bagsribbon.JPG",
"http://transition-se.com/training_may/viewsribbon.JPG",
"http://transition-se.com/training_may/makeupribbon.JPG",
"http://transition-se.com/training_may/roomribbon.JPG",
"http://transition-se.com/training_may/watchesribbon.JPG"
};
You can do it like a hard way, or you can do it easy way.
You can make symple Asynk task and load images to files on your device.
Example:
private class Downloader extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
// show dialog loading here
}
#Override
protected Integer doInBackground(String... params) {
// for loop here
for(int i=0; i<params.lenght; i++) {
try {
URL url = new URL(params[i]);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream( file name here );
// add this file to global list, so you can used it after
byte[] b = new byte[1024];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
return 1;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
#Override
protected void onProgressUpdate(Void... values) {
// update loading dialog precents
}
#Override
protected void onPostExecute(Integer result) {
// hide loading dialog
if (result == 1) {
// all images loaded to files
}
}
}
Or you can use out of the box libs for this operation which i prefer, try this Picasso Asynk image loader, it will handle complex operation for you
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.
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.
In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.
If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.
Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):
#EActivity(R.layout.layout_splash)
#RoboGuice
public class SplashScreenActivity extends Activity {
#Inject
private AvtopoiskParserImpl parser;
#Bean
BrandsAndRegionsHolder brandsAndRegionsHolder;
#ViewById(R.id.splash_progress)
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
}
#Background
protected void loadData() {
publishProgress(10);
LinkedHashMap<String, Integer> brands = null;
try {
brands = parser.getBrands();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(50);
LinkedHashMap<String, Integer> regions = null;
try {
regions = parser.getRegions();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(70);
populateData(brands, regions);
}
#UiThread
protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
brandsAndRegionsHolder.brandsMap = brands;
brandsAndRegionsHolder.regionsMap = regions;
publishProgress(100);
startActivity(intent);
finish();
}
#UiThread
void publishProgress(int progress) {
progressBar.setProgress(progress);
}
}
parser.getBrands() and parser.getRegions() are loading data from the web.
I want to do something like this:
boolean repeatRequest = true;
while (repeatRequest) {
try {
brands = parser.getBrands();
repeatRequest = false;
} catch (IOException e) {
Log.e(e.getMessage());
repeatRequest = showErrorDialog();
}
}
But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread.
I believe that it should be standard approach of doing so, but didn't manage to find it.
Any ides how can I implement this?
The best way is to use AsyncTask.
private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
private ProgressDialog mProgress;
protected Object doInBackground(Void... params) {
// This method runs in background
Object result = null;
try {
result = parser.parse();
} catch (Exception e) {
result = e.getMessage();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
// This method runs in UI thread
mProgress.setProgress(progress[0]);
}
protected void onPreExecute() {
// This method runs in UI thread
mProgress = new ProgressDialog(context);
mProgress.show();
}
protected void onPostExecute(Object result) {
// This method runs in UI thread
mProgress.dismiss();
if (result instance of String) {
// Here you can launch AlertDialog with error message and proposal to retry
showErrorDialog((String) result);
} else {
populateData(result);
}
}
}
This is my AsyncTask, called from getView of an adapter:
class LoadImage extends AsyncTask<Object,Void,String>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
}
Bitmap userAvatarStream = null ;
Bitmap IconStream = null;
URL IconURL;
ProgressDialog dialog;
#Override
protected void onPreExecute(){
//Setting all the variables by getting the ids from the layout
return;
}
#Override
protected String doInBackground(Object... params) {
try {
IconURL = new URL(cr.ImageUrl);
IconStream = BitmapFactory.decodeStream(IconURL.openConnection().getInputStream());
}
catch (MalformedURLException e){
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result){
// ImageView user_avatar = (ImageView)v.findViewById(R.id.follower_user_avatar);
imv.setImageBitmap(IconStream);
return;
}
The problem that I get here is that the images keep loading. Lets say I scroll down and the images go away to be refreshed again if I scroll up the list. It keeps making calls to get the images. This behaviour is obviously undesirable except at one place that if the internet on your cell-phone goes down and comes up again, this would help to auto-load the images. But, in the current state even that is crashing as it keeps making calls. How to stop AsyncTask from doing that?
Just cache you images to filesystem or memory.
Each time you scroll the list getView is called. If you put the image loading method on getView and didn't use Image Caching then it'll download the images again and again. There are some opensource image loader for list with caching support.
One of them is droidFu. It supports two level of caching. Filesystem and memory. Get droidFu from following link.
https://github.com/kaeppler/droid-fu
Try a boolean flag to keep the check whether the image was loaded successfully or not.
If it was not then only make a call to Load Image Asynctask.
You may need to use a boolean array to keep the track if there are more than one row in adapter.
Try this code:
class performBackgroundTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog.setMessage("Please wait ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... arg0) {
callxmlparser();
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (ringtoneNamelist != null && ringtoneNamelist.size() > 0) {
songslist.setAdapter(new Songslist());
} else {
Toast.makeText(SongsList.this,"Network signal speed is too slow\ncannot parse the data from the server\n Please try again", Toast.LENGTH_LONG).show();
}
dialog.dismiss();
}
}