Settings中“清除数据”流程

本文详细解析了Android系统设置中清除应用数据的实现过程,从触发类`AppStorageSettings.java`,到按钮点击回调,展示数据清除对话框,直到最终通过`ActivityManager`的`clearApplicationUserData`方法清除数据并发送广播。涉及关键方法包括`initiateClearUserData()`、`processClearMsg()`以及AMS中的权限检查和数据清理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、具体触发类:

src/com/android/settings/applications/AppStorageSettings.java

 

2、具体按钮:

mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA))
                .findViewById(R.id.button);

 

3、具体回调: 

@Override
    public void onClick(View v) {

。。。

else if (v == mClearDataButton) {
            if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) {
                RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
                        getActivity(), mAppsControlDisallowedAdmin);
            } else if (mAppEntry.info.manageSpaceActivityName != null) {
                if (!Utils.isMonkeyRunning()) {
                    Intent intent = new Intent(Intent.ACTION_DEFAULT);
                    intent.setClassName(mAppEntry.info.packageName,
                            mAppEntry.info.manageSpaceActivityName);
                    startActivityForResult(intent, REQUEST_MANAGE_SPACE);
                }
            } else {
                showDialogInner(DLG_CLEAR_DATA, 0);
            }
        } 

。。。

 

4、弹出dialog:

showDialogInner(DLG_CLEAR_DATA, 0);

 

5、弹dialog方法:

 @Override
    protected AlertDialog createDialog(int id, int errorCode) {
        switch (id) {
            case DLG_CLEAR_DATA:
                return new AlertDialog.Builder(getActivity())
                        .setTitle(getActivity().getText(R.string.clear_data_dlg_title))
                        .setMessage(getActivity().getText(R.string.clear_data_dlg_text))
                        .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                // Clear user data here
                                initiateClearUserData();
                            }
                        })
                        .setNegativeButton(R.string.dlg_cancel, null)
                        .create();

 

6、具体清除方法:

private void initiateClearUserData() {
        mClearDataButton.setEnabled(false);
        // Invoke uninstall or clear user data based on sysPackage
        String packageName = mAppEntry.info.packageName;
        Log.i(TAG, "Clearing user data for package : " + packageName);
        if (mClearDataObserver == null) {
            mClearDataObserver = new ClearUserDataObserver();
        }
        ActivityManager am = (ActivityManager)
                getActivity().getSystemService(Context.ACTIVITY_SERVICE);
        boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
        if (!res) {
            // Clearing data failed for some obscure reason. Just log error for now
            Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
            showDialogInner(DLG_CANNOT_CLEAR_DATA, 0);
        } else {
            mClearDataButton.setText(R.string.recompute_size);
        }
    }

 

7、调用ActivityManager clearApplicationUserData方法时传了个mClearDataObserver,该Observer会在清除完成后发一个msg给handler,handler里会调用 processClearMsg

    private void processClearMsg(Message msg) {
        int result = msg.arg1;
        String packageName = mAppEntry.info.packageName;
        mClearDataButton.setText(R.string.clear_user_data_text);
        if (result == OP_SUCCESSFUL) {
            Log.i(TAG, "Cleared user data for package : "+packageName);
            mState.requestSize(mPackageName, mUserId);
            /// M ALPS00235193: send the clear success broadcast { @
            Intent packageDataCleared = new Intent(Intent.ACTION_SETTINGS_PACKAGE_DATA_CLEARED);
            packageDataCleared.putExtra("packageName", packageName);
            getActivity().sendBroadcast(packageDataCleared);
           /// @ }
        } else {
            mClearDataButton.setEnabled(true);
        }
    }

清除ok,发送一个广播,先不管。。。

 

8、跟踪到framework ams中:

am.clearApplicationUserData(packageName, mClearDataObserver);

