2012-10-15 2 views
9

Ich schreibe einen Launcher, es muss die aktuelle App/Aufgabenliste vom System löschen, nicht "habe meine Apps nicht in der letzten Aufgabenliste angezeigt", aber ich habe keine Ahnung davon. Ich habe im Stackoverflow gesucht und nur this issue ist abgestimmt, aber die Antwort hat keine Hilfe. Ein anderer Typ hat die gleichen Fragen gestellt, er erinnerte sich an die RemoveTask, die von Android 4.0 kommt. Ja, ich habe den Quellcode von Android 2.3.7 und Android 4.0 überprüft, bei einer Runde geschätzt, ich denke, ich könnte fast den Endpunkt erreichen, wenn ich die Liste der mRecentTasks löschen kann, die in ActivityMangerService.Java definiert:Android, wie man die letzte Aufgabenliste löscht, die vom Hauptknopf in den meisten Telefonen erhalten könnte? Reflexion ist ein möglicher Weg?

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

Und eine andere vielleicht nützliche Definition:

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

Weil ich mit Java & nicht vertraut bin refelction, ich brauche über die Art und Weise helfen, die klar, dass diese Liste, unten ist der Code meines:

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

Mit dieser Funktion erfülle ich immer die "NullPointerException", weil der Empfänger null ist, der von selbst erhalten wurde. Und ich habe eine andere Art und Weise, wie diese versucht (Wenn ich die alle try/catch entfernen):

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

Das gleiche Ergebnis kann ich nicht die Instanz von ActivityManagerService bekommen und dann kann ich nicht die mRecentTasks bekommen. Irgendwelche Kommentare werden geschätzt und obwohl ich nicht weiß, "wie man alle Einzelteile in dieser Liste löscht", aber es könnte andere Fragen sein.

Danke.

+0

Ich verstehe nicht, welche Art von Launcher Sie schreiben ... Warum sollten Sie die Liste der letzten Programme löschen? Es klingt für mich wie ein Sicherheits-Exploit oder zumindest so, als würden Sie Android-Standardverhalten auf eine sehr unangenehme Weise überschreiben. Zum Beispiel könnte sich ein Malware-Programm verstecken ... – Radu

+0

Nicht exponierte API wird sich wahrscheinlich mit jeder Version/jedem Update ändern, was zu _break_ Ihrer App führt. Bessere eigene _recent apps list_ Komponente. –

+0

Hoffentlich ist dies durch eine Erlaubnis geschützt, die nur Firmware-Apps halten können, selbst wenn es einen lahmen Skript-Kiddie-Weg gibt, um sich hineinzuhacken. – CommonsWare

Antwort

0

Es gibt einige gute Anhaltspunkte darüber, wie diese hier in dieser Frage zu tun:

Altering the result of getRecentTasks

Nach diesen habe ich folgende Vorgehensweise für meine eigenen Zwecke (eine ähnliche Situation gebracht, wo Tabletten ausgeliehen werden zu Menschen und dann muss jemand "die Geschichte klären", bevor er sie der nächsten Person übergibt.

Zum einen in meinem Manifest, habe ich 18 Aufgaben wie folgt aus:

<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> 

Zweitens in einer AsyncTask, dass ich beginnen, wenn der Assistent den „Welcome Screen“ für die nächste Person beginnen die Tablette zu verwenden, nachdem ich den Browser-Verlauf und die Cookies zu löschen, muss ich folgendes:

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

Während ich „Thread.sleep (20)“ zwischen dem Start jeder Aufgabe verwendet haben, habe ich nicht vollständig untersucht, genau das, was es benötigt wird, und vielleicht könnte eine kürzere Zeit funktionieren. Für meine Zwecke ist eine Verzögerung von 1 Sekunde, während diese gelöscht werden, nicht problematisch.

Die letzten Bestandteile sind die achtzehn (sehr einfach) Aktivitäten, die gestartet werden, die wie folgt aussehen:

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

Hope this hilfreich.

+0

Danke, Karora, es kann eine praktikable Lösung sein, obwohl unser Team es nicht für gut genug hält. Wir hoffen, der Weg der Reflexion kann funktionieren –

1

Während ich konnte meine frühere Antwort bearbeitet habe, diese Lösung, die ich in einem anderen Projekt verwendet habe, ist so umfassend unterschiedliche (und einfacher), dass es besser ist, von neuem zu beginnen ...

In diesem Fall I hat einfach Reflexion für den Zugriff auf die removeTask() -Methode des Activitymanagers, und ich habe all das in eine Convenience-Klasse von MyActivityManager eingewickelt wie folgt verwendet:

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

} 

Dann, als ich mir die letzten Aufgaben löschen möchte folgendes tun:

new MyActivityManager(this).clearRecentTasks(); 

Es ist möglich, dass ein oder beide diese benötigt werden, damit dies funktioniert:

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

In meinem Fall ist die Anwendung mit Systemberechtigungen installiert.

+3

Nach diesem Link: http://StackOverflow.com/Questions/19349958/clear-all-recent-Task-programmaticcally Ihre Antwort wird nicht wirklich die Aufgaben zu entfernen.Sie müssen weiterhin die Berechtigung zum Entfernen von Aufgaben hinzufügen. Dies funktioniert nur, wenn Sie ein signierter Entwickler des ROMs sind. –

1

Der beste Weg, die ich gefunden habe ist, dies zu tun:

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/ 

Das ist nicht mein eigener Code ist, aber dies nur versteckt die aktuelle Liste Apps aus zeigt.

+1

Wie kann ich es in anderen Aktivitäten nennen? – androidBoomer

0

Ich habe gerade mit dem gleichen Problem getroffen. Okay, ich weiß nicht, wie klar die jüngste Liste ist, aber ich weiß, wie man Ihre App nicht dort hinstellt. starten Sie es mit: FLAG_ACTIVITY_NO_HISTORY Flag.

Dies funktionierte für mich, ich hoffe, ich kann damit für Sie helfen. Prost, Details: min SDK Ebene 14

Verwandte Themen