Как убить стороннее приложение? - PullRequest
5 голосов
/ 21 марта 2012

Моя программа должна убить определенное приложение.Возможно ли это на стоковом некорневом устройстве?Если да - как?Я знаю название процесса и PID.

Ответы [ 2 ]

25 голосов
/ 07 мая 2012

Еще раз я отвечаю слишком поздно, но, поскольку сегодня я столкнулся с такой же ситуацией, я подумал поделиться своими выводами, чтобы помочь кому-то.

Прежде всего вам нужно понять, что вы можете убить , а что нет. С точки зрения Android, приложение не похоже на другие ОС. Приложение Android состоит из множества компонентов (действия, приемники вещания, сервисы, наиболее важные задачи и т. Д.), Которые упакованы в пакет. В пакете может быть запущено несколько процессов в зависимости от запущенных компонентов.

Теперь интересно то, что пакет android не рассматривается (для android) kill или остановлен , если какой-либо или все его процессы были уничтожены, фактически пакет может по-прежнему будет работать даже без процессов вообще. Вы можете увидеть этот эффект, если вы запустите эмулятор, запустите программу (т.е. браузер), а затем убьете ее процесс с помощью DDMS, после чего перейдите в настройки пакета приложения (Settings --> Applications --> Manage Applications --> All --> Browser), вы увидите Force Stop кнопка включена, это означает, что приложение все еще работает (с точки зрения Android). Здесь произошло то, что приложение имеет одну или несколько задач заморожено . То есть Android сохранил состояние активности приложения (задачи или задачи), и поэтому пакет все еще работает или лучше, если пользователь вернется к нему, он получит последнее, что делал. Теперь, если вы нажмете кнопку Force Stop , Android отменит все эти замороженные задачи, и когда пользователь вернется в приложение, он увидит первое действие. A Task - это то, что вы не можете убить (начиная с froyo) только пользователя (с кнопки Force Stop ), системы или стороннего приложения, которое подписано тем же ключом система может сделать это (и, возможно, приложение с поддержкой root, но я не подтвердил это). С другой стороны, Процесс - это то, что вы можете уничтожить и восстановить используемую память, если вы соблюдаете некоторые ограничения:

  1. У вас есть разрешение android.permission.KILL_BACKGROUND_PROCESSES.
  2. Процессы не являются системными или корневыми процессами.
  3. Процесс не принадлежит постоянному компоненту.
  4. Процесс не является критичным для работы системы любым другим способом.

Помимо правила № 1, вам не нужно ничего с ними делать, Android позаботится об этом.

ActivityManager имеет удобную функцию, которую вы можете использовать, чтобы убить все процессы, которые имеет пакет одновременно. Когда вы вызываете его, Android убивает любой процесс, который может быть убит, и, таким образом, освобождает некоторую память. Однако состояние задач для этого пакета будет сохранено, и когда пользователь вернется в приложение, он увидит последнее, что он делал, если только сама система не убила их. Это может произойти либо потому, что ему нужны ресурсы, либо состояние было сохранено давно (около 30 минут). Побочным эффектом является то, что, поскольку пользователи думают, что все приложения похожи на настольные операционные системы, они не верят, что приложение действительно закрыто, но это жизнь с Android.

Теперь к коду:

Для своего проекта я подготовил три функции для достижения этой цели.

Первый ищет первый pid процесса, который может иметь пакет, и возвращает -1, если его нет.

private Context cx;
private ActivityManager am = (ActivityManager) cx.getSystemService(Context.ACTIVITY_SERVICE);

public int findPIDbyPackageName(String packagename) {
    int result = -1;

    if (am != null) {
        for (RunningAppProcessInfo pi : am.getRunningAppProcesses()){
            if (pi.processName.equalsIgnoreCase(packagename)) {
                result = pi.pid;
            }
            if (result != -1) break;
        }
    } else {
        result = -1;
    }

    return result;
}

Второй делает что-то глупое, но мне это нужно для моего проекта.

public boolean isPackageRunning(String packagename) {
    return findPIDbyPackageName(packagename) != -1;
}

Третий делает работу.

public boolean killPackageProcesses(String packagename) {
    boolean result = false;

    if (am != null) {
        am.killBackgroundProcesses(packagename);
        result = !isPackageRunning(packagename);
    } else {
        result = false;
    }

    return result;
}

Подтверждено, что они работают с эмулятором API 8 и 9 и на реальном устройстве (Galaxy S2) с API 15, и они ДЕЙСТВИТЕЛЬНО убивают процессы любого приложения (не только вашего), если они не нужны. *

Теперь о документации android.os.Process.killProcess, которая гласит:

... Как правило, это означает только процесс, выполняющий пакеты / приложение вызывающего, и любые дополнительные процессы, созданные этим приложением; ...

Я полагаю, что "процесс, выполняющий пакеты / приложение вызывающего абонента" означает домашнее приложение запуска, а НЕ ваше собственное приложение.Ваше приложение - абонент , а процесс, запускающий пакеты / приложение вызывающего абонента , - это домашняя программа запуска или любое другое приложение, запустившее ваше приложение.Для меня это единственный способ объяснить, что функция killBackgroundProcesses и функция android.os.Process.killProcess действительно работают в сторонних приложениях.

1 голос
/ 21 марта 2012

стоя у документа:

Завершить процесс с помощью данного PID.Обратите внимание, что, хотя этот API позволяет нам запрашивать уничтожение любого процесса на основе его PID, ядро ​​все равно будет накладывать стандартные ограничения на то, какие PID вы действительно можете уничтожить.Обычно это означает только процесс, выполняющий пакеты / приложение вызывающего, и любые дополнительные процессы, созданные этим приложением;пакеты, совместно использующие общий UID, также могут уничтожать процессы друг друга.

, чтобы вы могли убить свой собственный процесс ..

см. Документацию Process .Я пытался запустить adb shell kill pid, но для этого требуется разрешение суперпользователя

...