Android,如何清除大多数手机中可以从主页按钮获取的最近任务列表?反思是一种可能的方式吗?

Red*_*hen 9 reflection android launcher tasklist

我正在写一个启动器,它需要从系统中清除最近的应用程序/任务列表,而不是"没有在最近的任务列表中显示我的应用程序",但我现在不知道它.我在stackoverflow中搜索过,只有这个问题匹配,但答案没有任何帮助.其他一些人问了同样的问题,他提到了Android 4.0的RemoveTask.是的,我已经检查了Android 2.3.7和Android 4.0的源代码,估计一轮,我想如果我可以删除在ActivityMangerService.Java中定义的mRecentTasks列表,我几乎可以达到终点:

final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
Run Code Online (Sandbox Code Playgroud)

另一个可能有用的定义:

static ActivityManagerService mSelf;
public static ActivityManagerService self() {
    return mSelf;
}
Run Code Online (Sandbox Code Playgroud)

因为我不熟悉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");
    }   
}
Run Code Online (Sandbox Code Playgroud)

有了这个函数,我总是遇到"NullPointerException",因为接收器是null,由self得到.而我尝试了另一种方式(如果我删除所有try/catch):

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

同样的结果,我无法获得ActivityManagerService的实例然后我无法获得mRecentTasks.任何评论都表示赞赏,虽然我不知道"如何删除此列表中的所有项目",但它可能是另一个问题.

谢谢.

kar*_*ora 0

关于如何在此问题上执行此操作,这里有一些很好的线索:

更改 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>
Run Code Online (Sandbox Code Playgroud)

其次,在助手为下一个使用平板电脑的人启动“欢迎屏幕”时启动的 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));
}
Run Code Online (Sandbox Code Playgroud)

虽然我在每个任务启动之间使用了“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();
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这有帮助。