方法具体行数如下:

 6026     public boolean clearApplicationUserData(final String packageName,
 6027             final IPackageDataObserver observer, int userId) {

        enforceNotIsolatedCaller("clearApplicationUserData");
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        userId = mUserController.handleIncomingUser(pid, uid, userId, false,
                ALLOW_FULL_ONLY, "clearApplicationUserData", null);


android.util.Log.d("jackpeng","clear pkg is "+packageName+"----uid is "+uid+"---pid is "+pid);
        long callingId = Binder.clearCallingIdentity();
        try {
            IPackageManager pm = AppGlobals.getPackageManager();
            int pkgUid = -1;
            synchronized(this) {
                if (getPackageManagerInternalLocked().canPackageBeWiped(
                        userId, packageName)) {
android.util.Log.d("jackpeng","throw exception");
                    throw new SecurityException(
                            "Cannot clear data for a device owner or a profile owner");
                }


                try {
                    pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId);
                } catch (RemoteException e) {
                }
                if (pkgUid == -1) {
                    Slog.w(TAG, "Invalid packageName: " + packageName);
                    if (observer != null) {
                        try {
                            observer.onRemoveCompleted(packageName, false);
                        } catch (RemoteException e) {
                            Slog.i(TAG, "Observer no longer exists.");
                        }
                    }
                    return false;
                }
                if (uid == pkgUid || checkComponentPermission(
                        android.Manifest.permission.CLEAR_APP_USER_DATA,
                        pid, uid, -1, true)
                        == PackageManager.PERMISSION_GRANTED) {
android.util.Log.d("jackpeng","permission is granted and uid is matched ");
                    forceStopPackageLocked(packageName, pkgUid, "clear data");
                } else {
                    throw new SecurityException("PID " + pid + " does not have permission "
                            + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data"
                                    + " of package " + packageName);
                }


                // Remove all tasks match the cleared application package and user
                for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
                    final TaskRecord tr = mRecentTasks.get(i);
                    final String taskPackageName =
                            tr.getBaseIntent().getComponent().getPackageName();
                    if (tr.userId != userId) continue;
                    if (!taskPackageName.equals(packageName)) continue;
                    removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
                }
            }


            final int pkgUidF = pkgUid;
            final int userIdF = userId;
            final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() {
                @Override
                public void onRemoveCompleted(String packageName, boolean succeeded)
                        throws RemoteException {
                    synchronized (ActivityManagerService.this) {
                        finishForceStopPackageLocked(packageName, pkgUidF);
                    }


                    final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
                            Uri.fromParts("package", packageName, null));
                    intent.putExtra(Intent.EXTRA_UID, pkgUidF);
                    intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
                    broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
                            null, null, 0, null, null, null, null, false, false, userIdF);


                    if (observer != null) {
                        observer.onRemoveCompleted(packageName, succeeded);
                    }
                }
            };


            try {
                // Clear application user data
                pm.clearApplicationUserData(packageName, localObserver, userId);


                synchronized(this) {
                    // Remove all permissions granted from/to this package
android.util.Log.d("jackpeng","remove permiison start ");
                    removeUriPermissionsForPackageLocked(packageName, userId, true);
                }


                // Remove all zen rules created by this package; revoke it's zen access.
                INotificationManager inm = NotificationManager.getService();
                inm.removeAutomaticZenRules(packageName);
                inm.setNotificationPolicyAccessGranted(packageName, false);


            } catch (RemoteException e) {
            }
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
        return true;
    }

 

 

 

 

 

 

 

