Search code examples
androidbitmapandroid-asynctaskuribackground-process

AsyncTask: What to use when doInBackground busy?


I have to share an image in my app.

Glide.with(PhotoFullScreenActivity.this)
         .asBitmap()
         .load(getBestDownscaledAlternative(mPhotoList.get(mCurrentPosition)))
         .into(new SimpleTarget<Bitmap>() {
             @Override
             public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                 startShareImageTask(resource);
             }

             @Override
             public void onLoadFailed(@Nullable Drawable errorDrawable) {
                 super.onLoadFailed(errorDrawable);
                 Log.e("Check","error");
             }
         });

I'm using the above snippet to convert the URL into a bitmap and after the resource is ready I call the startShareImageTask to create a file.

The startShareImageTask looks like this:

private void startShareImageTask(Bitmap resource){

    new AsyncTask<Bitmap, Void, Uri>(){

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mShareLoadingPB.setVisibility(View.VISIBLE);
            Log.d("ShareImageTask", "onPreExecute: " + System.currentTimeMillis());
        }

        @Override
        protected Uri doInBackground(Bitmap... bitmaps) {
            Uri bmpUri = null;
            try {
                // Use methods on Context to access package-specific directories on external storage.
                // This way, you don't need to request external read/write permission.
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
                FileOutputStream out = new FileOutputStream(file);
                resource.compress(Bitmap.CompressFormat.JPEG, 90, out);
                out.close();

                // wrap File object into a content provider. NOTE: authority here should match authority in manifest declaration
                bmpUri = ImageFileProvider.getUriForFile(PhotoFullScreenActivity.this, getApplicationContext().getPackageName() + ".fileprovider", file);  // use this version for API >= 24

            } catch (IOException e) {
                e.printStackTrace();
                mShareLoadingPB.setVisibility(View.GONE);
            }
            return bmpUri;
        }

        @Override
        protected void onPostExecute(Uri uri) {
            super.onPostExecute(uri);
            mShareLoadingPB.setVisibility(View.GONE);

            mShareIntent = new Intent();
            mShareIntent.setAction(Intent.ACTION_SEND);
            mShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
            mShareIntent.setType("image/*");

            startActivity(Intent.createChooser(mShareIntent, "Share image"));
        }
    }.execute();
}

All works out great but my app needs to record something in a background task and when it does, my doInBackground method is not called until I finish the recording...I want to share the image while I'm recording something.

What can I do when my background thread is busy with another task? Is there any workaround to this?


Solution

  • I was able to make this work by changing the AsyncTask to RxJava. I'll leave the code difference here in case anyone bumps into this issue.

     mShareLoadingPB.setVisibility(View.VISIBLE);
        Log.d("ShareImageTask", "onPreExecute: " + System.currentTimeMillis());
    
        Observable.fromCallable(() -> {
            Uri bmpUri = null;
            try {
                // Use methods on Context to access package-specific directories on external storage.
                // This way, you don't need to request external read/write permission.
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
                FileOutputStream out = new FileOutputStream(file);
                resource.compress(Bitmap.CompressFormat.JPEG, 90, out);
                out.close();
    
                // wrap File object into a content provider. NOTE: authority here should match authority in manifest declaration
                bmpUri = ImageFileProvider.getUriForFile(PhotoFullScreenActivity.this, getApplicationContext().getPackageName() + ".fileprovider", file);  // use this version for API >= 24
    
            } catch (IOException e) {
                e.printStackTrace();
                mShareLoadingPB.setVisibility(View.GONE);
            }
            return bmpUri;
        })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DefaultObserver<Uri>() {
                    @Override
                    public void onNext(Uri uri) {
                        mShareLoadingPB.setVisibility(View.GONE);
    
                        mShareIntent = new Intent();
                        mShareIntent.setAction(Intent.ACTION_SEND);
                        mShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
                        mShareIntent.setType("image/*");
    
                        startActivity(Intent.createChooser(mShareIntent, "Share image"));
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        Log.e("Error","Error");
                    }
    
                    @Override
                    public void onComplete() {
    
                    }
                });