【问题标题】:Is it possible to restart Android App after calling ActivityManager.clearApplicationUserData()调用 ActivityManager.clearApplicationUserData() 后是否可以重新启动 Android App
【发布时间】:2019-12-20 12:15:06
【问题描述】:

我当前的 Android 应用程序需要调用

 ActivityManager.clearApplicationUserData()

模拟用户清空App存储

效果很好。

调用clearApplicationUserData() 的副作用是应用程序(可以理解地)关闭。

这会带来糟糕的用户体验。

拨打clearApplicationUserData() 后,我无法重新启动我的应用程序。

我已尝试将startActivityAlarm ManagerPending IntentForeground/Background 服务一起使用。

没有任何作用。

调用clearApplicationUserData()的Android App是否无法重启?

【问题讨论】:

  • 我的猜测是您的应用程序最终处于停止状态,就好像用户单击了“强制停止”一样。所有未完成的警报、作业等都将被取消。 “调用clearApplicationUserData()的Android应用程序是否无法重新启动?” - 我怀疑这在您自己的应用程序中是可能的。向用户显示一条消息,说明这将在调用该方法之前发生,并且用户可以从启动器重新启动应用程序。
  • 我认为这是它的构建目的.. 带有待处理意图的警报管理器,前景/背景无论如何都会变得清晰..如果您要使用clearApplicationUserData,那么这将是所需的流程..你可以签出它的源代码..
  • @CommonsWare 无论如何我可以启用详细日志记录(或类似的)以查看调用此方法时实际发生的情况?
  • 我不知道您所说的“实际发生了什么”是什么意思,但您可以查看 Logcat 以查看正在记录的内容。如果您在 Android Studio 中查看它,请将严重性过滤器切换为“详细”,并确保将结束下拉菜单设置为“无过滤器”,以查看所有消息。
  • 我过去也曾走上类似的道路。最终,手动擦除数据库和共享首选项并重新启动MainActivity 会更容易。如果这是可能的,强烈推荐!如果没有,也许类似于使用WorkManager 安排一个任务(不受清除应用数据影响(?))来启动您的活动?

标签: android android-intent


【解决方案1】:

第一个答案:此答案仅适用于有限的情况。这不是一个完整的答案)

public boolean clearApplicationUserData()

Description

返回true如果应用程序成功请求删除应用程序的数据; false 否则。

正如参考网站所述,在申请关闭之前,我们有一个返回者。所以,我们将使用这个returnee来重启应用。

if(ActivityManager.clearApplicationUserData)
{
     doRestart = true;
}

当ActivityonDestroy()onStop()被调用时重启应用。

   @Override
   protected void onDestroy() {
       super.onDestroy();
       if(doRestart){
           Intent intent = new Intent(this, Activity.class);
           this.startActivity(intent);
       }
   }

    @Override
    protected void onStop() {
        super.onStop();
        if(doRestart){
            Intent intent = new Intent(this, Activity.class);
            this.startActivity(intent);
        }
    }

我们在onDestroy()onStop() 中都设置了重启操作,以确保应用会再次重启。

另外,我认为在操作系统停止活动之前强制停止活动是个好主意。

if(ActivityManager.clearApplicationUserData)
{
     doRestart = true;
     finish(); <= i mean this 
}

这是因为它确保onDestroy()onStop() 将被调用。

【讨论】:

  • 在调用ActivityManager.clearApplicationUserData() 后,应用程序进程被强制终止。没有其他代码行被执行。
  • @Onik 你试过了吗?当 Activity 关闭时,总是调用 onDestroy() 。官方消息称它返回一个布尔值,否则它应该返回 void 。
  • 我当然试过了,为什么要写这么详细的评论呢?如果您有其他方法调用行为,我猜 API 实现会有所不同,这使得您的解决方案操作系统版本特定。
  • @Mr.AF 感谢您花时间回答。我一定会试试你的解决方案
  • @Onik 看我的下一个答案 :)
【解决方案2】:

我的建议可能听起来微不足道,但是您是否考虑过不打电话给ActivityManager.clearApplicationUserData()

docs 对此方法的评价如下:

允许应用程序从磁盘中擦除自己的数据。这是 相当于用户选择从内部清除应用的数据 设备设置 UI。它会清除所有与 app -- 其私有数据和外部私有区域中的数据 存储——但不会删除已安装的应用程序本身,也不会删除 任何 OBB 文件。

因此,为了模仿这种行为,您只需清除内部和外部存储目录即可。访问其中任何一个都不需要权限。

