简体   繁体   English

屏幕关闭时调用Android onStart()事件

[英]Android onStart() event is called when the screen is turned off

I got an Android app which needs to load some data from a website and then display it. 我有一个Android应用程序,需要从网站加载一些数据然后显示它。 For that purpose, the user gets shown a loading bar, in a background thread loads the website and then it switches back to the main thread (with a Handler ) and displays the information. 为此,向用户显示一个加载栏,在后台线程中加载网站,然后切换回主线程(使用Handler )并显示信息。 So far so good, no problem here. 到目前为止一切顺利,这里没有问题。 But if the user turns off the phone while the information are being loaded and doesn't return when they are displayed, the app crashes. 但是,如果用户在加载信息时关闭了手机,却在显示信息时没有返回,则应用程序将崩溃。

So I need to interrupt the process when the user turns off his phone and retry it when he turns it on again. 因此,我需要在用户关闭手机时中断该过程,并在再次打开手机时重试。 This shouldn't be a problem, as explained here , there are a lot of events to do such things. 正如这里所解释的 ,这不应该是一个问题,有很多事件可以做到这一点。

But my debug messages showed, that the onStart() -Event (which would be perfect for my problem) is somehow called, when the user's phone is still turned off! 但是我的调试消息显示,当用户的手机仍处于关闭状态时, onStart() Event(对我的问题而言非常理想)被调用了! This causes bugs. 这会导致错误。 Is there any way to avoid that? 有什么办法可以避免这种情况?

Edit: Here's my code (trimmed, of course) 编辑:这是我的代码(当然,已修剪)

(MainActivity.java) (MainActivity.java)

private static MainActivity activity;
//Handler to run code from other threads in the main thread (needed to modify the GUI)
private static Handler handler;

private static ProgressBar progressBar;

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

    activity = this;
    handler = new Handler();

    [...]

}

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

    Log.e("s", "start");
    PageManager.mayContinue(true);

    if(PageManager.getCurrentPage() == null) {
        PageManager.loadPage(new StatusPage());
    }else{
        PageManager.loadPage(PageManager.getCurrentPage());
    }
}

@Override
public void onStop(){
    super.onStop();


    Log.e("s", "Stop");
    PageManager.mayContinue(false);
}

public static MainActivity getActivity(){
    return activity;
}

public static void runOnMainThread(Runnable r){
    handler.post(r);
}

(PageManager.java) (PageManager.java)

    private static Boolean isPageLoading = false;

private static Page currentPage;

private static boolean mayContinue;

public static void loadPage(final Page page){

    if(isPageLoading){
        return;
    }

    if(currentPage != null) {
        boolean allowedToLoadDifferentPage = currentPage.onPageLeft();
        if (!allowedToLoadDifferentPage) {
            return;
        }
    }

    isPageLoading = true;

    FragmentManager fragmentManager = MainActivity.getActivity().getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    DisplayFragment fragment = new DisplayFragment();
    fragment.setPage(page);
    fragmentTransaction.replace(R.id.display_fragment, fragment);
    fragmentTransaction.commit();

    MainActivity.getProgressBar().setVisibility(View.VISIBLE);

    Runnable r = new Runnable(){

        @Override
        public void run() {

            //Load the required data
            page.loadPage();

            isPageLoading = false;

            if(!mayContinue){

                MainActivity.runOnMainThread(new Runnable() {
                    @Override
                    public void run() {
                        MainActivity.getProgressBar().setVisibility(View.INVISIBLE);
                    }
                });

                Log.e("PageManager", "Loading process got blocked!");

                return;
            }

            currentPage = page;

            MainActivity.runOnMainThread(new Runnable() {

                @Override
                public void run() {
                    MainActivity.getProgressBar().setVisibility(View.INVISIBLE);
                    //Display the loaded data
                    page.setViewValues();
                }

            });
        }


    };

    new Thread(r).start();
}

public static Page getCurrentPage(){
    return currentPage;
}

public static void mayContinue(boolean value) {
    mayContinue = value;
}

A part of StatusPage.java: StatusPage.java的一部分:

@Override
public void setViewValues() {

    RecyclerView rv = (RecyclerView)MainActivity.getActivity().findViewById(R.id.insert_values);
    LinearLayoutManager llm = new LinearLayoutManager(MainActivity.getActivity());
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    rv.setLayoutManager(llm);

    RecyclerViewAdapter adapter = new RecyclerViewAdapter();
    rv.setAdapter(adapter);
    [...]
}

The LogCat: LogCat:

  03-21 07:50:38.109 6121-6121/de.namnodorel.app E/s: start   //The Activity got launched
    03-21 07:50:38.261 6121-6121/de.namnodorel.app E/RecyclerView: No adapter attached; skipping layout
    03-21 07:50:38.342 6121-6121/de.namnodorel.app E/RecyclerView: No adapter attached; skipping layout
    //I turn the phone off
    03-21 07:50:39.541 6121-6121/de.namnodorel.app E/s: Stop
    //??? (I didn't turn it on)
    03-21 07:50:40.326 6121-6121/de.namnodorel.app E/s: start
    //The app crashes because the findViewById() returned null (which means there is nothing with that ID on the current screen)
    03-21 07:50:41.337 6121-6121/de.namnodorel.app E/AndroidRuntime: FATAL EXCEPTION: main

                                                                      Process: de.namnodorel.app, PID: 6121
                                                                      java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
                                                                          at

