9

私はランチャーを書いています。「最近のタスクリストにアプリが表示されませんでした」ではなく、システムから最近のアプリ/タスクリストをクリアする必要がありますが、今はわかりません。私はstackoverflowで検索しましたが、この問題だけが一致しましたが、答えは何の助けにもなりません. 他の人が同じ質問をし、Android 4.0 からの RemoveTask に言及しました。はい、Android 2.3.7 と Android 4.0 のソース コードを確認しました。推定ラウンドで、ActivityMangerService.Java で定義されている mRecentTasks のリストを消去できれば、ほぼ終点に到達できると思います。

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");
    }   
}

この関数では、受信者が自分で取得したnullであるため、常に「NullPointerException」に遭遇します。そして、私はこのような別の方法を試しました(すべてのtry/catchを削除した場合):

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

同じ結果、ActivityManagerService のインスタンスを取得できず、mRecentTasks を取得できません。「このリストのすべてのアイテムを削除する方法」はわかりませんが、コメントをお待ちしておりますが、別の質問になる可能性があります。

ありがとう。

4

5 に答える 5

1

以前の回答を編集することもできましたが、別のプロジェクトで使用したこのソリューションは非常に包括的に異なる (そして簡単である) ため、最初からやり直すことをお勧めします...

この場合、単にリフレクションを使用して ActivityManager の removeTask() メソッドにアクセスし、そのすべてを次のように 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" />

私の場合、アプリケーションはシステム権限でインストールされています。

于 2013-04-27T23:43:10.900 に答える
1

私が見つけた最良の方法は、これを行うことです:

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/

これは私自身のコードではありませんが、最近のアプリのリストが表示されないようにするだけです。

于 2013-12-06T09:57:44.940 に答える
0

私はちょうど同じ問題に遭遇しました。さて、最近のリストがどれほど明確かはわかりませんが、アプリをそこに入れないようにする方法は知っています。次から始めます: FLAG_ACTIVITY_NO_HISTORY flag 。

これでうまくいきました。お手伝いできることを願っています。乾杯、詳細: SDK レベル 14 以上

于 2014-06-17T22:18:18.517 に答える
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>

次に、アシスタントが次にタブレットを使用する人のために「ようこそ画面」​​を開始したときに開始する 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 秒の遅延は問題ではありません。

最終的な構成要素は、開始されている 18 の (非常に単純な) アクティビティです。これらは次のようになります。

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

これが役に立てば幸いです。

于 2012-10-21T08:40:25.867 に答える