Need Help in Downloading in Background Images in Android?

25,699

Solution 1

The best way to download it using the service like i have done to download the file from server and put in SD card also use the notification for it. It is quite long code but i think the perfect one,if did not understand any thing then please go to android developer blog for services.

public class DownloadService extends Service{

     SharedPreferences preferences;

    private static final String DOCUMENT_VIEW_STATE_PREFERENCES = "DjvuDocumentViewState";

      private Looper mServiceLooper;
      private ServiceHandler mServiceHandler;
      private NotificationManager mNM;
      String downloadUrl;
      public static boolean serviceState=false;

      // Handler that receives messages from the thread
      private final class ServiceHandler extends Handler {
          public ServiceHandler(Looper looper) {
              super(looper);
          }
          @Override
          public void handleMessage(Message msg) {
              downloadFile();
              showNotification(getResources().getString(R.string.notification_catalog_downloaded),"VVS");
              stopSelf(msg.arg1);
          }
      }


    @Override
        public void onCreate() {
            serviceState=true;
            mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
            HandlerThread thread = new HandlerThread("ServiceStartArguments",1);
            thread.start();

            // Get the HandlerThread's Looper and use it for our Handler 
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);

        }



     @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
             Log.d("SERVICE-ONCOMMAND","onStartCommand");  

               Bundle extra = intent.getExtras();
               if(extra != null){
                   String downloadUrl = extra.getString("downloadUrl");
                   Log.d("URL",downloadUrl);

                   this.downloadUrl=downloadUrl;
               }

              Message msg = mServiceHandler.obtainMessage();
              msg.arg1 = startId;
              mServiceHandler.sendMessage(msg);

              // If we get killed, after returning from here, restart
              return START_STICKY;
          }



     @Override
          public void onDestroy() {

             Log.d("SERVICE-DESTROY","DESTORY");
             serviceState=false;
            //Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
          }


     @Override
      public IBinder onBind(Intent intent) {
          // We don't provide binding, so return null
          return null;
      }


      public void downloadFile(){

            downloadFile(this.downloadUrl,fileName);


      }



        void showNotification(String message,String title) {
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = message;

        // Set the icon, scrolling text and timestamp
       Notification notification = new Notification(R.drawable.icon, "vvs",
                System.currentTimeMillis());
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        Intent intent = new Intent(this, HomeScreenActivity.class);
        intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
         //The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this.getBaseContext(), 0,
              intent, PendingIntent.FLAG_CANCEL_CURRENT);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, title,
                      text, contentIntent);
        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
        mNM.notify(R.string.app_name, notification);
    }

  public void downloadFile(String fileURL, String fileName) {

    StatFs stat_fs = new StatFs(Environment.getExternalStorageDirectory().getPath());
    double avail_sd_space = (double)stat_fs.getAvailableBlocks() *(double)stat_fs.getBlockSize();
    //double GB_Available = (avail_sd_space / 1073741824);
    double MB_Available = (avail_sd_space / 10485783);
    //System.out.println("Available MB : " + MB_Available);
    Log.d("MB",""+MB_Available);
   try {
        File root =new File(Environment.getExternalStorageDirectory()+"/vvveksperten");
        if(root.exists() && root.isDirectory()) {

        }else{
            root.mkdir();
        }
        Log.d("CURRENT PATH",root.getPath());
        URL u = new URL(fileURL);
        HttpURLConnection c = (HttpURLConnection) u.openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.connect();
          int fileSize  = c.getContentLength()/1048576;
          Log.d("FILESIZE",""+fileSize);
          if(MB_Available <= fileSize ){
               this.showNotification(getResources().getString(R.string.notification_no_memory),getResources().getString(R.string.notification_error));
              c.disconnect();
              return;
          } 

        FileOutputStream f = new FileOutputStream(new File(root.getPath(), fileName));

        InputStream in = c.getInputStream();


        byte[] buffer = new byte[1024];
        int len1 = 0;
        while ((len1 = in.read(buffer)) > 0) {
            f.write(buffer, 0, len1);
        }
        f.close();
        File file = new File(root.getAbsolutePath() + "/" + "some.pdf");
        if(file.exists()){
            file.delete();
            Log.d("FILE-DELETE","YES");
        }else{
            Log.d("FILE-DELETE","NO");
        }
        File from =new File(root.getAbsolutePath() + "/" + fileName);
        File to = new File(root.getAbsolutePath() + "/" + "some.pdf");


        } catch (Exception e) {
        Log.d("Downloader", e.getMessage());

    }

Solution 2

For anyone running into this question later, take a look at the async download mechanism used in the android sample code for the project com.example.android.bitmapfun.ui.ImageGridActivity. It downloads images asynchronously and also caches them for offline display in an ImageView. Folks have wrapped their code around this one and made image loading libraries of their own. These libraries use an AsyncTask instead of a service. Async tasks are expected to wrap up their work within a couple of seconds.

If you are looking to download something larger, I'd recommend the DownloadManager that is available since API 9 instead of using services. There is a lot of code in there that adds resilience to the download.

The download manager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots. Instances of this class should be obtained through getSystemService(String) by passing DOWNLOAD_SERVICE. Apps that request downloads through this API should register a broadcast receiver for ACTION_NOTIFICATION_CLICKED to appropriately handle when the user clicks on a running download in a notification or from the downloads UI. Note that the application must have the INTERNET permission to use this class.

Solution 3

You are probably over engineering this. I have implemented swiping with dynamically loading images and I just a use a simple utility class that does it all for me via static method call. Try this class:

package com.beget.consumer.util;

/*
 Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.    
*/
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

public class DrawableLoader {
    private final Map<String, Drawable> drawableMap;
    private WeakReference<ImageView> imageViewReference;

    public DrawableLoader() {
        drawableMap = new HashMap<String, Drawable>();
    }

    public Drawable fetchDrawable(String urlString) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        try {
            InputStream is = fetch(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");
            drawableMap.put(urlString, drawable);
            Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                    + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                    + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
            return drawable;
        } catch (MalformedURLException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        }
    }

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {

        imageViewReference = new WeakReference<ImageView>(imageView);

        if (drawableMap.containsKey(urlString)) {
            imageViewReference.get().setImageDrawable(drawableMap.get(urlString));
        }

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                imageViewReference.get().setImageDrawable((Drawable) message.obj);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
                Drawable drawable = fetchDrawable(urlString);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }

    private InputStream fetch(String urlString) throws MalformedURLException, IOException {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);
        return response.getEntity().getContent();
    }

}