【讨论】:

    【解决方案3】:

    第二个答案:我需要更多的贡献)

    在 Android 操作系统和Android Developers 网站中进行了 8 小时研究,以便找到在调用clearApplicationUserData 时重新启动活动的解决方案。最后,我将能够找到一个 nice/hacking 解决方案。

    这个解决方案看起来像齐达内运球 :)

    让我们介绍一下解决方案。一开始clearApplicationUserData在被任务、通知、警报等调用时会清除应用程序的所有线索,因此显式Activity调用是不可能的。

    隐式方式是唯一可能的调用活动的方式。

    经过几次测试,我发现应用程序manifest 注册了intent-filters 不会被删除,并且它们能够监听传入的系统广播

    已清除的应用程序大约不会收到 98% 的系统广播,剩下的 2% 可能不会很快广播.

    那该怎么办?嗯?来吧伙计,我必须找到解决方案...

    宾果游戏,**我必须触发一些东西才能系统广播它**

    所以我决定选择 WIFI_STATE_CHANGED 因为

    • 轻松访问权限
    • 系统延迟广播它这确保应用程序已关闭 播出前

    manifest.xml

    <receiver
       android:name=".PackageDataClearedReceiver"
       android:enabled="true"
       android:exported="true">
         <intent-filter android:priority="100">
           <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
           <action android:name="android.net.wifi.STATE_CHANGE" />
         </intent-filter>
     </receiver>
    

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
        ActivityManager am;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            AppCompatButton btn = findViewById(R.id.btn);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            am = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
                            if (am != null) {
                                ExecutorService pool = Executors.newFixedThreadPool(2);
                                final Collection<Future> futures = new HashSet<Future>();
                                futures.add(pool.submit(new Runnable() {
                                    @Override
                                    public void run() {
                                        WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                                        wifiManager.setWifiEnabled(true);
                                        wifiManager.setWifiEnabled(false);
                                        am.clearApplicationUserData();
                                    }
                                }));
                                for (Future future : futures) {
                                    future.isDone();
                                }
                            }
    
                        }
                    }).start();
                }
            });
        }
    }
    

    演示

    请记住,它只是一个最低限度的可行产品,需要进一步开发才能使其完美运行。

    【讨论】:

    • 这种方法不适用于我的应用程序,因为我已经检测到 WIFI 状态的变化以向我的用户显示消息,如果我在每次 WIFI 状态变化时采用第二种解决方案的方法,我将开始我的主要活动
    • @Hector 是的,它需要更多的开发和定制以满足您的需求,因为我说它是最小可行产品。您需要定制它
    • @Hector 您需要在 Receiver 中设置条件以便在需要时重新启动活动
    • @AFarmanbar:PackageDataClearedReceiver 是什么?
    • @MehulKabaria 这只是一个启动活动的简单广播接收器。
    【解决方案4】:

    通过 API clearApplicationUserData() 清除设备上的应用数据会重置应用,就像它刚刚安装一样。正如您所发现的,在您的应用中注册的所有警报和广播也会被清除。正如其他人所指出的那样,将您的应用程序保持在前台的最有效方法是自己清除数据,而不是使用 API。这是一个例子:https://stackoverflow.com/a/9073473/949224


    不过,如果你确定要使用 API(保证所有数据都被清除)并且应用被强制停止,我有一个建议:

    创建一个可以在您清除应用数据之前启动的小型配套应用。配套应用只是重新启动您的应用,可能在短暂的超时后。

        Intent launchIntent = getPackageManager().getLaunchIntentForPackage("example.com.testrelaunchapp");
        if (launchIntent != null) {
            startActivity(launchIntent);//null pointer check in case package name was not found
        } else {
            Log.w( TAG, "Unable to resolve launch activity of relauncher companion app");
        }
    
        ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE))
                        .clearApplicationUserData();   
    

    配套应用程序本身需要在之后关闭,理想情况下应该从 Activity Stack 等中隐藏起来。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final Intent launchIntent = getPackageManager().getLaunchIntentForPackage("example.com.yourmainapp");
        if (launchIntent != null) {
            Handler handler = new Handler(getMainLooper());
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i( TAG, "About to act on launchIntent");
                    launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(launchIntent);
                    finish();
                    System.exit(0);
                }
            }, 1000);
        }    
     }     
    

    我已经在 Android 6.0 上看到过这项工作,但不能保证它是通用的并且可以全面工作。如果需要,还需要做更多的工作来使配套应用程序的 UI 更少,并从手机的启动器中隐藏。您可能还希望将 APK 捆绑为您自己的应用程序中的文件并在首次运行时安装它,这需要用户启用从“未知来源”(非 Play 商店)安装。如果需要,可以通过对正确系统设置的意图来完成,但用户需要很好地解释为什么需要这样做。

    所以,正如我所说,更简单的方法是自己清除数据和应用权限。

    【讨论】:

    • 我认为这不是可行的解决方案。因为您的解决方案需要额外安装的软件包,这使得它不可能。如果我们能够拥有额外的包或配套应用程序,那么将有很多方式开始活动。
    • 当然可以提示用户安装您自己的另一个应用程序。问题是您是否希望将此行为作为您操作方式的一部分。正如我所提到的,我不会推荐它,但原则上仍然值得一提这个想法,以防它对其他人有用。
    猜你喜欢
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多