2012-02-22 78 views
2

我想知道,可能在我的活动的onCreate(),如果应用程序以前按照正常的家庭/后退按钮关闭,或者如果用户实际上进入Android设置并选择强制关闭。是否有可能知道应用程序是否在用户通过设置强制退出后启动?

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

编辑:

我想我可能没有解释我的意思不够好。我已经阅读了活动生命周期文档,并且我非常了解这一点。

基本上,我只想知道什么时候创建活动,无论用户是否先前进入了Android设置并强行停止。如果应用程序被强制停止,我想采取一个行动(具体来说,启动时显示启动画面)。

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

  1. 应用程序处于激活状态时,使用
  2. 用户点击后退按钮(的onStop()的onDestroy ()调用),或home键(的onStop()调用),或最近使用的应用按钮(的onStop()调用)
  3. 用户进入Android设置,水龙头强行停止

在这种情况下,我将有将标志放入onStop()的共享偏好设置中,但用户点击强制停止并且标志为stil l在onCreate()中激活。

我不想显示启动画面,除非用户在设置中强制停止。我知道这不是应该被做的方式......但这个决定不是由我做出的。

+0

总是在onCreate()中显示启动画面。 onCreate()仅在应用程序完成时调用。点击“返回”按钮不会调用onDestroy()。退出到主屏幕,然后重新启动应用程序将调用onResume(),而不是onCreate()。我原来的答案是。你误解了生命周期。 – 2012-02-22 20:06:50

+0

事实是,当用户按下后退按钮时,总是调用onDestroy()。尝试一下!按回来,然后重新启动应用程序将导致onCreate()被调用。 – howettl 2012-02-22 20:54:58

+0

此外,onDestroy()/ onCreate()也会在设备方向更改时调用。我绝对不希望我的启动画面在任何时候改变方向。 – howettl 2012-02-22 21:02:56

回答

1

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

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

1:the shared preference2:sqlite database

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

CONSTANTS.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> 

我希望这会有所帮助!

+0

此解决方案无法正常工作 – bCliks 2014-08-03 05:27:15

+0

@bala:是什么问题?它在我所有的应用程序中都能正常工作。 – 2014-08-03 09:51:10

+0

打开你的应用程序,然后返回到主主屏幕。按住主页按钮查看最近使用的应用程序列表。现在从该列表中滑动并关闭您的应用。在这种情况下,该解决方案失败在这种情况下'isForceStopped = true'。这就是为什么我告诉这个解决方案工作不正常。我对么?任何想法? – bCliks 2014-08-03 13:28:52

0

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

0

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

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

下一次,当你开始你可以检查出在sharedpreferences变量的活动,看看lastforceClose变量,如果它要么设置为false或没有(和你自己现在改为true)...

你可能也想在这里处理案例,当用户有deleted data通过Android设置..(即密钥不存在于共享首选项xml文件等)

+0

这不会将用户击回家而不是返回。它也不考虑用户回击,然后进入设置和关闭力量。 – howettl 2012-02-22 18:59:20

+0

当用户点击主页按钮时,活动并没有完全被杀死......您可以在最大程度上将其展开,但您永远不会想要在主页按钮点击(案例1的评论)时停止您的应用程序......此外,你根据正常行为定义'closed',正如你可以通过覆盖后退按钮实际调用'按照正常行为正确关闭'(第二种情况在注释中提到的) – 2012-02-22 19:17:48

+0

我知道当用户点击主页按钮。我不想以编程方式停止应用程序。我只想知道活动何时开始,无论用户是否在设置中强制停止。 – howettl 2012-02-22 19:21:09

0

我不是100%肯定,但这应该工作。
1)在某些永久存储上的Activity的onDestroy中保存状态(正常关闭)。(SharedPreferences或SQLite)
2)在onCreate检查状态,如果它是正常关机,那么应用程序通常关闭,否则强制关闭。重置状态。

0

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

1

首先,它听起来像你可能会混淆恢复与创建。绝对通读应用基础知识,特别是关于Activity Lifecycle的内容。该状态图很有帮助。

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

在Android应用程序的生命周期要了解的一个最重要的概念是这样的:

Android操作系统完全不会有什么关于你的应用将持续多久还活着的保证,除了保证它可以在任何时候死亡无论你想不想。

你应该总是相应编写你的应用程序,它是填充生命周期的每一一个启动和逐步减少挂钩很好的做法。当用户从你的应用程序中退出硬件按钮时,应用程序不会被销毁,但当应用程序通过强制退出而关闭时,它将被彻底销毁。与其试图想方设法了解应用程序是如何关闭的,处理此问题的“正确”方法是将您的onPause()onStop()onDestroy()方法设置为根据状态进行适当的清理量并且可能有某种Preference对象或状态变量,如果onDestroy()被调用,则只会翻转,因为从技术上讲操作系统仍然可以为您强制退出应用程序,即使用户不通过任务经理。

0

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

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

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

0

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

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

相关问题