简体   繁体   English

用户关闭屏幕后是否开始活动?

[英]Start activity when user turns screen off?

I have an app whose security I would like to improve. 我有一个想要提高安全性的应用程序。 When the user unlocks the device I would like the app to return to the login screen so that an intruder cannot use the app just by unlocking the device and having the app resume its original state. 当用户解锁设备时,我希望应用程序返回登录屏幕,以使入侵者无法仅通过解锁设备并使应用程序恢复其原始状态就可以使用该应用程序。

I'm using a BroadcastReceiver to detect when power button is pressed but this currently results the login screen being loaded regardless of whether the user was using the app just before they pressed the power button. 我正在使用BroadcastReceiver来检测何时按下电源按钮,但这当前导致登录屏幕被加载,而不管用户在按下电源按钮之前是否正在使用该应用程序。

Below I have included my BroadcastReceiver code, perhaps somebody could shed some light on this issue if possible? 在下面,我包括了我的BroadcastReceiver代码,如果可能的话,也许有人可以阐明这个问题?

public class ScreenReceiver extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            Intent n = new Intent(context, MainActivity.class);
            context.startActivity(n);
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            wasScreenOn = true;
        }
    }
}

When a user clicks on the home button , onPause() and onStop() gets called. 当用户单击主页按钮时 ,将调用onPause()和onStop()。 When they click on the back button (to exit the app), onPause(), onStop(), and finally onDestory() gets called. 当他们单击后退按钮 (退出应用程序)时,将调用onPause(),onStop()和onDestory()。 Finally, when they press the power button , onPause() and onStop() gets called. 最后,当他们按下电源按钮时 ,将调用onPause()和onStop()。

They all have onPause() being called first. 它们都有onPause()首先被调用。 Override onPause() and go back to the main activity using intent. 覆盖onPause()并使用intent返回主活动。 You can also clear the stack of activities so they can't hit the back button to go back into one. 您还可以清除活动堆栈,以使它们无法单击“后退”按钮返回到一项。

MainActivity 主要活动

public class MainActivity extends AppCompatActivity {

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

        Button goPrivate = (Button) findViewById(R.id.goPrivate);

        goPrivate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, Private.class));
            }
        });
    }
}

activity_main.xml activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.vzw.www.myapplication.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MAIN"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="GO TO PRIVATE"
        android:id="@+id/goPrivate"/>

</RelativeLayout>

Create a new activity. 创建一个新的活动。 I named mine Private.java 我命名为Private.java

Private.java 私有.java

public class Private extends AppCompatActivity {

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

    @Override
    protected void onPause() {
        super.onPause();
        startActivity(new Intent(Private.this, MainActivity.class));
    }
}

activity_private.xml activity_private.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.vzw.www.myapplication.Private"
    android:layout_gravity="center">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PRIVATE!"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Just create a blank project in Android Studio and try this. 只需在Android Studio中创建一个空白项目,然后尝试即可。 It works! 有用! :) :)

What happens if we click into ANOTHER activity and go deep into the app? 如果我们单击另一个活动并深入应用程序,会发生什么?

Create a boolean inside of Private class. 在Private类内部创建一个布尔值。

boolean goSuperClicked = false;

Updated private class is below: 更新后的私有类如下:

public class Private extends AppCompatActivity {

    Button goSuper;
    boolean goSuperClicked = false;

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

        goSuper = (Button) findViewById(R.id.goSuper);

        goSuper.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                goSuperClicked = true;
                startActivity(new Intent(Private.this, SuperPrivate.class));
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d("onPause()", "onPause called");
        if (!goSuperClicked) {
            startActivity(new Intent(Private.this, MainActivity.class));
        }

    }
}

I don't think this is actually what you want. 我认为这实际上不是您想要的。 If they have a lock screen, they had to enter a password on it. 如果他们有锁定屏幕,则必须在屏幕上输入密码。 You can be fairly sure its the right person. 您可以确定它是合适的人。 If you want this kind of behavior, you want to timeout the session due to inactivity instead. 如果您想要这种行为,则由于不活动而希望使会话超时。

Either way, the solution is the same. 无论哪种方式,解决方案都是相同的。 In onResume, you should check to see if they timed out/went to the lock screen. 在onResume中,您应该检查它们是否超时/进入锁定屏幕。 If so, launch the login screen as a new task (that will prevent the back button from taking you back to this screen) and finish() the current activity. 如果是这样,将登录屏幕作为一个新任务启动(这将阻止后退按钮将您带回到该屏幕),并完成()当前活动。 Pass the login screen some info so it can recreate the current activity. 向登录屏幕传递一些信息,以便它可以重新创建当前活动。 When the user is verified, check for that info and create the proper activity from it. 验证用户后,检查该信息并从中创建正确的活动。 If the info doesn't exist, launch your standard homescreen. 如果该信息不存在,请启动标准主屏幕。

The easiest way to pass it enough info to create the new Activity is to pass it a Bundle with the activity name or url, and the results of calling onSaveInstanceState. 传递足够信息以创建新Activity的最简单方法是,将包含活动名称或URL以及调用onSaveInstanceState的结果的Bundle传递给它。

Some suggestions: 一些建议:

1) Set up a broadcast receiver that detects a screen on/off intent. 1)设置检测屏幕开/关意图的广播接收器。

Intent.ACTION_SCREEN_OFF and ACTION_SCREEN_ON

2) Implement broadcast receiver that starts Activity when it matches Screen off. 2)实现广播接收器,当它与“ 屏幕关闭”匹配时启动“活动”

3) Detect Screen off and on via PowerManager 3)通过PowerManager检测屏幕的开与关

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();

4) Since screen off happens on onStop() callbacks, therefore, you have to put above code inside onStop() callbacks of your Activity lifecycle. 4)由于屏幕关闭发生在onStop()回调上,因此,您必须将以上代码放入Activity生命周期的onStop()回调中。 Something like below. 像下面这样。

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    boolean isScreenOn = pm.isScreenOff();
if(isScreenOn) {
 sendBroadcast(<your_screenOff_intent);
}

This is the way, but because of the security lock (to open your device), I think, it can't be implemented. 这样,但是由于安全锁(打开设备),我认为它无法实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM