2

我想知道,可能在我的活动的 onCreate() 中,如果应用程序之前按照正常的主页/返回按钮关闭,或者用户是否实际进入 Android 设置并选择强制关闭。

是否可以区分这两种情况?

编辑:

我想我可能没有很好地解释我的意思。我已经阅读了活动生命周期文档,我对此非常了解。

基本上,我只想知道活动是什么时候创建的,用户之前是否进入过 Android 设置并点击了强制停止。如果应用程序被强制停止,我想采取行动(特别是在启动时显示启动画面)。

下面的很多答案都说我可以在 onStop() 或 onDestroy() 中放置一个标志,并且如果用户点击强制停止,这些方法将不会被调用。问题是这些方法在到达那一点之前已经被调用了,因为这个序列:

  1. 应用处于活动状态,正在使用
  2. 用户点击返回按钮(onStop()、onDestroy() 调用)或主页按钮(onStop() 调用)或最近的应用程序按钮(onStop() 调用)
  3. 用户进入安卓设置,点击强制停止

在这种情况下,我会将标志放入 onStop() 上的共享首选项中,但随后用户点击强制停止,并且标志在 onCreate() 中仍处于活动状态。

除非用户在设置中点击了强制停止,否则我不想显示启动画面。我知道这不是应该做的……但这个决定不是我做的。

4

8 回答 8

1

我昨天遇到了同样的问题,就是我发现马克墨菲所说的。但我设法破解了它。

实际上,每当按下“强制停止”时,系统都会清除应用程序占用的所有内存,除了两件事。

1:the shared preference2:sqlite database

所以我通过在应用程序中存储一个布尔变量来完成这个技巧,操纵该值,然后在每次启动应用程序时检查它。它完成了。

常量.java

package com.mehuljoisar.forcestopdemo;

public class CONSTANTS {

//the changes made to value of below variable will be cleared on force stop,so whenever force stop occurs,the value of variable will be "isForceStopped=true" again.
    public static boolean isForceStopped = true;
}

MainActivity.java

package com.mehuljoisar.forcestopdemo;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {

    private Context mContext;
    private Intent i;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initialize();


        if(CONSTANTS.isForceStopped)
        {
        //this block of code will be executed in 2 scenario,
        //1: when application is started for very first time
        //2: when application is started after force stopping
            Toast.makeText(mContext, "Display Splash-screen and move to next screen", Toast.LENGTH_SHORT).show();
        //don't forget this part,it's important to make change so that next time splash screen can be avoided
             CONSTANTS.isForceStopped=false;

        //and then launch next screen
            launchSecondScreen();
        }
        else
        {
        //directly launch next screen
            launchSecondScreen();
        }
    }

    private void launchSecondScreen() {
        i.setClass(mContext, SecondActivity.class);
        startActivity(i);
        finish();
    }

    private void initialize() {
        mContext = this;
        i = new Intent();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

SecondActivity.java

package com.mehuljoisar.forcestopdemo;

import android.app.Activity;
import android.os.Bundle;

public class SecondActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

}

AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mehuljoisar.forcestopdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.mehuljoisar.forcestopdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.mehuljoisar.forcestopdemo.SecondActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我希望它会有所帮助!

于 2013-02-20T10:40:23.137 回答
1

我不确定是否有更简单的方法,但您可以创建一个 SharedPreferences 对象,该对象使用 Activity 的 onStop 函数中的标志进行更新。并检查 onCreate 中的标志。如果用户强制关闭应用程序,我认为不会调用 onStop 或 onDestroy。

于 2012-02-22T18:19:07.807 回答
0

您可以尝试保留所有应用程序生命周期事件的记录,然后检查您的各种onCreate()s记录的最后一个事件是否正常。如果不是,您可以合理地推断出发生了什么事。我猜用户调用的任何强制关闭只会导致系统向kill(2)应用程序发送一个,在这种情况下你不会收到任何指示。可能会有所帮助。

您还可以考虑是否可以以不同的方式实现您所追求的目标。如果您的应用程序完全是无状态的,那么任何类型的关闭都不会有问题。如果您的应用程序具有状态,那么理论上您的所有数据/应用程序事务都可以实现ACID性,因此您可以避免由于崩溃/强制关闭而导致的不一致。

这有帮助还是你在追求别的东西?

于 2012-02-22T18:37:45.640 回答
0

从服务而不是活动写入状态标志怎么样?活动生命周期仍将完成,但服务生命周期不应完成。

它与您的要求不同,但可能足够接近。如果您显示的活动没有此要求,您可能希望停止服务(并稍后重新启动)。或者只是让服务编写某种事件流并使用它来确定启动时要显示的内容。

于 2012-03-17T05:25:17.127 回答
0

如果用户使用“强制关闭”关闭了您的应用程序,则“onStop”方法不会执行。您可以在该方法中放置一个标志(如保存在文件中、用户首选项、sql 等)。下次应用程序启动时,请检查该标志!

于 2012-02-22T18:15:45.000 回答
0

覆盖onBackButtonPressed您的 Home 活动(在正常情况下,当使用后退按钮时,应用程序主活动已关闭)。

在此函数中设置一个变量(例如,lastforceClose 为 false)SharedPreferences,然后调用 onbackbuttonpressed() 或 finish() 的超级方法来完成活动。

下次无论何时开始活动时,您都可以检查 sharedpreferences 中的变量以查看 lastforceClose 变量是否设置为 false (您自己现在将其更改为 true)...

当用户通过 android 设置时,您可能还想在此处处理案例deleted data..(即共享首选项 xml 文件中不存在密钥等)

于 2012-02-22T18:17:58.647 回答
0

我不是 100% 确定,但这应该可行。
1)在一些持久存储上的Activity的onDestroy中保存状态(正常关闭)。(SharedPreferences 或 SQLite)
2)在 onCreate 检查状态,如果是正常关闭,则应用程序正常关闭,否则强制关闭。重置状态。

于 2012-02-22T18:18:45.607 回答
0

首先,听起来您可能会将恢复与创建混淆。一定要通读 App 基础知识,特别是关于Activity Lifecycle的内容。该状态图很有帮助。

当用户“退出”应用程序时,它不一定被销毁。事实上,它可能不会被销毁,除非开发人员在其中添加了一些onPause()明确销毁 Activity 的钩子。

Android 应用程序生命周期中最重要的一个概念是:

Android 操作系统绝对不保证您的应用程序将存活多久,除了保证它随时可能死亡,无论您是否愿意。

您应该始终相应地编写您的应用程序,并且填充生命周期中的每一个启动和结束钩子是一种很好的做法。当用户从您的应用程序中退出硬件按钮时,应用程序不一定会被破坏,但是当应用程序通过强制退出关闭时,它绝对会被破坏。与其试图弄清楚应用程序是如何关闭的,“正确”的处理方法是让你的onPause()onStop()onDestroy()方法设置为根据活动的状态进行适当的清理工作,并且可能有某种 Preference 对象或状态变量,只有在以下情况下才会被翻转onDestroy()被调用,因为从技术上讲,即使用户没有通过任务管理器这样做,操作系统仍然可以为您“强制退出”应用程序。

于 2012-02-22T18:20:41.143 回答