2012-10-15 39 views
9

Tôi đang viết Trình chạy, cần xóa danh sách ứng dụng/tác vụ gần đây từ hệ thống chứ không phải "không hiển thị ứng dụng của tôi trong danh sách nhiệm vụ gần đây", nhưng hiện tại tôi không có ý tưởng gì về nó. Tôi đã tìm kiếm trong ngăn xếp và chỉ this issue được khớp nhưng câu trả lời không có bất kỳ trợ giúp nào. Một số người khác đã hỏi những câu hỏi tương tự, ông đã metioned RemoveTask mà đến từ Android 4.0. Có, tôi đã kiểm tra mã nguồn của Android 2.3.7 và Android 4.0, với ước tính vòng, tôi nghĩ rằng tôi gần như có thể đạt đến điểm kết thúc nếu tôi có thể xóa danh sách mRecentTasks được xác định trong ActivityMangerService.Java:Android, cách xóa danh sách tác vụ gần đây có thể nhận được từ nút Trang chủ trong hầu hết điện thoại? Phản ánh là một cách có thể?

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

Và một định nghĩa có thể hữu ích:

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

Bởi vì tôi không quen thuộc với Java & refelction, tôi cần giúp đỡ về cách mà rõ ràng danh sách này, dưới đây là mã của tôi:

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

Với chức năng này, tôi luôn đáp ứng "NullPointerException" bởi vì người nhận là null có được tự. Và tôi đã cố gắng một cách khác như thế này (Nếu tôi loại bỏ tất cả try/catch):

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

Các kết quả tương tự, tôi không thể có được sự thể hiện của ActivityManagerService và sau đó tôi không thể nhận được mRecentTasks. Bất kỳ nhận xét nào được đánh giá cao và mặc dù tôi không biết "cách xóa tất cả các mục trong danh sách này", nhưng đó có thể là một câu hỏi khác.

Cảm ơn.

+0

Tôi không hiểu loại trình khởi chạy bạn đang viết ... tại sao bạn nên xóa danh sách chương trình gần đây? Nó chỉ âm thanh với tôi như một khai thác an ninh, hoặc ít nhất là bạn đang ghi đè hành vi mặc định của Android theo một cách rất khó chịu. Ví dụ: một chương trình phần mềm độc hại có thể tự ẩn mình ... – Radu

+0

API không tiếp xúc có thể thay đổi với mọi bản phát hành/bản cập nhật sắp được khởi chạy ứng dụng của bạn. Tốt hơn có thành phần list_ ứng dụng _recent của riêng bạn. –

+0

Hy vọng rằng, điều này được bảo vệ bởi sự cho phép mà chỉ các ứng dụng phần mềm mới có thể giữ, ngay cả khi có cách viết kịch bản-kiddie để hack theo cách của bạn vào nó. – CommonsWare

Trả lời

0

Có một số manh mối tốt về làm thế nào để làm điều này trên câu hỏi này ở đây:

Altering the result of getRecentTasks

Sau này, tôi đã đưa ra những phương pháp sau đây cho mục đích riêng của tôi (một tình huống tương tự, nơi viên được mượn với mọi người và sau đó ai đó phải "xóa lịch sử" trước khi giao cho người tiếp theo).

Thứ nhất, trong manifest của tôi, tôi đã tạo ra 18 nhiệm vụ như thế này:

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

Thứ hai, trong một AsyncTask mà tôi bắt đầu khi trợ lý bắt đầu "Welcome Screen" cho người kế tiếp để sử dụng chiếc máy tính bảng, sau khi tôi xóa lịch sử trình duyệt và các tập tin cookie, tôi làm như sau:

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

trong khi tôi đã sử dụng "Thread.sleep (20)" giữa sự ra đời của mỗi công việc tôi đã không kiểm tra đầy đủ chính xác những gì cần thiết có và có lẽ thời gian ngắn hơn có thể hiệu quả. Vì mục đích của tôi, thời gian trì hoãn 1 giây trong khi các mục này bị xóa không phải là vấn đề.

Các thành phần cuối cùng là mười tám (rất đơn giản) hoạt động đang được bắt đầu, mà trông như thế này:

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

Hy vọng điều này là hữu ích.

+0

Cảm ơn, Karora, nó có thể là một giải pháp khả thi mặc dù nhóm của chúng tôi không nghĩ rằng nó đủ tốt. Chúng tôi hy vọng cách phản chiếu có thể hoạt động –

1

Trong khi tôi thể đã chỉnh sửa câu trả lời trước đây của tôi, giải pháp này tôi đã sử dụng trong một dự án khác nhau là rất toàn diện khác nhau (và dễ dàng hơn) rằng nó là tốt hơn để bắt đầu lại từ đầu ...

Trong trường hợp này tôi chỉ đơn giản là sử dụng phản ánh để truy cập phương pháp removeTask() của ActivityManager, và tôi đã được bao bọc tất cả điều đó vào một lớp tiện lợi của MyActivityManager như sau:

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

} 

sau đó, khi tôi muốn xóa các nhiệm vụ gần đây tôi làm như sau:

new MyActivityManager(this).clearRecentTasks(); 

Có thể là một hoặc cả hai là cần thiết để làm việc này:

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

Trong trường hợp của tôi ứng dụng được cài đặt với các điều khoản của hệ thống.

+3

Theo liên kết này: http://stackoverflow.com/questions/19349958/clear-all-recent-task-programmaticcally Câu trả lời của bạn sẽ không thực sự xóa các tác vụ.Bạn vẫn cần thêm quyền để xóa nhiệm vụ, thao tác này không hoạt động trừ khi bạn là nhà phát triển ROM đã ký. –

1

Cách tốt nhất mà tôi đã tìm thấy là để làm điều này:

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/ 

Đây không phải là mã của riêng tôi, nhưng điều này chỉ ẩn danh sách ứng dụng gần đây hiển thị.

+1

Tôi có thể gọi nó như thế nào trong hoạt động khác? – androidBoomer

0

Tôi vừa gặp vấn đề tương tự. Được rồi, tôi không biết làm thế nào rõ ràng danh sách gần đây, nhưng tôi biết, làm thế nào không để đưa ứng dụng của bạn ở đó. bắt đầu bằng: cờ FLAG_ACTIVITY_NO_HISTORY.

Điều này phù hợp với tôi, tôi hy vọng tôi có thể trợ giúp với bạn. Chúc mừng, chi tiết: min Cấp SDK 14