This is all you need. Then when you need to load an image, you call:

fetchDrawableOnThread("http://path/to/your/image.jpg", yourImageViewReference);

That's it.
If you have an URL from a JSON object, parse the URL into your string so:
String url = jsonObj.getString("url"); Then call fetchDrawableOnThread(url, yourImageViewReference);

Share:
25,699
Sankar Ganesh PMP
Author by

Sankar Ganesh PMP

Professionally I am a Software Engineer ,apart from that I am also a Guitarist &amp; occasionally I wrote some poems. **Youtube link: https://www.youtube.com/c/SankarGaneshImperativeConqueror ** Skype id : sankarganesh.s Gmail Address: [email protected] Software Blog Link: http://sankarganesh-info-exchange.blogspot.com/ My Poem Blog Link: http://sankarganeshpoemworld.blogspot.in/

Updated on August 11, 2022

Comments

  • Sankar Ganesh PMP
    Sankar Ganesh PMP over 1 year

    I have an image view , i had written swiping , at that time of swiping,the images are downloading from Internet, so i thought i have to download the images in the background before swiping , for that which i need to use asynctask or Service or IntentService, all these will help in downloading and storing in data/data/mypackages , but still swiping gets slow in my case any idea, also convey me which one is best one, is it i'm calling in a right way

    1. asynctask

    2. services

    3. Intent Service as shown below,

    i m confused which one is right method because still my problem not solved

    Here's asynctask code sample snippet

    public class Demo extends Activity {
    
      @Override
    
      public void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.main);
    
           new FirstTask().execute(); // calling Asynctask here
    
      }
    

    }

    Async Task code

    private class FirstTask extends AsyncTask<Void, Void, Void> {
            private final ProgressDialog dialog = new ProgressDialog(Catalogue.this);
            int temp = 0;
    
            // can use UI thread here
            protected void onPreExecute() {
                this.dialog.setMessage("Loading...");
                this.dialog.setCancelable(false);
                //this.dialog.show();
                System.gc();
                Toast.makeText(Catalogue.this, "My Async  Created",
                        Toast.LENGTH_LONG).show();
            }
    
            @Override
            protected Void doInBackground(Void... params) {
                Looper.prepare();  
                try {
    
                    myddownloadmethod();// calling my download method
    
                } catch (Exception e) {
                    Util.trace("Error in Async"+e.getMessage());
    
                }
                  Looper.loop();
    
                return null;
            }
    
            protected void onPostExecute(Void result) {
    
                if (this.dialog.isShowing()) {
                    Toast.makeText(Catalogue.this, "My Async destroyed",
                            Toast.LENGTH_LONG).show();
                    Toast.makeText(Catalogue.this, "count" + temp,
                            Toast.LENGTH_LONG).show();
                    this.dialog.dismiss();
                }
            }
        }
    

    Here's My Service sinppet

    public class MyService extends Service implements Runnable
    
    {      @Override
    
            public void onCreate() {
    
                    super.onCreate();
    
                    Thread mythread = new Thread(this);
    
                    mythread.start();
    
            }
    
    
    
            public void run() {
    
                    Looper.prepare();  
    
                    try {
    
                            myddownloadmethod();// calling my download method
    
                    } catch (Exception e1) {
    
                            // TODO Auto-generated catch block
    
                            e1.printStackTrace();
    
                    }
    
                    Looper.loop();
    
            }
    
    
    
            @Override
            public IBinder onBind(Intent intent) {
    
                    // TODO Auto-generated method stub
    
                    return null;
    
            }
    
    
    
    }
    
    
    
    Invoking Service  
    
    public class ServicesDemo extends Activity {    
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
          startService(new Intent(this, MyService.class));
    
    
      }
    
    }
    

    Here's IntentService Code

    public class Downloader extends IntentService {
    
        public Downloader() {
            super("Downloader");
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
    
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
    
                }
    
        @Override   
        public void onHandleIntent(Intent i) {
    
            try {
                 myddownloadmethod();// calling my download method
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                Log.d("Error",e1.getMessage());
            }
    
        }
    }
    

    Calling IntentService from MyActivity

    public class ServicesDemo extends Activity {    
          @Override
          public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            Intent i1=new Intent(this, Downloader.class);
            startService(i1);
    
    
    
          }
    
        }
    
  • Sankar Ganesh PMP
    Sankar Ganesh PMP almost 13 years
    i cannot do this, because all the urls are dynamic urls which parsed from a JSON
  • Caspar Harmer
    Caspar Harmer almost 13 years
    As are mine. Parse the URL from your JSON into a variable and then replace the string first parameter with your variable.
  • MollyCat
    MollyCat almost 11 years
    Late in the game, but what about when your app gets rotated. Wouldn't this be killed?
  • Caspar Harmer
    Caspar Harmer almost 11 years
    Possibly. I never had any problems with it, but also can't test your theory - too busy.
  • dcow
    dcow about 10 years
    I think a lot of people will want something more robust than UIL. UIL also requires writing data to external storage. The DownloadManager is also great but similarly requires the data to be written to a secondary location and then copied into your application.
  • TheYann
    TheYann over 9 years
    I like this solution, however is it safe to let the HandlerThread running without ever calling the quit() or quitSafely() method? Or would the HandlerThread kill itself automatically after a while? I don't know nor find anywhere the lifecycle of such an object.
  • Gowtham
    Gowtham over 5 years
    It would be more helpful if you share a code snippet.
  • SIVAKUMAR.J
    SIVAKUMAR.J over 5 years
  • Afinas EM
    Afinas EM over 5 years
    How can I call this class from my activity?