以编程方式清除应用程序数据

141
我希望能在我的应用程序中通过编程的方式清除数据。
应用程序的数据可能包含诸如数据库、共享首选项、内部/外部文件或应用程序内创建的任何其他文件等内容。
我知道我们可以通过以下方式清除移动设备上的数据:
设置-> 应用程序-> 管理应用程序-> 我的应用程序-> 清除数据
但是,我需要通过Android程序完成以上操作?
6个回答

145

在 API 19(KitKat)中引入了一个新的 API:ActivityManager.clearApplicationUserData()

我强烈建议在新应用程序中使用它:

import android.os.Build.*;
if (VERSION_CODES.KITKAT <= VERSION.SDK_INT) {
    ((ActivityManager)context.getSystemService(ACTIVITY_SERVICE))
            .clearApplicationUserData(); // note: it has a return value!
} else {
    // use old hacky way, which can be removed
    // once minSdkVersion goes above 19 in a few years.
}

如果您不想使用hacky的方法,您也可以在用户界面上隐藏按钮,从而使旧手机上无法使用该功能。

了解此方法对于任何使用android:manageSpaceActivity的人都是强制性的。


每当我使用它时,我都是从具有android:process=":manager"manageSpaceActivity中进行操作。在那里,我手动终止我的应用程序的任何其他进程。这使我可以让UI保持运行状态,并让用户决定下一步该去哪里。

private static void killProcessesAround(Activity activity) throws NameNotFoundException {
    ActivityManager am = (ActivityManager)activity.getSystemService(Context.ACTIVITY_SERVICE);
    String myProcessPrefix = activity.getApplicationInfo().processName;
    String myProcessName = activity.getPackageManager().getActivityInfo(activity.getComponentName(), 0).processName;
    for (ActivityManager.RunningAppProcessInfo proc : am.getRunningAppProcesses()) {
        if (proc.processName.startsWith(myProcessPrefix) && !proc.processName.equals(myProcessName)) {
            android.os.Process.killProcess(proc.pid);
        }
    }
}

16
对我来说,clearApplicationUserData();也会强制关闭应用程序。 - gaurav414u
14
必须杀掉该应用程序,否则它可能仍持有数据,并将写回。唯一安全的方法是:(1) 杀死应用程序,(2) 清除其所有数据,(3) 下次启动应用程序时,它将开始一个全新的状态,没有任何数据。 - hackbod
5
嗨@TWiStErRob,我想在我的应用程序中点击“退出”按钮时实现这种方法。但是它会强制关闭应用程序。相反,我想启动包含注册/登录表单的主要活动。这可能吗? - pblead26
1
对于 KitKat 之前的版本,请参见此答案:https://dev59.com/-2445IYBdhLWcg3wcZ4N#23470355 - ultraon
2
应用此代码后,是否可以启动其他活动? - Amandeep Rohila
显示剩余11条评论

111

我只是将ihrupin在链接中发布的教程放在这篇文章中。

package com.hrupin.cleaner;

import java.io.File;

import android.app.Application;
import android.util.Log;

public class MyApplication extends Application {

    private static MyApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
    }

    public static MyApplication getInstance() {
        return instance;
    }

    public void clearApplicationData() {
        File cacheDirectory = getCacheDir();
        File applicationDirectory = new File(cacheDirectory.getParent());
        if (applicationDirectory.exists()) {
            String[] fileNames = applicationDirectory.list();
            for (String fileName : fileNames) {
                if (!fileName.equals("lib")) {
                    deleteFile(new File(applicationDirectory, fileName));
                }
            }
        }
    }

    public static boolean deleteFile(File file) {
        boolean deletedAll = true;
        if (file != null) {
            if (file.isDirectory()) {
                String[] children = file.list();
                for (int i = 0; i < children.length; i++) {
                    deletedAll = deleteFile(new File(file, children[i])) && deletedAll;
                }
            } else {
                deletedAll = file.delete();
            }
        }

        return deletedAll;
    }
}

如果您想让一个按钮执行此操作,您需要在onClick监听器中调用MyApplication.getInstance(). clearApplicationData()。

更新:您的SharedPreferences实例可能会保留您的数据并在您删除后重新创建首选项文件。因此,您需要获取您的SharedPreferences对象并

prefs.edit().clear().commit();

更新:

如果你还没有这么做的话,在AndroidManifest.xml文件中在application标签内添加android:name="your.package.MyApplication"。否则,MyApplication.getInstance()会返回null,导致NullPointerException


5
注意!你需要删除应用文件夹中的所有内容,包括共享偏好设置,不仅仅是缓存文件夹及其内容。 - Snicolas
2
我已经实施了这个解决方案。但是我的应用程序数据没有被清除,只有缓存被清除了..还剩下5MB..还有其他的解决方案吗?请帮帮我 :( - SweetWisher ツ
1
@MinceMan 请注意,为了更好的效果,这必须在扩展Application的类中编写。 - vishalmullur
1
是的,它删除了所有文件,但应用程序没有意识到,因此仍然可能存在应用程序目录中的文件。应用程序在从最近的应用程序中删除应用程序后才意识到清除。我尝试重新创建活动,但它不起作用。 - gturedi
1
这种方法的一个好处是它不会像activityManager.clearApplicationUserData()一样重置用户授予的权限。 - AtomicBoolean
显示剩余5条评论

24

组合来自2个答案的代码:

这是基于组合后的源码的答案。

private void clearAppData() {
    try {
        // clearing app data
        if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) {
            ((ActivityManager)getSystemService(ACTIVITY_SERVICE)).clearApplicationUserData(); // note: it has a return value!
        } else {
            String packageName = getApplicationContext().getPackageName();
            Runtime runtime = Runtime.getRuntime();
            runtime.exec("pm clear "+packageName);
        }

    } catch (Exception e) {
        e.printStackTrace();
    } 
}

这个程序能在所有 Android 设备上运行吗,不管是哪个版本的 Android?对我来说,它可以在我拥有的所有三个 Android 设备上运行(包括 Lollipop、Marshmallow 和 Pie 版本)。 - Kathir
是的,if else 是用于等于或小于 Kit Kat 的...使用 clearApplicationUserData,它以上使用 runtime.exce...基本上是一个 shell 命令...除了权限之外相当可靠...它应该可以正常工作... - CrandellWS

2

我在任何地方都会使用的技术:

 Runtime.getRuntime().exec("pm clear me.myapp");

执行上述代码将关闭应用程序并删除所有数据库和共享首选项。

0

尝试这段代码

private void clearAppData() {
    try {
        if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) {
            ((ActivityManager)getSystemService(ACTIVITY_SERVICE)).clearApplicationUserData();
        } else {
            Runtime.getRuntime().exec("pm clear " + getApplicationContext().getPackageName());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

请问您能否为此添加一个解释或提供获取此内容的链接? - Just The Highlights

0

如果您想要一个更简洁的解决方案:

void deleteDirectory(String path) {
  Runtime.getRuntime().exec(String.format("rm -rf %s", path));
}

2
你可能想要引用该路径,以防它包含空格和其他特殊字符。 - TWiStErRob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接