de.namnodorel.app.game.status.StatusPage.setViewValues(StatusPage.java:47)
                                                                          at de.namnodorel.app.game.PageManager$1$2.run(PageManager.java:75)
                                                                          at android.os.Handler.handleCallback(Handler.java:739)
                                                                          at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                          at android.os.Looper.loop(Looper.java:135)
                                                                          at android.app.ActivityThread.main(ActivityThread.java:5294)
                                                                          at java.lang.reflect.Method.invoke(Native Method)
                                                                          at java.lang.reflect.Method.invoke(Method.java:372)
                                                                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
                                                                          at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)

I would expect onStart and onStop() to be also called, when the screen is turned off. 我希望在屏幕关闭时也可以调用onStartonStop() The docs say, they're called, when the Activity isn't visible anymore/visible again. 文档说,当“活动”不再可见/再次可见时,它们被称为。 And because when the screen is turned off, nothing is visible (or the LockScreen at least) I expect them to be called. 而且由于关闭屏幕后,看不到任何内容(或者至少是LockScreen),所以我希望它们被调用。 They are, but onStart() is called in the wrong place. 他们是,但是onStart()在错误的地方被调用。

Why is onStart() perfect for your problem? 为什么onStart()适合您的问题? Why not onCreate() ? 为什么不onCreate()呢?

One way to overcome this issue is to have a global boolean value set to true in the 克服此问题的一种方法是将全局布尔值设置为true

onRestart()

method. 方法。 And in the 而在

onStart()

method check if that boolean is true, if it is, do not go on with the process that causes bugs, otherwise, go on. 方法检查布尔值是否为真,如果是,则不要继续执行导致错误的过程,否则继续。 After that, in the 之后,在

onStart()

method set that boolean to false. 方法将布尔值设置为false。

May be you can do it another way. 也许您可以用另一种方式来做。 Register broadcast receiver with Intent.ACTION_SCREEN_OFF, Intent.ACTION_SCREEN_ON 使用Intent.ACTION_SCREEN_OFF,Intent.ACTION_SCREEN_ON注册广播接收器

OK, I've figured it out. 好,我知道了。 In the onStart() -Method I simply check if the screen is turned on or not. onStart()方法中,我只是检查屏幕是否打开。 If it's not, the call is not handled. 如果不是,则不处理该呼叫。 That's maybe not a solution, but at last a workaround. 那也许不是解决方案,但最后是一种解决方法。 This is what my code now looks like: 这是我的代码现在的样子:

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

    if(isScreenOn()) {
        PageManager.mayContinue(true);

        if(PageManager.getCurrentPage() == null) {
            PageManager.loadPage(new StatusPage());
        }else{
            PageManager.loadPage(PageManager.getCurrentPage());
        }
    }

}


@Override
public void onStop(){
    super.onStop();

    PageManager.mayContinue(false);
}

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

    if (Build.VERSION.SDK_INT < 21) {
        return pm.isScreenOn();
    }else{
        return pm.isInteractive();
    }
}

When a phone is turned off,is can be waked up by notifications or some other system services,may make your activity be active. 当手机关闭时,可以通过通知或其他系统服务唤醒,可能会使您的活动处于活动状态。

onStart() : Called when the activity is becoming visible to the user. onStart():在活动对用户可见时调用。

onResume(): Called when the activity will start interacting with the user. onResume():当活动将开始与用户进行交互时调用。

You may change to execute your code in onResume(). 您可以更改以在onResume()中执行代码。

If this is too late for you,you can add a judgement if phone is turned off by PowerManager. 如果这对您来说太迟了,您可以添加一个判断,以判断PowerManager是否关闭了电话。

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

相关问题 屏幕关闭时,Android加速度计无法正常工作 - Android accelerometer not working when screen is turned off Android-屏幕关闭或屏幕超时时终止应用 - Android - Kill an app when screen turned off or screen times out 如何在Android 5.0 Lollipop中关闭屏幕固定时收到通知? - How to be notified when screen pinning is turned off in Android 5.0 Lollipop? 屏幕关闭时,服务中的android加速计停止运行 - android accelerometer in service stops when screen is turned off 在Android中关闭屏幕时如何防止CPU“休眠”? - How to keep CPU from 'sleeping' when screen is turned off in Android? 屏幕关闭时,Android BroadcastReceiver不起作用 - Android BroadcastReceiver does'nt work when screen is turned off Android服务在屏幕关闭时停止收集数据 - Android service stops collecting data when the screen is turned off 屏幕打开/关闭时如何更新 Android 小部件? - How to update an Android widget when the screen is turned On/Off? 是否可以在 JavaScript 中检测到 Android 和 iOS 浏览器中的屏幕何时关闭 - Is it possible, in JavaScript, to detect when the screen is turned off in the Android & iOS browsers 为什么关闭屏幕时闪光灯也关闭了? - why the flash is turned off when the screen is turned off?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM