0

I am getting a list of image url from server whose count is approximately in between 400-500. How can i download this image in background into local folder of the device ?

SO far i have run a foreground service in which i am using ExecutorService to run a thread. My service code is below

public class SaveImageService extends Service {

    private Context context;
    public static final String NOTIFICATION_CHANNEL_ID = "10001";
    public SaveImageService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            startMyOwnForeground();
        else
            startForeground(1, new Notification());
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        context = this;
        super.onStartCommand(intent, flags, startId);
        List<Callable<String>> saveDataThreads = new ArrayList<>();
        SaveTaskImage saveTaskImage = new SaveTaskImage(this);
        saveDataThreads.add(saveTaskImage);
        ExecutorService executor = Executors.newFixedThreadPool(saveDataThreads.size());
        try {
            List<Future<String>> aaa = executor.invokeAll(saveDataThreads);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executor.shutdown();
        if (executor.isShutdown()) {
            stopForeground(true);
            stopSelf();
        }
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startMyOwnForeground() {
        String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
        String channelName = "My Background Service";
        NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
        chan.setLightColor(Color.BLUE);
        chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        assert manager != null;
        manager.createNotificationChannel(chan);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        Notification notification = notificationBuilder.setOngoing(true)
                .setSmallIcon(R.mipmap.talentify_logo_red)
                .setContentTitle("App is running in background")
                .setPriority(NotificationManager.IMPORTANCE_MIN)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build();
        startForeground(2, notification);
    }
}

In SaveTask thread i triggering a sync task as below

new SaveImageAsync ("file_path").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,url);

Below is my async task code :

public class SaveImageAsync extends AsyncTask<String, Void, String> {
    private MediaSaver mediaSaver;

    public SaveImageAsync(MediaSaver mediaSaver){
        this.mediaSaver = mediaSaver;
    }
    @Override
    protected String doInBackground(String... params) {
        Bitmap bmp = null;
        try{
            System.out.println("Save image url --> "+params[0].replaceAll(" ", "%20"));
            URL url = new URL(params[0].replaceAll(" ", "%20"));
            InputStream fileInputStream = url.openStream();
            if(fileInputStream != null) {
                mediaSaver.save(fileInputStream);
                System.out.println("Saving  image --> ");
            }else{
                System.out.println("Not Saving  image --> ");

            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }

    @Override
    protected void onPostExecute(String string) {
    }
}

But in this approach i am able to save only 50 -60 images in background. Its not running till end. What should i do please suggest

Feroz Siddiqui
  • 3,840
  • 6
  • 34
  • 69
  • What are the symptoms of your issue? Does the background task crash? Do you have any stack trace? Is service killed or finishes normally? Is your app process killed? Is your service recreated (due to START_STICKY)? – Pawel Nov 08 '18 at 00:23
  • yes it seem process is getting killed in between. its not running till the end. – Feroz Siddiqui Nov 08 '18 at 00:24
  • is there is way i can make queue of these downloads? – Feroz Siddiqui Nov 08 '18 at 00:29
  • 1
    Running 200 simultaneous threads is most likely never going to work. You need to use sensible thread count and queue the tasks. – Pawel Nov 08 '18 at 00:31
  • for this what approach should i follow? timing is not an issue here. I just want to download all the images. – Feroz Siddiqui Nov 08 '18 at 00:32
  • Limit threads in your `ExecutorService` to something like 8, and don't `shutdown` it immediately as it will clear the tasks in queue. – Pawel Nov 08 '18 at 00:38
  • Should i use work manager or thread pool executor ?? – Feroz Siddiqui Nov 08 '18 at 01:02

1 Answers1

1

Use below library -

implementation 'com.amitshekhar.android:android-networking:1.0.2'

Implementation of that library -

for (int j = 0; j < imageArrayList.size(); j++) {
        downloadImage(imageArrayList.getImagePath(j), imageArrayList.get(j),getImageName);
    }


 private void downloadImage(String imageURL, String imagename) {

    AndroidNetworking.download(imageURL, getCacheDir().getPath() + "/" + Constant.FOLDER_NAME + "/", imagename)
            .setPriority(Priority.HIGH)
            .build()
            .setDownloadProgressListener(new DownloadProgressListener() {
                @Override
                public void onProgress(long bytesDownloaded, long totalBytes) {
                    // do anything with progress
                }
            })
            .startDownload(new DownloadListener() {
                @Override
                public void onDownloadComplete() {

                    // do anything after completion


                }

                @Override
                public void onError(ANError error) {
                    // handle error

                }
            });

}

You can also use android DownloadManager API. Android: How to use download manager class?

Farman Ali Khan
  • 822
  • 7
  • 24