运行应用程序两次才能正常工作。

20

我正在制作一个安卓应用程序,测试你手机上是否启用了某些安全功能。例如,如果你启用了密码登录或者手机上的数据是否加密。

但是不知何故,这个应用程序必须运行两次才能测试并查看手机上是否启用了这些安全功能,这是我试图解决的问题。我希望它在应用程序创建和第一次运行时就可以测试并查看这些安全功能是否已启用,而不是在第二次运行时再测试。

我在MainActivity文件的onStart()函数中测试这些功能是否已启用。下面是该函数的代码:

    @Override
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @SuppressLint("NewApi")
    public void onStart()
    {
        super.onStart();

        //determine if phone uses lock pattern
        //It returns 1 if pattern lock enabled and 0 if pin/password password enabled
        ContentResolver cr = getBaseContext().getContentResolver();
        lockPatternEnable = Settings.Secure.getInt(cr, Settings.Secure.LOCK_PATTERN_ENABLED, 0);//Settings.System 


        //returns 1 if pin/password protected. 0 if not
        KeyguardManager keyguardManager = (KeyguardManager) getBaseContext().getSystemService(Context.KEYGUARD_SERVICE);
        if( keyguardManager.isKeyguardSecure()) 
        {
           //it is pin or password protected
           pinPasswordEnable=1;
        } 
        else 
        {
           //it is not pin or password protected 
            pinPasswordEnable=0;
        }//http://stackoverflow.com/questions/6588969/device-password-in-android-is-existing-or-not/18716253#18716253

        //determine if adb is enabled. works
        adb=Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0);

        //determine if bluetooth is enabled.works
        bluetooth=Settings.Global.getInt(cr, Settings.Global.BLUETOOTH_ON, 0);
        //Settings.System BLUETOOTH_DISCOVERABILITY

        //determine if wifi is enabled. works
        WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
        if (wifi.isWifiEnabled())
        {
            //wifi is enabled
            wifiInt=1;
        }
        else
            wifiInt=0;

        //determine if data is encrypted
        getDeviceEncryptionencryption();

        //determine if gps enabled


    }//end of onStart() function
如果需要发布更多代码来回答这个问题,请告诉我,感谢您的帮助。也许问题与 super.onStart(); 有关。
有人认为添加启动画面可能会解决问题吗?
4个回答

7

这里有一个很好的解释,介绍了应用程序的生命周期流程。 onStart()方法可以被执行多次。你可以保持计数器记录进入该方法的次数,并在每次进入时采取不同的操作:

 static int counter=0;
 public void onStart()
    {
      counter++;
      Log.i("MyApp", "onStart() run "+counter);
      switch (counter){
        case 1: break; // first run
        case 2: break; // second run
        default: break;// other runs
      }
 }

为了更清楚地了解生命周期以及为什么会调用两次onStart()方法,建议在每个重要状态的周期中都有计数器和Log.i() - 至少在onCreate()和onRestart()中。
请记住,当您点击Home按钮时,应用程序仍然停留在内存中。当您再次点击应用程序图标时,它会重新启动正在运行的应用程序(调用onRestart()方法,然后是onStart()方法,而不是onCreate())。当您真正杀死应用程序时,序列将是onCreate和onStart而没有onRestart。拥有logcat记录确实有助于理解应用程序的生命周期流程以及为什么会多次调用onStart()方法。

如果应用程序被Android杀死并且用户返回应用程序,则此方法将无效。 - Emanuel Moecklin
你所描述的是让应用程序第一次运行。这是正确的。但 OP 正在询问第二次运行。如果你总是立即杀死应用程序,那么就没有第二次运行,这不是 OP 所请求的。 - Izold Tytykalo
谁说 Android 只在第一次运行时出现问题?这种情况随时都可能发生,例如在第三次运行后。你的代码会重新开始,并确定它又是第一次运行,显然是错误的。 - Emanuel Moecklin

2
使用静态变量来检查 onStart 被调用的次数不是一个好主意,因为当 Android 需要为其他应用程序提供更多内存时,该应用程序可能会被终止,同时允许用户返回到该应用程序。这将是以下图片中红色框线所示的路径(参见http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle):

enter image description here

一个静态变量在此之后会再次变成0,你的应用程序将再次运行安全检查。 你需要做的是使用实例变量,在onSaveInstanceState中进行持久化,并在onCreate中进行恢复。如果应用程序被杀死,onSaveInstanceState被调用并保存您Activity的状态。如果用户返回应用程序,则调用onCreate并恢复状态。这对于其他情况也适用,当应用程序没有被杀死,但用户只是导航离开应用程序,稍后重新打开它。以下是一个简单的应用程序保存和恢复的示例:
public class MainActivity extends Activity {

    private boolean mSecurityCheckDone;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
        }
    }

    @Override
    protected void onStart() {
        super.onStart();

        if (! mSecurityCheckDone) {
            // run the security check

            mSecurityCheckDone = true;
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putBoolean("mSecurityCheckDone", mSecurityCheckDone);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        if (savedInstanceState != null) {
            mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
        }
    }

}

1

使用标志(flag)怎么样?

singleTop

如果在目标任务栈的顶部已经存在该活动(Activity)的实例,则系统通过调用其onNewIntent()方法将意图(Intent)路由到该实例,而不是创建一个新的活动实例。

singleTask

系统会在新任务(Task)的根部创建该活动,并将意图路由到它。但是,如果该活动的实例已经存在,则系统会通过调用其onNewIntent()方法将意图路由到现有实例,而不是创建一个新的实例。

singleInstance

与 "singleTask" 相同,但系统不会将任何其他活动(Activity)启动到持有该实例的任务(Task)中。该活动始终是其任务(Task)的唯一成员。

http://developer.android.com/guide/topics/manifest/activity-element.html


0

如果您想要在活动首次创建时运行它,我不确定为什么要使用onStart(),我可能会使用onCreate()。

Android中没有API可以告诉您应用程序是否已经运行过至少一次,因此您需要使用某种类型的持久性存储,例如SharedPreferences可用于保留在第一次运行应用程序时设置的标志,然后您可以像here所示那样检查它。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    SharedPreferences settings = getSharedPreferences("Prefs", 0);
    if (settings.getBoolean("first_time", true)) {
        //the app is being launched for first time, do something        
        Log.d("Comments", "First time");

        // first time task

        // record the fact that the app has been started at least once
        settings.edit().putBoolean("first_time", false).commit(); 
    }
}

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