Search code examples
androidperformanceandroid-mediaprojectionandroid-activitymanager

How to prevent ActivityManager from killing my application's background process


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);
        }
    };

Solution

  • 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.