Android, как очистить список последних задач, которые можно получить с помощью кнопки "Домой" в большинстве телефонов? Отражение это возможный способ?

Я пишу Launcher, он должен очистить список последних приложений / задач из системы, а не "не показывал мои приложения в списке недавних задач", но я понятия не имею об этом сейчас. Я искал в стеке потока, и только эта проблема соответствует, но ответ не имеет никакой помощи. Другой человек задавал те же вопросы, он упомянул RemoveTask, который поставляется с Android 4.0. Да, я проверил исходный код Android 2.3.7 и Android 4.0, по приблизительным оценкам, я думаю, я мог бы почти достичь конечной точки, если бы я мог стереть список mRecentTasks, который определен в ActivityMangerService.Java:

final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();

И еще одно, возможно, полезное определение:

static ActivityManagerService mSelf;
public static ActivityManagerService self() {
    return mSelf;
}

Поскольку я не знаком с Java и refelction, мне нужна помощь о том, как очистить этот список, ниже приведен код моего:

    public static <T> void clearRecentTaskList(Launcher launcher){
    ActivityManager am = (ActivityManager) launcher.getSystemService(Context.ACTIVITY_SERVICE);
    Object systemRecentTask = new ArrayList<T>();

    Object receiver = null;
    Field recentTaskList = null;
    Class<?> service = null;
    Field self = null;        


    try {
        service = Class.forName("com.android.server.am.ActivityManagerService");
        Log.d(LOG_TAG, "clearRecentTaskList, service gotton"+service.getName());
    } catch (ClassNotFoundException e2) {
        Log.d(LOG_TAG, "clearRecentTaskList, class service not found");
    }

    try {
        self = service.getDeclaredField("mSelf");
    } catch (SecurityException e2) {
        Log.d(LOG_TAG, "clearRecentTaskList, SecurityException during get mSelf");

    } catch (NoSuchFieldException e2) {
        Log.d(LOG_TAG, "clearRecentTaskList, NoSuchFieldException during get mSelf");
    }
    Log.d(LOG_TAG, "clearRecentTaskList, self  gotton " + self.toGenericString());

    try {
        self.setAccessible(true);
        receiver = self.get(null);
    } catch (IllegalArgumentException e2) {
        Log.d(LOG_TAG, "clearRecentTaskList, IllegalArgumentException during use self to get the receiver");
    } catch (IllegalAccessException e2) {
        Log.d(LOG_TAG, "clearRecentTaskList, IllegalAccessException during use self to get the receiver");
    }

    if ( receiver != null){
        Log.d(LOG_TAG, "clearRecentTaskList, receiver is : "+receiver.toString());
    } else {
        Log.d(LOG_TAG, "clearRecentTaskList, receiver is NULL");
    }


    try {
        recentTaskList = service.getDeclaredField("mRecentTasks");
        recentTaskList.setAccessible(true);
        Log.d(LOG_TAG, "clearRecentTaskList, recentTaskList gotton"+recentTaskList.toGenericString());

        try {
            systemRecentTask = recentTaskList.get(receiver);
        } catch (IllegalArgumentException e1) {
            Log.d(LOG_TAG, "IllegalArgumentException during try to clearRecentTask");
        } catch (IllegalAccessException e1) {
            Log.d(LOG_TAG, "IllegalAccessException during try to clearRecentTask");
        }

        Log.d(LOG_TAG, "Try to print the size of recent task: "+((ArrayList<T>) systemRecentTask).size());

    } catch (SecurityException e) {
        Log.d(LOG_TAG, "SecurityException during try to clearRecentTask");
    } catch (NoSuchFieldException e) {
        Log.d(LOG_TAG, "NoSuchFieldException during try to clearRecentTask");
    }   
}

С этой функцией я всегда встречаю "NullPointerException", потому что получатель имеет значение null, полученное самостоятельно. И я попробовал другой способ, как это (если я удаляю все try/catch):

self = service.getDeclaredMethod("mSelf", null);
receiver = self.invoke(null, null); // mSelf is a static method which in ActivityMangerService class

Тот же результат, я не могу получить экземпляр ActivityManagerService, а затем я не могу получить mRecentTasks. Любые комментарии приветствуются, и хотя я не знаю, "как удалить все элементы в этом списке", но это могут быть другие вопросы.

Благодарю.

5 ответов

Лучший способ, который я нашел, это сделать это:

public class BaseActivity extends Activity {
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

            Log.d("Focus debug", "Focus changed !");

        if(!hasFocus) {
            Log.d("Focus debug", "Lost focus !");

            Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            sendBroadcast(closeDialog);
        }
    }
}// all credit goes here: http://www.juliencavandoli.com/how-to-disable-recent-apps-dialog-on-long-press-home-button/

Это не мой собственный код, но он просто скрывает список последних приложений.

Хотя я мог бы отредактировать свой предыдущий ответ, это решение, которое я использовал в другом проекте, настолько разносторонне (и проще), что лучше начинать все сначала...

