0

I have a requirement where i have to store the last 10 preview frames of android camera when the capture button is clicked. I am able to put 10 frames into a buffer and when the capture button is clicked i am cloning this buffer and saving the frames to file system through an AsyncTask. Everything is working fine, but the problem is with activity life cycle. When i press home or menu button while the AsyncTask is still executing, my AsyncTask stops and i can only see 3 to 5 frames in the file system. I have already tried many alternatives like doing it in a Thread, ExecutorService and even an Intent Service. The problem with using the service is that my buffer contains data more than 10mb and the limit for activity-service communication is 500kb to 1mb(i think, as i got an exception when tried). Below is my code, any help is much appreciated.

private class PreviewFramesProcessor extends AsyncTask<List<byte[]>, Void, Void> {

        @Override
        protected void onPreExecute() {
            dialog.setIndeterminate(true);
            dialog.setCanceledOnTouchOutside(false);
            dialog.setCancelable(false);
            dialog.setMessage("Processing...");
            dialog.show();
        }

        @Override
        protected Void doInBackground(List<byte[]>...temp) {
            /*String folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath();
            panImagesFolder = new File(folder + File.separator + getUniqueFolderName());*/
            panImagesFolder.mkdirs();
            List<byte[]> byteArrayList = temp[0];
            for(int i = byteArrayList.size() - 1; i >= 0 ; i--) {
                File pictureFile = getUniqueMediaFileUri(panImagesFolder, i);
                try {
                    byte[] tempArray = convertYuvToJpeg(byteArrayList.get(i), mCameraDevice);
                    FileOutputStream fos = new FileOutputStream(pictureFile);
                    fos.write(tempArray);
                    fos.close();
                    galleryAddPic(pictureFile);
                    byteArrayList.remove(i);
                } catch(Exception e) {
                    Log.e("Nagendra", "Exception in processByteArrayBuffer(): " + e.getMessage());
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            isPictureTaken = false;
            dialog.hide();
        }

        @Override
        protected void onProgressUpdate(Void... values) {

        }
    }
EKN
  • 1,886
  • 1
  • 16
  • 29
Nagendra
  • 11
  • 5
  • have you tried making the async object as global variable? – Rahul Oct 24 '17 at 09:14
  • Similar question: https://stackoverflow.com/questions/14314252/acivity-is-getting-destroyed-while-pressing-the-home-button – Ghulam Moinul Quadir Oct 24 '17 at 09:20
  • @Rahul Kumar, Yes. I am instantiating this AsyncTask through a global static variable and then executing the same. – Nagendra Oct 24 '17 at 09:32
  • @Ghulam Moinul Quadir, No. My problem isn't similar. My activity is not getting destroyed in this case. – Nagendra Oct 24 '17 at 09:33
  • Have you tried to start a foreground service and inside this you capture the preview frames, save them and pass the data back to the activity when storage has finished? If you want to survive an activity finish then service should be the way to go. I cannot think of any other good alternatives. – Ewald Benes Oct 24 '17 at 09:52
  • "The problem with using the service is that my buffer contains data more than 10mb and the limit for activity-service communication is 500kb to 1mb(i think, as i got an exception when tried)". Are you sending 10MB data in bundle object? – Sagar Trehan Oct 24 '17 at 10:16
  • @Ewald, i will check it out. – Nagendra Oct 24 '17 at 10:24
  • @Sagar Trehan, unfortunately, Yes! My object contains 10 preview frames, each frame's size varies from 500kb to 1.5mb. – Nagendra Oct 24 '17 at 10:26
  • It will cause multiple issues in app like slowness, phone slowdown, oom. Consider writing the frames in files and just share the path of files in Bundle object. – Sagar Trehan Oct 24 '17 at 10:31
  • Well, that's where i'm facing the issue. That's what i'm trying to do in AsyncTask. I am unable to use Service as an alternative to AsyncTask due to larger size of frames. – Nagendra Oct 24 '17 at 10:40
  • AsyncTask should not be used for long running task. You should use service for this work. All frames should be store in files(Persistence Storage) and while notifying the result to activity just pass the file path in bundle object instead of passing frames itself. – Sagar Trehan Oct 24 '17 at 10:56
  • @Sagar, The frames i have will be in activity. To save those frames i am using AsyncTask which is failing when my activity is in background. I cannot pass my frames to a service since my frames are larger in size. Please note that i'm not trying to pass data from a service to activity, instead its the other way around! – Nagendra Oct 24 '17 at 11:08
  • To avoid the bundle size limitation try to capture the frames directly in the service and after having saved the files then notify the activity. Have you tried that? – Ewald Benes Oct 24 '17 at 11:27
  • @Edwald, No, not yet. I think i can store the frames in a static list and try to access\process that list in the service. The problem with saving frames directly in the service is that i have to stop adding the frames to buffer when camera capture button is clicked and then save the still image as well as all 10 preview frames to file system. – Nagendra Oct 25 '17 at 05:14

1 Answers1

0

I thing your activity being destroy, Check whether Don't keep Activity is enabled in Developer Setting.

  • Its disabled. However, the progress dialog i am showing will still be showing when i return to the activity. This doesn't seem like a sign of activity being destroyed! – Nagendra Oct 24 '17 at 09:57
  • Hw r u starting AsyncTask, it means which method you are using to start AsyncTask, can you share code block? – Vijay Pal Vishwakarma Oct 24 '17 at 10:07
  • My global variable would be something like this: private static PreviewFramesProecssor pfp; later i will initialize it as pfp = new PreviewFramesProcessor(); and execute it using pfp.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, myList); – Nagendra Oct 24 '17 at 10:15
  • android:configChanges="keyboardHidden|orientation|screenSize" add this line in manifest, – Vijay Pal Vishwakarma Oct 24 '17 at 10:33
  • Tried that as well! – Nagendra Oct 24 '17 at 10:40