2

I am developing a mobile application that runs in the background. It takes screenshots in the background on an interval, however after some time, ActivityManager would kill the process with the log, I/ActivityManager: killing com.example: excessive cpu xxxx during yyyyy dur=zzzzz limit=2

What can I do to prevent ActivityManager from killing the application?

I check for memory leak using LeakCanary but 0 leak is found

I tried:
- minifyEnabled true
- shrinkResources true
- proguardFiles

I am using a Handler to run my program automatically (mainly MediaProjection and ImageReader) at an interval. After following tutorials from other questions and google, I made my Handler static, however the same issue still persists.

MainActivity.java:

    public void startCapturing() {
        try {
            mHandler.post(captureInterval);
            Toast.makeText(this, "started", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class SafeRunnable implements Runnable {
        private final WeakReference<MainActivity> mReference;

        SafeRunnable(MainActivity reference) {
            mReference = new WeakReference<>(reference);
        }

        @Override
        public void run() {
            final MainActivity reference = mReference.get();
            if (reference != null) {
                runWithParent(reference);
            }
        }
        public void runWithParent(MainActivity reference) {

        }
    }

    private final Runnable captureInterval = new SafeRunnable(this) {
        @Override
        public void runWithParent(MainActivity reference) {
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
            destroyImageReader();
            destroyVirtualDisplay();
            if (!mKeyguardManager.isKeyguardLocked()) {
                if (mMediaProjection == null) {
                    startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
                } else {
                    createVirtualDisplay();
                }
            }
            reference.mHandler.removeCallbacksAndMessages(captureInterval);
            reference.mHandler.postDelayed(this, 5000);
        }
    };
  • "I am developing a mobile application that runs in the background" -- you might want to explain, in significantly greater detail, how you are doing this. Are you using a foreground service? `WorkManager`? `JobScheduler`? Something else? – CommonsWare Mar 27 '20 at 13:27
  • Hi @CommonsWare, I have updated the questions with the code that runs the Handler. I instantiate the `Handler` in `onCreate()`. I do not use any foreground service. – Andre Hadianto Mar 28 '20 at 06:52
  • In Android, background processes get terminated all the time. This is covered in many places like [the documentation](https://developer.android.com/guide/components/activities/process-lifecycle), books, and courses. The closest that you will get to what you are aiming for is a foreground service. Also, bear in mind that taking a screenshot every 5 seconds will consume ~1GB per day, depending on screen resolution. – CommonsWare Mar 28 '20 at 11:18

1 Answers1

2

Running services will be terminated every 30 minutes. Services that wish to remain alive for longer than this must call Service.startForeground, which places a notification on the notification bar, so that users know that your service is permanently running and potentially sucking battery life.

Please show a notification to the user.

Hope this will be helpful.

Magudesh
  • 419
  • 5
  • 13
  • 2
    After refactoring my code into a Foreground service, it works like charm. However, there is a memory leak issue now. But it will be for another question. Thanks for your help! – Andre Hadianto Apr 01 '20 at 12:02