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