Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/mobile/app: minimal app stalls on Android #12378

Closed
rakyll opened this issue Aug 28, 2015 · 10 comments
Closed

x/mobile/app: minimal app stalls on Android #12378

rakyll opened this issue Aug 28, 2015 · 10 comments

Comments

@rakyll
Copy link
Contributor

rakyll commented Aug 28, 2015

$ cat main.go
package main

import "golang.org/x/mobile/app"

func main() {
    app.Main(func(a app.App) {
    })
}

I build and launch the application on an Android device. Once I touch on the back button, the app doesn't exit but stalls. InputDispatcher logs the following warning.

W/InputDispatcher(  750): Asynchronous input event injection failed.
I/InputDispatcher(  750): Dropped event because the current application is not responding and the user has started interacting with a different application.

And Android system dialog pops up, telling me " isn't responding. Do you want to close it?"

/cc @crawshaw @hyangah @nigeltao

@rakyll rakyll changed the title x/mobile: minimal app stalls on Android x/mobile/app: minimal app stalls on Android Aug 28, 2015
@crawshaw
Copy link
Member

That seems like a reasonable behavior. The app isn't responding to the events the OS is sending to it. What should it do instead?

@rakyll
Copy link
Contributor Author

rakyll commented Aug 31, 2015

The app isn't responding to the events the OS is sending to it.

The app event channel requires application to consume the events even if the app developer has no intent to handle the events. It is a hard requirement that is neither documented nor predictable.

@crawshaw
Copy link
Member

crawshaw commented Sep 1, 2015

I'm not sure there's much we can do about that. We could probably get past the initial stall (which is probably caused by the fact we don't return from onNativeWindowRedrawNeeded until a paint is successful) but before long the event channel will fill and the program will run out of memory. If we adopt @nigeltao's paint cycle proposal (which I would like to) it will take a lot longer to run out of memory, but it remains true: an empty app will not be successful on android.

@rakyll
Copy link
Contributor Author

rakyll commented Sep 1, 2015

Wouldn't it possible to drain the channel if there is not a subscriber? We shouldn't assume that the user must understand the internals of the package. If we begin to fill once user explicitly calls the Events accessor, the current behavior will be predictable.

@crawshaw
Copy link
Member

crawshaw commented Sep 1, 2015

An android app that doesn't process events isn't doing anything. What is the problem you are trying to solve?

@rakyll
Copy link
Contributor Author

rakyll commented Sep 1, 2015

An android app that doesn't process events isn't doing anything.

Please elaborate.

I am running sensor package (using the previous API) to collect data from a device. I don't need to handle lifecycle/paint events. Any package could be used in a standalone way will require user to consume the events channel. I don't understand this limitation.

@crawshaw
Copy link
Member

crawshaw commented Sep 1, 2015

We do not (yet?) support non-interactive apps. An all-Go app is an android Activity. An Activity interacts with the user, usually on the whole screen, sometimes on part of it. It gets something to draw on.

The program you are describing is, in android terms, a background service. An implementation of a background service is significantly different than what we have for all-Go apps. It doesn't have an Activity subclass, it doesn't get an icon on the screen (unless it's bundled as an app with an activity to start). Some further documentation:

http://developer.android.com/training/run-background-service

To build non-interactive apps that fit well within the android ecosystem requires far more design and implementation than draining the event channel. It requires the packaged program not be built on top of an Activity.

(As an aside: doesn't the reworked sensor package write to the event channel? Presumably you will be reading from it. The program will still be reported as not responding because of the current implementation of onNativeWindowRedrawNeeded, but even with that "fixed" so that apps that fail to draw are not caught by the OS, that's not enough to say we support non-interactive android programs.)

@nigeltao
Copy link
Contributor

nigeltao commented Sep 2, 2015

FWIW, I'm with crawshaw on this one. You might not need to handle lifecycle or paint events, but you should still receive on the events channel. I believe that this minimal app should work:

func main() {
app.Main(func(a app.App) {
for range a.Events() {
}
})
}

It might not work with the current paint.Event / a.EndPaint painting implementation, but I suspect that it should work with my proposed paint model.

As for if it's possible to drain the channel if there is not a subscriber? I don't think it's easy to do, and even if it would, it probably would make the API more complicated, and most likely make 'normal' app code more complicated. As crawshaw said, the app package is for what Android calls Activities, not background services, and any useful Activity should respond to events.

@rakyll
Copy link
Contributor Author

rakyll commented Sep 2, 2015

I think it is fair to classify the sensor data collecting app as a background service. I raised the issue because it was not clear what a minimal app must look like. Additionally, several spots on the minimal app creates confusion. I am wondering whether I could ever implement anything in the lines 1 and 3 below, and it is not obvious how these lines fit into the activity's lifecycle. Docs clarifying the questions below could have been useful.

func main() {
  // line1: should i ever put code before the Main function?
  app.Main(func(a app.App) {
    //  line2: what is the difference between this line and the main function's first line?
    for range a.Events() {
    }
  })
  // line3: is it ok to put code after the Main function? is it equivalent of onDestroy? 
}

@crawshaw
Copy link
Member

crawshaw commented Sep 2, 2015

The package docs for x/mobile/app show a minimal event loop and appears to answer the line2 and line3 questions. It also mentions that an app is an activity and visual, answering the question about banging services. If you want to clarify anything there, please send a CL.

@golang golang locked and limited conversation to collaborators Sep 4, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants