Проблемы с системой управления памятью Android - PullRequest
1 голос
/ 09 июля 2020

Цель моего приложения - оно должно работать вечно без вмешательства пользователя. Но он много раз терпел неудачу, вероятно, проблемы с памятью. Согласно документу Android, Android сначала позволяет пользователю с помощью onTrimMemory () предупреждать, если системе нужна память. Тем не менее, если системе Android требуется больше памяти, тогда сгенерируйте исключение OOM (Out of memory), и приложение выдаст sh. Мое приложение использует службу с активностью, а служба запускается с прикрепленным уведомлением. (Это будет держать службу на переднем плане, и это не является целью высокого уровня, которую нужно убить). Ниже код создает липкое уведомление.

private void startForegroundService(Context context, String text){
    Intent notificationIntent = new Intent(context, MainActivity.class);
    notificationIntent.setAction(Intent.ACTION_MAIN);
    notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_SINGLE_TOP
            | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);

    PendingIntent pendingIntent = PendingIntent.getActivity(context, 1,
            notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(
                NOTIFICATION_CHANNEL_ID,
                text,
                NotificationManager.IMPORTANCE_DEFAULT);
        ((NotificationManager) context.getSystemService(NOTIFICATION_SERVICE)).createNotificationChannel(channel);
        notificationBuilder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);

    } else {
        notificationBuilder = new Notification.Builder(context);
    }

    notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(getString(R.string.background_control))
            .setContentText(text)
            .setContentIntent(pendingIntent);

    startForeground(MAIN_NOTIFICATION_ID, notificationBuilder.build());
}

Первое, что я делаю Я не понимаю, что события, связанные с памятью, не в порядке. Например, если Android требуется память, то сначала следует выбросить уровень onTrimMemory () в порядке (5, 20, 60, ..), а если требуется больше, выбросить OOM. Но пока что я испытал это не последовательно, а совершенно случайно. И в моем приложении не происходит утечки памяти. Я много раз проверял это с помощью Android IDE Profiler. А в некоторых тестовых приложениях проблем с памятью не возникает. Думаю, это означает, что, вероятно, утечки памяти нет.

Во-вторых, я хочу знать, как точно оценить память. Теперь я использую Runtime.getRuntime () для проверки текущей памяти. Не только куча памяти приложения, но и системы. Я вхожу в журнал, когда происходит cra sh, но памяти достаточно. Код ниже предназначен для регистрации событий.

@Override
public void onTrimMemory(int level) {
    super.onTrimMemory(level);
    Runtime runtime = Runtime.getRuntime();
    long totalMem = runtime.totalMemory();
    long freeMem = runtime.freeMemory();
    final double usedMemInMB = (double) (totalMem - freeMem) / 1048576;

    LogManager.addLog(LogManager.WARNING_TAG,
            "onTrimMemory Level(" + level + "), Free/ Used/ Total/ Avail: "
                    + String.format("%5.2f", (freeMem / 1024.0 / 1024.0)) + "/ "
                    + String.format("%5.2f", usedMemInMB) + "/ "
                    + String.format("%5.2f", (totalMem / 1024.0 / 1024.0)) + "/ "
                    + String.format("%7.2f", (getAvailableMemory() / 1024.0 / 1024.0)) + "MB"
    );
}

private long getAvailableMemory() {
    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);

    return memoryInfo.availMem;
}

Поэтому я не понимаю, почему Android бросает onTrimMemory () или OOM или даже убивает мое приложение без предупреждения.

1 Ответ

0 голосов
/ 19 августа 2020

Только одна утечка памяти в моем приложении была устранена. Я рекомендую использовать Profiler Android Studio и tack, чтобы найти утечку, если кто-то страдает от этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...