I am trying to download multiple files in listview with progressbar. What I achieved is, I can start a particular download, pause/resume it using AsyncTask and progress bar is updated(for single file), this part works well
My problem is I am not able to download multiple files simultaneously and when I leave the listview to another screen although my download is going on in the background but progress is not updated, progress bar shows 0 progress as if it is not downloading but its been downloading in the background.
Finally I found the answer which was much simpler than I thought, here it is as follows
Create a service having Asynctask for downloading and hashtable of values(url, Asynctask)
Pass the value(url, Asynctask) when a list item is clicked and check whether that hashtable contain the value already if yes cancel that Asynctask task if no add it to hashtable and start Asynctask
now for updating progress in my adapter I ran a thread which iterate over hashtable and passes the value using BroadcastListener.
And in activity intercept the broadcast and depending on the ListItem visible update the progress
PS: If anybody needs some code I can provide basic code of the description explained above
public class DownloadingService extends Service {
public static String PROGRESS_UPDATE_ACTION = DownloadingService.class.getName() + ".progress";
private static final long INTERVAL_BROADCAST = 800;
private long mLastUpdate = 0;
private Hashtable<String, DownloadFile> downloadTable;
private LocalBroadcastManager broadcastManager;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MessageEntity entityRecieved = (MessageEntity) intent.getSerializableExtra("ENTITY");
queueDownload(entityRecieved);
return super.onStartCommand(intent, flags, startId);
}
private void queueDownload(MessageEntity entityRecieved){
if (downloadTable.containsKey(entityRecieved.getPacketID())) {
DownloadFile downloadFile = downloadTable.get(entityRecieved.getPacketID());
if (downloadFile.isCancelled()) {
downloadFile = new DownloadFile(entityRecieved);
downloadTable.put(entityRecieved.getPacketID(), downloadFile);
startDownloadFileTask(downloadFile);
} else {
downloadFile.cancel(true);
downloadTable.remove(entityRecieved.getPacketID());
}
} else {
DownloadFile downloadFile = new DownloadFile(entityRecieved);
downloadTable.put(entityRecieved.getPacketID(), downloadFile);
startDownloadFileTask(downloadFile);
}
}
#Override
public void onCreate() {
super.onCreate();
downloadTable = new Hashtable<String, DownloadFile>();
broadcastManager = LocalBroadcastManager.getInstance(this);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
void startDownloadFileTask(DownloadFile asyncTask) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
asyncTask.execute();
}
private void publishCurrentProgressOneShot(boolean forced) {
if (forced || System.currentTimeMillis() - mLastUpdate > INTERVAL_BROADCAST) {
mLastUpdate = System.currentTimeMillis();
int[] progresses = new int[downloadTable.size()];
String[] packetIds = new String[downloadTable.size()];
int index = 0;
Enumeration<String> enumKey = downloadTable.keys();
while (enumKey.hasMoreElements()) {
String key = enumKey.nextElement();
int val = downloadTable.get(key).progress;
progresses[index] = val;
packetIds[index++] = key;
}
Intent i = new Intent();
i.setAction(PROGRESS_UPDATE_ACTION);
i.putExtra("packetIds", packetIds);
i.putExtra("progress", progresses);
mBroadcastManager.sendBroadcast(i);
}
class DownloadFile extends AsyncTask<Void, Integer, Void> {
private MessageEntity entity;
private File file;
private int progress;
public DownloadFile(MessageEntity entity) {
this.entity = entity;
}
#Override
protected Void doInBackground(Void... arg0) {
String filename = entity.getMediaURL().substring(entity.getMediaURL().lastIndexOf('/') + 1);
file = new File(FileUtil.getAppStorageDir().getPath(), filename);
downloadFile(entity.getMediaURL(), file);
return null;
}
public String downloadFile(String download_file_path, File file) {
int downloadedSize = 0;
int totalSize = 0;
try {
// download the file here
while ((bufferLength = inputStream.read(buffer)) > 0 && !isCancelled()) {
progress = percentage;
publishCurrentProgressOneShot(true);
}
} catch (final Exception e) {
return null;
}
return file.getPath();
}
}
On big problem with AsynchTask is when you finish its activity, AsynchTask looses it's track with your UI. After that when you return back to that activity the progressBar is not updating even if the download progress still running in background. In fact that AsynchTask is not belong to the new Activity you lunched so the new instance of progress bar in new Activity will not updating.
To fix this problem I suggest you:
1- Run a thread with a timerTask in onResume() which updates ur progressbar with values updating from the AsyncTask running background. Something like this:
private void updateProgressBar(){
Runnable runnable = new updateProgress();
background = new Thread(runnable);
background.start();
}
public class updateProgress implements Runnable {
public void run() {
while(Thread.currentThread()==background)
try {
Thread.sleep(1000);
Message msg = new Message();
progress = getProgressPercentage();
handler.sendMessage(msg);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
}
}
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
progress.setProgress(msg.what);
}
};
and when your activity is not visible you must destroy the thread:
private void destroyRunningThreads()
{
if(background!=null)
{
background.interrupt();
background=null;
}
}
2- Define a global static boolean variable. Set it true in onPreExecute and in onPostExecute set it to false. It shows that you are downloading or not, so you can check if the variable is equal to true, show the previous progressbar dialog.(you can do something like this with an integer value-or array of integers- in order to show the update percentage for each download progress).
3- The last way I personally used is to show the download progress in Notification Bar and in my list view I just show that it is downloading right now or not.(using 2nd method with a boolean values). In this way even if you finish the activity the notification bar is still updated with download progress.
when you leave your activity, the activity that asynctask shows the progressbar is killed and thus the progressBar dose not show anymore when you come back on new activity because the asynctask dose not aware of your new activity.
General solution that will work in any cases for example when your user closes your app and again opens it and wants to know the progressBar is separating your presentation completely. that means you can create sharedPreferences or database table and put your state of your file in to it while your asynctask is downloading. for example every 500 milisecond update the sharedPreferences or database table with how much downloaded from total file size. then when user come back to your new activity you read from DB or sharedPreferences to show progressBar and update it every for example 1000 milisecond. In this way your user will know the progressBar even if he closes the app and opens it again. I know it takes a bit more work but it surely makes your users be happy.
in order to read and update at fixed rate you can use scheduleAtFixedRate
Related
I have done my research very thoroughly with no actual result so here I am.
I have a horizontal ProgressBar in my app which I use to indicate a progress in file upload. When I upload a whole directory though, I am trying to make it show progress of single files uploaded at the time. I use asynctasks with a FixedThreadPool(1). The thing is, that only the first task triggers the progressbar.
The method in main activity:
uploadExecutor = Executors.newFixedThreadPool(1);
private void upload() throws DropboxException, IOException {
if(isDir){
DataDir dir = new DataDir(file);
List<File> files = dir.getFileList();
for(File item : files){
Upload upload = new Upload(getActivity(), dropbox, "/Apps/Sink/", item, bar);
upload.executeOnExecutor(uploadExecutor);
}
}
else {
Upload upload = new Upload(getActivity(), dropbox, "/Apps/Sink/", file, bar);
upload.executeOnExecutor(uploadExecutor);
}
}
Upload is a class that implements AsyncTask and handles the upload of the file.
When created, the instance of the class sets the bar to be visible and in OnPostExecute() sets it to be invisible
EDIT
Adding the Upload class.
public Upload(Context context, DropboxAPI<?> api, String dropboxPath,
File file, ProgressBar mBar) {
this.mBar = mBar;
mBar.setProgress(0);
mBar.setVisibility(View.VISIBLE)
#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;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
//mDialog.setProgress(percent);
mBar.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
showToast("File successfully uploaded");
} else {
showToast(mErrorMsg);
}
mBar.setVisibility(View.INVISIBLE);
}
EDIT
I resolved the issue by moving the for cycle into the upload class.
Very similar approach HERE
In your Upload class you can implement the method for AsynkTak that checks for progress status changes
protected void onProgressUpdate(Integer... progress) { /Your code/ }
http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)
The problem you have is that you initialize one AsyncTask per file and give each of them a reference to the same ProgressBar.
What happens is, you loop through the files and init the AsyncTasks. Now if the first task finishes the bar will be set to invisible. The following tasks aren't able to set it visible again with your current setup.
You can try to set the bar visible in onPostExecute() of the AsyncTask, because this one will be invoked before doInBackground() kicks in. Or you can trigger the onProgreesUpdate() at the beginning of doInBackground() to make it visible there.
I have an application that uses IntentService to run a background task where I pull data from a website, parse the data out, and create calendar events based on the results. Everything seems to be working create, except I'm running into an issue with rotation.
Using the code below, when I rotate the screen, the ProgressDialog box stays visible, but is never updated with new text when the process is updated, and never goes away once the call is completed. I'm using an IntentService instead of an ASyncTask because the user can also schedule the IntentService to run at other times without having to interface with the app. Any help is appreciated, thanks!
public void onCreate(Bundle savedInstanceState) {
Object retained = getLastNonConfigurationInstance();
if (retained instanceof CalendarHandler) {
// CH is a class level variable defined at the top which references my IntentService, aptly named CalendarHandler
ch = (CalendarHandler) retained;
ch.setActivity(this);
} else {
ch = null;
}
activity = this;
btnLogin.setOnClickListener(OnClickListener(View view) {
ch = new CalendarHandler();
ch.setActivity(MyTlc.this);
// Do other stuff, like run the intent service
}
}
public Handler handler = new Handler() {
public void handleMessage(Message message) {
// We read the information from the message and do something with it
// based on what the result code is
String result = message.getData().getString("status");
if (result.equals("ERROR")) {
activity.removeDialog(PROGRESS_DIALOG);
results.setText(message.getData().getString("error"));
} else if (result.equals("DONE")) {
activity.removeDialog(PROGRESS_DIALOG);
int count = message.getData().getInt("count", 0);
activity.results.setText("Added " + count + " shifts to the calendar");
} else {
activity.pDialog.setMessage(result);
}
super.handleMessage(message);
}
};
From what I understand, this should work, and like I said the ProgressDialog box does stay properly, I just can't seem to pass information to the dialog box after rotating.
I am working on a Download Manager project, so, to show all downloaded / downloading actions, i prefer to use ListView to show my download list. Suppose that, we have as many as downloading task, so, the progress bars of all tasks must be updated. For background download task, i created a new class that i named it HttpDownloader. So, i pass these progress bars on objects of this class. When a new object is added to my tasklist, so, i call the constructor of HttpDownloader and pass the new item progress bar to it. The thing confused me is When i add a new object to tasklist and call notifyDataSetChanged of adapter, my list is refreshed, so all progress bar reset to default layout values but HTTPDownloader Thread is running in background successfully. So, it is my question that,
1. After calling notifyDataSetChanged, references to old listview's objects are destructs ?
2. If yes, How can i keep old view's reference ?
3. If no, please explain me, why progress bars reset to default and do not change when background process force to passed progressbar to change the value of progress ?
HTTPDownloader class
class HttpDownloader implements Runnable {
public class HttpDownloader (String url, ProgressBar progressBar)
{
this.M_url = url;
this.M_progressBar = progressBar;
}
#Override
public void run()
{
DefaultHttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(this.M_url);
HttpResponse response;
try{
response = client.execute(get);
InputStream is = response.getEntity().getContent();
long contentLength = response().getEntity().getContentLength();
long downloadedLen = 0;
int readBytes = 0;
byte [] buffer = new byte [1024];
while ((readBytes = in.read(buffer, 0, buffer.length)) != -1) {
downloadedLen += readBytes;
//Some storing to file codes
runOnUiThread(new Runnable() {
#Override
public void run() {
M_progressBar.setProgress((100f * downloadedLen) / contentLength);
}
});
}
is.close();
} catch (ClientProtocolException e) {
Log.e("HttpDownloader", "Error while getting response");
} catch (IOException e) {
Log.e("HttpDownloader", "Error while reading stream");
}
}
}
AdapterClass
class MyAdapter extends ArrayAdapter<String> {
ArrayList<String> M_list;
public MyAdapter(ArrayList<String> list) {
super(MainActivity.this, R.layout.download_item, list);
this.M_list = list;
}
#Override
public int getCount() {
return this.M_list.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.download_item, parent, false);
ProgressBar bar = (ProgressBar) rowView.findViewById(R.id.progrees);
new Thread (new HttpDownloader(this.M_list.get(position), bar)).start();
return rowView;
}
}
Well if you want to keep the references to show a good download manager, lets see how do it, go by parts.
The concept is easy to understand, we have threads downloading items, we are going to call each of this piece of work tasks. Each task is associated with a row in the list view, because you want to show a download progress of each item download.
So if each task is associated with each row, we are going to save tasks actually are in execution, in this way, we know in all moment what tasks are running and their state. This is importante because, like I have said before, getView() method is called many times, and we need to know each download in progress and its state.
Lets see some code of our Adapter:
class MyAdapter extends ArrayAdapter<Uri> {
ArrayList<Uri> M_list;
Map<Uri, HttpDownloader> taskMap;
public MyAdapter(ArrayList<Uri> list) {
super(MainActivity.this, R.layout.download_item, list);
this.M_list = list;
taskMap = new HashMap<Uri, HttpDownloader>();
}
#Override
public int getCount() {
return this.M_list.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.download_item, parent, false);
ProgressBar progressBar = (ProgressBar) rowView.findViewById(R.id.progressBar);
configureRowWithTask(position, progressBar);
return rowView;
}
private void configureRowWithTask(int position,final ProgressBar bar) {
Uri url = M_list.get(position);
HttpDownloader task;
if (!(taskMapHasTaskWithUrl(url))) {
task = new HttpDownloader(url, bar);
Thread thread = new Thread(task);
thread.start();
taskMap.put(url, task);
} else {
task = taskMap.get(url);
bar.setProgress(task.getProgress());
task.setProgressBar(bar);
}
}
private boolean taskMapHasTaskWithUrl(Uri url) {
if (url != null) {
Iterator taskMapIterator = taskMap.entrySet().iterator();
while(taskMapIterator.hasNext()) {
Map.Entry<Uri, HttpDownloader> entry = (Map.Entry<Uri, HttpDownloader>) taskMapIterator.next();
if (entry.getKey().toString().equalsIgnoreCase(url.toString())) {
return true;
}
}
}
return false;
}
}
Some explanations about it:
I have changed your type of adapter to ArrayAdapter of Uris to work better with links.
I have added a Map wich has pairs key-value, keys are Uris and values are HttpDownloaders. This map will save each task in use.
I have added two important methods, one is configureRowWithTask(), like its own name says configures a row with a task, associating them, but only if the task is new, in other case is a task in use.
The other method is taskMapHasTaskWithUrl(), simply checks if the given task (by its url) is currently in the taskMap.
Probably, the most important method is configureRowWithTask(), I am going to explain it deeply.
configureRowWithTask() method checks if one task is in use, this method is needed because getView() is called many times, but we dont want the same downloading task be executed more than once, so this method checks that, if the task is new (not present in the taskMap) then creates a new instance of HttpDownloader and put the new task in the map.
If the task requested is present in the taskMap, it means that the task has been requested previously but the row in the list has gone out and there have been a new call to getView() method. So the task is present, we dont have to create it again, probably the task is downloading the item and the only thing we have to do is see its download progress and set it to the row's progress bar. And finally sets the reference to the progress bar, probably the HttpDownloader has lost this reference.
With this part clear, we go with the second part, the HttpDownloader class, lets see some code:
public class HttpDownloader implements Runnable {
private Uri url;
private ProgressBar progressBar;
private int progress = 0;
private Handler handler;
public HttpDownloader (Uri url, ProgressBar progressBar) {
this.url = url;
this.progressBar = progressBar;
progressBar.setProgress(progress);
handler = new Handler();
}
#Override
public void run() {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url.toString());
HttpResponse response;
try {
response = client.execute(get);
InputStream is = response.getEntity().getContent();
long contentLength = response.getEntity().getContentLength();
int downloadedLen = 0;
int readBytes = 0;
byte [] buffer = new byte [1024];
while ((readBytes = is.read(buffer, 0, buffer.length)) != -1) {
downloadedLen += readBytes;
//Some storing to file codes
progress = (int) ((100f * downloadedLen) / contentLength);
handler.post(new Runnable() {
#Override
public void run() {
if (progressBar != null) {
progressBar.setProgress(progress);
}
}
});
}
} catch (ClientProtocolException e) {
Log.e("HttpDownloader", "Error while getting response");
} catch (IOException e) {
e.printStackTrace();
Log.e("HttpDownloader", "Error while reading stream");
}
}
public int getProgress() {
return progress;
}
public void setProgressBar(ProgressBar progressBar) {
this.progressBar = progressBar;
}
}
This class is basically the same, the diference is that I use a Handler to change the progress of the progress bar in the UI thread, and change this progress only if the reference to the progress bar is not null.
Important thing is every time bytes are downloaded, value of download progress is refreshed.
I have checked the code in a test app and seems that all runs ok, if you have some problems, let me know and I will try to help you ; )
Hope you understand it.
when you call notifyDataSetChanged() or Activity resumes, getView() method of the Adapter is called by each row of the list.
So, when you add new item to the list and call notifyDataSetChanged(), getView() method is executed as many times as items are in the list in that moment, plus one more cause the new item you have added.
Like you know, getView() method builds the row, so builds a new ProgressBar, and obvioulsy this ProgressBar begins at position 0 of progress.
So the answer could be resumed as yes, each time you call notifyDataSetChanged(), getView() method is called many times, one for each row (if you set android:layout_height param to 0dip and android:layout_weight to 1.0, like you probably know for ListViews), thats the reason why you get ProgressBars "initialized" when you add new item to the ListView.
Iv'e got an Android app that is using a list activity to display a list of items pulled from the internet. I First use an AsyncTask to load the list and that Async task finishes it calls a different async task to start loading the thumbnail pictures that go along with the list items. The problem I am having is that the user has access to a refresh button that they can press at any time and when it is pressed, the whole list of items is delete and the loading starts over. The Async task that loads the thumbnails could potentially still be running if this happens and may try to add a thumbnail to a non existing list item then. Iv'e tried synchronizing on the list, using a Boolean which after researching I realized would not work. I have also tried using a static atomic boolean to check if refresh has been hit to cancel the thumbnail loader. Any ideas?
public class LoadItems extends AsyncTask<Void, Void, Boolean> {
private Activity activity;
private static boolean loading = false;
public static final AtomicBoolean refreshing = new AtomicBoolean(false);
private static final String TAG = "LoadItems";
private int start;
private List<ListItem> items;
public LoadItems(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
loading = true;
start = ItemViewer.itemList.size();
}
#Override
protected Boolean doInBackground(Void... arg0) {
items = WebFunctions.getMoreItems(activity);
return (items != null);
}
protected void onPostExecute(Boolean success) {
if (success) {
for (ListItem item: items) {
ItemViewer.itemList.add(item);
Log.d(TAG, "added item " + item.getTitle());
}
LoadThumbnails thumbnailLoader = new LoadThumbnails();
thumbnailLoader.execute(start, ItemViewer.itemList.size());
}
loading = false;
}
public void protectedExecute() {
if (!loading)
execute();
}
public void refresh() {
if (!refreshing.getAndSet(true)) {
WebFunctions.reset();
ItemViewer.itemList.removeAllItems();
execute();
}
}
}
public class LoadThumbnails extends AsyncTask<Integer, Void, Drawable> {
private int position;
private int end;
#Override
protected Drawable doInBackground(Integer... params) {
position = params[0];
end = params[1];
Drawable thumbnail = null;
synchronized(ItemViewer.itemList) {
if (LoadItems.refreshing.get())
cancel(true);
String url = ItemViewer.itemList.get(position).getThumbnailUrl();
if (!url.isEmpty())
thumbnail = WebFunctions.loadDrawableFromUrl(ItemViewer.activity, url);
}
return thumbnail;
}
protected void onPostExecute(Drawable d) {
synchronized (ItemViewer.itemList) {
if (LoadItems.refreshing.get())
cancel(true);
if (d != null)
ItemViewer.itemList.setThumbnail(position, d);
position++;
if (position < end) {
LoadThumbnails lt = new LoadThumbnails();
lt.execute(position, end);
}
}
}
}
This is pretty simple to solve. Whenever the user hits the refresh button, make sure you call cancel() on the last async tasks you have created before you create new tasks. For example,
private void onRefreshClick(View v) {
if(mLastLoadItemTask != null) mLastLoadItemTask.cancel(true);
if(mLastLoadThumbnailTask != null) mLastLoadThumbnailTask.cancel(true);
mLastLoadItemTask = new LoadItems(...);
mLastLoadItemTask.execute();
}
Then, in the onPostExecute of each of your async tasks, first check to see if they were cancelled by calling isCancelled(). If they were cancelled, make sure the onPostExecute method does no work by just returning. For example,
protected void onPostExecute(...) {
if(isCancelled()) return;
//Adding items to list
//Or start load thumbnail task
}
As you can see that should prevent any unintentional or stale updates because the onPostExecute methods and your cancel calls will all happen on the main therad. The last thing I would suggest is to alter your loadThumbs task to be able to stop doing work as soon as possibly by checking isCancelled() whenever it makes sense to do so.
The following steps might help:
cache the results, whatever you have previously pulled from the net should be saved and quickly restored back when your application is launched. this way you avoid long delays and empty screens on application startup, which, in turn, stops the user from pressing 'reload'
make a boolean variable reload_in_progress, set it to true when you start pulling data from the net, and set it to false when all thumbnails are ready. 'reload' click handler should ignore clicks when reload_in_progress is true.
show some king of progress bar to the user, so (s)he knows it's already reloading and does not push reload again.
almost forgot, never update data shown to the user "live", this leads to wonderful situations, when the user clicks on item while it's changing and doing something completely different from what (s)he expected. long updates should keep its data to themselves and quickly swap old data for the new one only when everything is ready.
I'm trying to display a series of images from a specific folder in sdcard - in the form of slideshow. filelist[] contains names of all files present in that directory.
I'm filtering out the images here. Next, thread.sleep(1000) does not seem to have any effect. Only the last image in the directory is displayed after a time of 1000ms. Where am I going wrong? Any other way I could accomplish this?
Maybe I've gone completely wrong. I'm a newbie so plz help.
public class List_imgActivity extends Activity {
/** Called when the activity is first created. */
Bitmap[] bitmapArray = new Bitmap[1000];
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button pf=(Button) findViewById(R.id.pick_button);
pf.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Intent intent = new Intent("org.openintents.action.PICK_DIRECTORY");
intent.setData(Uri.parse("file:///sdcard"));
intent.putExtra("org.openintents.extra.TITLE", "Please select a folder");
intent.putExtra("org.openintents.extra.BUTTON_TEXT", "Use this folder");
startActivityForResult(intent, 1);
}
});
}
protected void onActivityResult(int requestCode, int recievecode, Intent intent)
{
if (requestCode == 1 )
{
Uri uri = intent.getData();
try {
File f=new File(new URI(uri.toString()));
final String nx=f.toString();
if(f.isDirectory()) {
File filelist[] = f.listFiles();
for(int i=0;i<filelist.length;i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String filename = filelist[i].getName();
int pos = filename.lastIndexOf(".");
String ext = filename.substring(pos);
if(ext.equals(".jpg"))
{
TextView tv1= (TextView) findViewById(R.id.textView1);
tv1.setText(filelist[i].toString());
ImageView iv1=(ImageView) findViewById(R.id.imageView1);
bitmapArray[i] = BitmapFactory.decodeFile(filelist[i].toString());
iv1.setImageBitmap(bitmapArray[i]);
}
}
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In Android behaviour like this will make the UI-Thread sleep. This will freeze the whole UI of the phone your App will look crashed to the user and the System will automatically kill your application after a while.
There is a mechanism to change things in specific time intervalls. You should use this handlers for doing this. Handlers
A handler has a postDelayed and sendMessageDelayed methods that allow you to either build a Runnable that will be executed after a certain time or send a message that must be handled by the implementation of your handler.
The initialization of the handler would look something like this:
showNextImageHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
showNextImage();
}
};
showNextImageHandler.sendMessageDelayed(showNextImageHandler.obtainMessage(), 1000);
This code creates a new handler that calls the function showNextImage every time it receives a message. I would store the Handler in an instance variable of your activity to send further messages later on. After the handler is created a first empty message is send in a way that will delay the posting of the message 1000 milliseconds. After a second the showNextImage function will be called. In this function you can change the view and if a next image exists you can post another delayed message to trigger another call to the function later on.
U Must synchronise the current object before applying Thread.sleep() method