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

157

我正在使用Robotium为Android应用程序开发自动化测试。为确保测试的一致性和可靠性,我希望每次测试都以被测试应用程序的清空状态开始。为此,我需要清除应用程序数据。可以在“设置/应用程序/管理应用程序/[我的应用程序]/清除数据”中手动完成此操作。

有没有推荐的以编程方式实现此操作的方法?


使用adb工具在每次应用启动之间清除数据是可行的吗? adb -w - smith324
很遗憾,此选项不可用(adb帮助已过时)。 - user597603
这将会非常棒。当调试数据库问题时,我必须经常导航到“清除数据”选项,这确实打断了我的工作流程。 - Jason Prado
在这里讨论了如何通过Android Studio实现:https://dev59.com/pFwZ5IYBdhLWcg3wNOCI。 - user905686
具体而言,按照以下步骤操作:https://dev59.com/pFwZ5IYBdhLWcg3wNOCI#57461180 - Matt Wolfe
10个回答

176

你可以使用软件包管理工具清除已安装应用的数据(类似于在设备上的应用设置中按下“清除数据”按钮)。 因此,使用adb可以执行以下操作:

adb shell pm clear my.wonderful.app.package

1
在Android 2.1-update1上,这会不幸地产生“错误:未知命令'clear'”。 - Paul Lammertsma
@Palani:对我来说,在2.1-r1(andoid-7)以上的任何版本都可以工作。有任何错误信息吗? - edovino
1
以上命令连接到 Android shell 并在 Android 上执行 "pm clear my.wonderful.app.package"。在我的设备上,"pm" 命令没有 "clear" 选项。这与 sdk 无关,而是取决于设备固件。 - Palani
我正在寻找从我的Android应用程序以编程方式获取Android设备中浏览器(默认)和Chrome浏览器应用程序的清晰数据。请帮忙。 - Brijesh Patel
不能在每个设备上运行,但对于它能够运行的设备来说,它非常出色。 - Cory Trese

37

回应 @edovino 的答案,以编程方式清除一个应用程序的所有首选项的方法是:

private void clearPreferences() {
    try {
        // clearing app data
        Runtime runtime = Runtime.getRuntime();
        runtime.exec("pm clear YOUR_APP_PACKAGE_GOES HERE");

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

警告:应用将会强制关闭。


6
如果你在此之后运行任何测试代码,它都会失败。 - Rajath
执行这个操作需要在清单文件中声明任何权限吗? - reubenjohn
1
不需要任何特殊权限。 - Sebastiano
2
如果我不想強制關閉應用程序,那我該怎麼辦? - N J

22

你可以使用以下代码清除SharedPreferences应用数据

Editor editor = 
context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE).edit();
editor.clear();
editor.commit();

要清除应用程序数据库,此答案是正确的 -> 清除应用程序数据库


18

从API版本19开始,可以调用ActivityManager.clearApplicationUserData()。

((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).clearApplicationUserData();

16
请注意,调用此功能将终止您的应用程序。 - Zach Rattner

9

请检查以下代码:

@Override
protected void onDestroy() {
// closing Entire Application
    android.os.Process.killProcess(android.os.Process.myPid());
    Editor editor = getSharedPreferences("clear_cache", Context.MODE_PRIVATE).edit();
    editor.clear();
    editor.commit();
    trimCache(this);
    super.onDestroy();
}


public static void trimCache(Context context) {
    try {
        File dir = context.getCacheDir();
        if (dir != null && dir.isDirectory()) {
            deleteDir(dir);

        }
    } catch (Exception e) {
        // TODO: handle exception
    }
}


public static boolean deleteDir(File dir) {
    if (dir != null && dir.isDirectory()) {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++) {
            boolean success = deleteDir(new File(dir, children[i]));
            if (!success) {
                return false;
            }
        }
    }

    // <uses-permission
    // android:name="android.permission.CLEAR_APP_CACHE"></uses-permission>
    // The directory is now empty so delete it

    return dir.delete();
}

7
如果你只需要清除几个共享参数,那么这个解决方案更好
@Override
protected void setUp() throws Exception {
    super.setUp();
    Instrumentation instrumentation = getInstrumentation();
    SharedPreferences preferences = instrumentation.getTargetContext().getSharedPreferences(...), Context.MODE_PRIVATE);
    preferences.edit().clear().commit();
    solo = new Solo(instrumentation, getActivity());
}