<think>好的,用户现在问的是关于Android 13中的clearApplicationUserData流程。我需要回顾之前的对话,看看用户之前的问题是什么。之前用户询问了如何清空APK存储空间的流程,我介绍了用户手动操作和开发者通过代码实现的方法,还提到了分区存储和权限变化。 现在用户的问题是“android13 clearApplicationUserData流程”。首先,我要确定clearApplicationUserData是什么。根据我的知识,这是一个API方法,允许应用清除自己的用户数据。在Android开发中,这个方法会重置应用,类似于用户在设置里清除数据的效果。 接下来,我需要考虑用户可能的身份和使用场景。用户可能是一个Android开发者,或者是对Android系统操作感兴趣的高级用户。他们可能想知道如何在代码中使用这个API,或者了解背后的机制,特别是Android 13的变化。 用户之前的问题是关于清空存储空间的,现在具体到clearApplicationUserData,可能是在开发过程中需要实现类似功能,或者遇到了相关问题。需要确保回答涵盖使用方法、注意事项,以及Android 13的变更,比如权限、分区存储的影响等。 我需要解释clearApplicationUserData的作用,它是PackageManager中的一个方法,调用后会删除应用的数据目录、缓存、SharedPreferences、数据库等。同时,在Android 13下,可能需要处理新的权限或存储限制,比如分区存储导致的外部存储访问变化。 另外,用户可能关心的是如何正确使用这个API,是否有权限要求,以及可能出现的异常情况。比如,需要系统权限,或者只有系统应用才能调用,普通应用可能无法使用。此外,需要提到清除数据后的行为,比如应用可能被停止,需要重新启动。 还需要比较手动清除和应用调用API清除的区别,强调用户操作和程序化操作的不同。可能用户想知道在自动化测试或者特定功能中如何触发数据清除,比如在应用内提供一个“重置”按钮。 最后,确保回答结构清晰,分步骤说明使用方法,注意事项,并指出Android 13的特别之处。避免使用过于专业的术语,但作为技术性回答,必要的术语还是需要的,比如提到PackageManager、Storage API的变化等。</think>在 Android 13 中,`clearApplicationUserData()` 是一个系统级 API,允许应用(通常是系统应用或具有特殊权限的应用)清除自身的用户数据,其效果等同于用户在系统设置中手动点击「清除数据」操作。以下是该流程的详细介绍: --- ### **1. `clearApplicationUserData()` 的作用** 此方法会删除以下内容: - **内部存储数据**:应用私有目录(`/data/data/<package_name>`)中的所有文件,包括数据库、SharedPreferences 等。 - **外部存储私有目录**:通过 `getExternalFilesDir()` 或 `getExternalCacheDir()` 创建的文件。 - **缓存文件**:包括内部缓存(`cacheDir`)和外部缓存(`externalCacheDir`)。 - **用户配置**:登录状态、设置等所有用户生成的数据。 - **媒体库关联文件**(若应用未适配分区存储,可能残留媒体文件记录)。 调用后,应用会恢复到首次安装时的初始状态。 --- ### **2. 调用流程与权限要求** #### **代码实现**(需系统权限或设备所有者权限) ```java // 通过 PackageManager 调用 PackageManager pm = context.getPackageManager(); pm.clearApplicationUserData(packageName, null); // 需要系统权限(SYSTEM_UID)或设备所有者权限 ``` #### **权限限制**: - **普通应用无法直接调用**:此 API 需要 **`android.permission.CLEAR_APP_USER_DATA`** 权限,该权限仅授予系统应用(如系统设置、设备管理应用)。 - **替代方案**:普通应用可通过系统 Intent 引导用户手动清除数据: ```java Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); ``` --- ### **3. Android 13 的适配注意事项** 1. **分区存储(Scoped Storage)** - 应用通过 `clearApplicationUserData()` 清理外部存储私有目录时,系统会自动处理,无需额外适配。 - 若应用在公共目录(如 `Downloads`、`Pictures`)存储文件,需通过 `MediaStore` API 主动清理,否则残留文件可能保留。 2. **权限变更** - **不再依赖 `WRITE_EXTERNAL_STORAGE`**:Android 11+ 已废弃该权限,清理私有目录无需声明。 3. **数据残留风险** - 如果应用在公共媒体目录(如 `DCIM`)写入文件,需确保通过 `MediaStore` 删除记录,否则调用 `clearApplicationUserData()` 后文件可能仍保留在设备中。 --- ### **4. 调用后的行为** - **应用进程终止**:系统会强制停止应用进程。 - **数据不可恢复**:所有用户数据被永久删除(除非有备份)。 - **重新启动**:用户再次打开应用时,会触发首次启动流程。 --- ### **5. 适用场景** - **设备管理应用**:在企业设备管理中,远程清除用户数据。 - **系统工具应用**:提供深度清理功能(需系统权限)。 - **自动化测试**:在测试中重置应用状态。 --- ### **6. 与用户手动清除数据的区别** | **操作方式** | **权限要求** | **清理范围** | |--------------------|----------------------------------|------------------------------------------| | `clearApplicationUserData()` | 系统权限或设备所有者权限 | 完全清除私有数据,可能残留公共目录文件 | | 用户手动清除 | 无 | 同上,但需用户主动操作 | --- ### **总结** - **系统级操作**:`clearApplicationUserData()` 是高效的数据清理方法,但需系统级权限支持。 - **普通应用限制**:无权限的应用需引导用户手动操作。 - **Android 13 适配**:注意分区存储对公共文件清理的影响,避免数据残留。 如果需要为普通应用设计“清除数据”功能,建议通过删除私有目录文件(`filesDir`、`cacheDir` 等)实现部分清理,或依赖系统提供的用户操作流程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值