В этом случае я просто использовал отражение, чтобы получить доступ к методу removeTask() ActivityManager, и обернул все это в удобный класс MyActivityManager следующим образом:

import java.lang.reflect.Method;

public class MyActivityManager {


    private ActivityManager mActivityManager = null;
    private Method mRemoveTask;

    public MyActivityManager(Context context) {
        try {
            Class<?> activityManagerClass = Class.forName("android.app.ActivityManager");
            mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

            mRemoveTask = activityManagerClass.getMethod("removeTask", new Class[] { int.class, int.class });
            mRemoveTask.setAccessible(true);

        }
        catch ( ClassNotFoundException e ) {
            Log.i("MyActivityManager", "No Such Class Found Exception", e);
        }
        catch ( Exception e ) {
            Log.i("MyActivityManager", "General Exception occurred", e);
        }
    }

    /**
     * If set, the process of the root activity of the task will be killed
     * as part of removing the task.
     */
    public static final int REMOVE_TASK_KILL_PROCESS = 0x0001;

    /**
     * Completely remove the given task.
     *
     * @param taskId Identifier of the task to be removed.
     * @param flags Additional operational flags.  May be 0 or
     * {@link #REMOVE_TASK_KILL_PROCESS}.
     * @return Returns true if the given task was found and removed.
     */
    public boolean removeTask(int taskId, int flags) {
        try {
            return (Boolean) mRemoveTask.invoke(mActivityManager, Integer.valueOf(taskId), Integer.valueOf(flags) );
        } catch (Exception ex) {
            Log.i("MyActivityManager", "Task removal failed", ex);
        }
        return false;
    }

    public void clearRecentTasks() {
        List<RecentTaskInfo> recents = mActivityManager.getRecentTasks(1000, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
        // Start from 1, since we don't want to kill ourselves!
        for( int i=1; i < recents.size(); i++ ) {
            removeTask( recents.get(i).persistentId, 0);
        }
    }

}

Затем, когда я хочу очистить последние задачи, я делаю следующее:

new MyActivityManager(this).clearRecentTasks();

Вполне возможно, что один или оба из них необходимы для этой работы:

<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />

В моем случае приложение установлено с системными разрешениями.

Я только что встретился с той же проблемой. Ладно, я не знаю, насколько понятен недавний список, но я знаю, как не разместить там свое приложение. начните его с флага FLAG_ACTIVITY_NO_HISTORY.

Это сработало для меня, я надеюсь, что смогу помочь с этим для вас. Приветствия, детали: минимальный уровень SDK 14

Есть несколько хороших подсказок относительно того, как сделать это по этому вопросу здесь:

Изменение результата getRecentTasks

Следуя этим правилам, я использовал следующий подход для своих собственных целей (аналогичная ситуация, когда таблетки передаются в аренду людям, а затем кто-то должен "очистить историю", прежде чем передать их следующему человеку).

Во-первых, в своем манифесте я создал 18 заданий, подобных этому:

<activity
  android:name=".nul.Null0"
  android:enabled="false"
  android:excludeFromRecents="false"
  android:exported="false"
  android:label="n0"
  android:launchMode="singleInstance"
  android:stateNotNeeded="true"
  android:taskAffinity=""
  android:theme="@android:style/Theme.Translucent.NoTitleBar" >
  <intent-filter>
    <action android:name="com.morphoss.blah.welcome.nul.Null0" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Во-вторых, в AsyncTask, который я запускаю, когда помощник запускает "Экран приветствия" для следующего человека, который будет использовать планшет, после очистки истории браузера и файлов cookie, я делаю следующее:

try {
    PackageManager pm = getPackageManager();
    ComponentName cn;
    Intent nullActivity;
    for( int i=0; i<19; i++ ) {
        cn = new ComponentName("com.morphoss.blah.welcome","com.morphoss.blah.welcome.nul.Null"+i);
        pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
        nullActivity = new Intent();
        nullActivity.setComponent(cn);
        nullActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(nullActivity);
        Thread.sleep(20);
    }
    Thread.sleep(100);
    for( int i=0; i<18; i++ ) {
        cn = new ComponentName("com.morphoss.blah.welcome","com.morphoss.blah.welcome.nul.Null"+i);
        pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
    }
}
catch( Exception e) {
    if ( Constants.LOG_DEBUG ) Log.d(TAG,Log.getStackTraceString(e));
}

Хотя я использовал "Thread.sleep(20)" между запуском каждой задачи, я не полностью изучил, что именно там требуется, и, возможно, может подойти более короткое время. Для моих целей задержка в 1 секунду, пока они удалены, не является проблемой.

Последними ингредиентами являются восемнадцать (очень простых) действий, которые начинаются, которые выглядят так:

package com.morphoss.blah.welcome.nul;

import android.app.Activity;
import android.os.Bundle;

public class Null0 extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.finish();
    }
}

Надеюсь, это полезно.

Чтобы удалить все недавние задачи:

ActivityTaskManager.getService(). RemoveAllVisibleRecentTasks();

Другие вопросы по тегам