这不需要启用“仪器模式”吗?那么什么是仪器模式呢? - ADTC
是的,这需要一个“仪器化”的应用程序,即您的测试与您的应用程序代码在真实设备上的同一进程中运行,这意味着您可以访问所有应用程序的状态并在运行时进行更改以进行测试。 - Thomas Keller
应该在括号中放什么? - NickUnuchek
@NickUnuchek 偏好设置文件的名称。 - Thomas Keller

3
使用Context,我们可以清除应用程序特定的文件,如偏好设置、数据库文件。我已经使用以下代码使用Espresso进行UI测试。
    @Rule
    public ActivityTestRule<HomeActivity> mActivityRule = new ActivityTestRule<>(
            HomeActivity.class);

    public static void clearAppInfo() {
        Activity mActivity = testRule.getActivity();
        SharedPreferences prefs =
                PreferenceManager.getDefaultSharedPreferences(mActivity);
        prefs.edit().clear().commit();
        mActivity.deleteDatabase("app_db_name.db");
    }

2
如果Android版本高于KitKat,您也可以使用此功能。
公共无返回类型的onClick(View view)方法:
    Context context = getApplicationContext(); // add this line
    if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) {
        ((ActivityManager) context.getSystemService(ACTIVITY_SERVICE))
            .clearApplicationUserData();
        return;
    }

1
什么是以编程方式推荐的完成此操作的方法?
唯一可能的选择是在测试之前运行ADB命令adb shell pm clear package。最大的问题是将测试执行和shell命令结合起来有点麻烦。
然而,我们(在Mediafe)提出了一些解决方案,可以在常规未root设备上为您工作。您需要做的就是添加一个注释。其余的都是通过运行简单的bash脚本完成的。
只需在任何测试之前添加@ClearData注释,然后tada,在测试执行之前将执行ADB清除命令。
这是这样一个测试的例子:
@Test
@ClearData
public void someTest() {
    // your test
}

这个想法如下所示

  1. 使用 adb shell am instrument -e log true 读取所有测试用例
  2. 通过解析(1)中的输出构建执行计划
  3. 逐行运行执行计划

使用相同的思路,您可以轻松支持以下所有选项:

  • 清除数据
  • 清除通知栏
  • 参数化
  • 按标签过滤和运行

只需使用注释。像这样:

@Test
@ClearData
@Tags(tags = {"sanity", "medium"})
@Parameterized.Repeat(count = 3)
public void myTest() throws Exception {
    String param = params[index];
    // ...
}

额外奖励! 对于每个失败的测试:

  • 收集 Logcat + 堆栈跟踪
  • 录制视频(mp4)
  • 转储 DB(sqlite)
  • 转储默认共享首选项(xml)
  • 收集 dumpsys 文件,如:电池、网络状态等。

总的来说,很容易添加更多选项,因为测试是从 bash 脚本而不是 gradle 任务逐个执行的。

完整博客文章https://medium.com/medisafe-tech-blog/running-android-ui-tests-53e85e5c8da8

带有示例的源代码https://github.com/medisafe/run-android-tests

希望这回答了六年的问题;)


0

这种由Sebastiano添加的方式是可以的,但是当您从IntelliJ IDE运行测试时,需要添加:

 try {
    // clearing app data
    Runtime runtime = Runtime.getRuntime();
    runtime.exec("adb shell pm clear YOUR_APP_PACKAGE_GOES HERE");

}

不要只有“pm package…”

更重要的是:在driver.setCapability(App_package, package_name)之前添加它。


在应用程序中使用runtime.exec时,您不能编写adb shell,您只需要从pm开始即可。 - S. Ber Rosenberg

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