OpenSageTV / sagetv-miniclient

SageTV MiniClient for Android TV (and phone/tablet)
http://forums.sagetv.com/forums/showthread.php?t=62439
Apache License 2.0
19 stars 14 forks source link

Android N changes to StrictMode results in NetworkOnMainThreadException #56

Closed jrmull closed 8 years ago

jrmull commented 8 years ago

Verified that this causes an exception on the latest Android N developer preview (4) on a Nexus 6 such that the miniclient isn't usable.

AOSP issue 205605 addresses the change and is marked as 'WorkingAsIntended' so I wouldn't expect the behavior to change in dev preview 5 or the final version of Android N. The pertinent quote from the linked issue:

Hi, the upcoming version of android is tightening strict mode checks, with respect to the network traffic. Your app is trying to perform a socket write in the main thread, resulting in NetworkOnMainThreadException exception. So respective application has to take care of this, by not doing these operations in main thread.

stuckless commented 8 years ago

Perfect... Gotta love Google :( At this point, the changes that Google is making to Android, we are being left in a position whereby the Android MiniClient might become obsolete and unusable.

I can see Android warning about doing such a thing, since it decreases the user's performance for THIS application only... but to crash an application because of it, is stupid. At least this issue is likely fixable, especially since I didn't think I was doing any network operations on the main thread.

A bigger issue is the fact that if I compile against Android M or N, then ijkplayer is no longer a viable option because of other "security" changes that Google has done. As I said with each new release, Google is doing it's best to kill this project :( I can still use ExoPlayer, but it's so unstable that you can can't really call it an option :( (it is getting better though).

jrmull commented 8 years ago

I can see Android warning about doing such a thing, since it decreases the user's performance for THIS application only... but to crash an application because of it, is stupid.

I do find it peculiar that the exception apparently occurs even when StrictMode is disabled (as is recommended for apps distributed on Google Play). Maybe they're treating it more severely in N since 'Network requests on the UI thread are almost always a problem, though' (Google's words).

A bigger issue is the fact that if I compile against Android M or N, then ijkplayer is no longer a viable option because of other "security" changes that Google has done.

I don't want to get too off topic here but this ijkplayer issue (really FFmpeg) only impacts apps targeting >= API 23 on x86 devices correct? So x64 and arm stuff is still okay. Maybe the 'solution' is to just disable ijkplayer as an option only when running on x86 architecture once the miniplayer needs to target M or later? The Nexus Player is probably the only device that would be impacted and users of that device would have the option to stay on an older miniclient build until ExoPlayer is up to the task.

stuckless commented 8 years ago

Yeah, the problem with ffmpeg is that it's x86 only... If this were my full time job, I wouldn't care about having to create different builds with different configurations, etc... but this is my hobby :) and Google increasingly make it less fun :( Likely I will just drop x86 support when I decide to target M... or... I guess I'll have to check if you are running x86 and just auto-configure the player to be ExoPlayer. Either way... just more work when I'd rather spend my time adding more feature :( I don't think ExoPlayer is ready for the task of playing lots of different kinds of media... and I think I'd just be opening myself up for more support work, when people are forced to use it, and it doesn't work :(

As for the network thread on the UI... I'll have to see where that is happening... I've known for some time that doing work on the UI thread would cause other issues, so, I've been pretty good about trying to avoid that... but somehow, something did get through :( Do you have a stack trace for this... If not, I'll setup an emulator and reproduce it there... I'm just curious as to "where" this is happening in the code.

Thanks for the bug report... I'll try to get to this on the weekend, if not sooner.

jrmull commented 8 years ago

@stuckless I wanted to wait and make sure that this is still an issue on Android N DP5 which they just pushed yesterday. It is, so here are the stack traces for the first two exceptions thrown:

java.net.SocketException: Socket closed
    at java.net.PlainDatagramSocketImpl.receive0(Native Method) ~[na:0.0]
    at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:147) ~[na:0.0]
    at java.net.DatagramSocket.receive(DatagramSocket.java:811) ~[na:0.0]
    at sagex.miniclient.ServerDiscovery.discoverServers(ServerDiscovery.java:63) ~[na:0.0]
    at sagex.miniclient.ServerDiscovery$1.run(ServerDiscovery.java:25) ~[na:0.0]
    at java.lang.Thread.run(Thread.java:761) ~[na:0.0]
android.os.NetworkOnMainThreadException: null
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303) ~[na:0.0]
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111) ~[na:0.0]
    at java.net.SocketOutputStream.write(SocketOutputStream.java:157) ~[na:0.0]
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) ~[na:0.0]
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) ~[na:0.0]
    at java.io.DataOutputStream.flush(DataOutputStream.java:123) ~[na:0.0]
    at sagex.miniclient.MiniClientConnection.postSageCommandEvent(MiniClientConnection.java:1270) ~[na:0.0]
    at sagex.miniclient.uibridge.EventRouter.postCommand(EventRouter.java:64) ~[na:0.0]
    at sagex.miniclient.android.NavigationFragment.buttonClick(NavigationFragment.java:157) ~[na:0.0]
    at sagex.miniclient.android.NavigationFragment$1.onClick(NavigationFragment.java:76) ~[na:0.0]
    at android.view.View.performClick(View.java:5609) ~[na:0.0]
    at android.view.View$PerformClick.run(View.java:22259) ~[na:0.0]
    at android.os.Handler.handleCallback(Handler.java:751) ~[na:0.0]
    at android.os.Handler.dispatchMessage(Handler.java:95) ~[na:0.0]
    at android.os.Looper.loop(Looper.java:154) ~[na:0.0]
    at android.app.ActivityThread.main(ActivityThread.java:6077) ~[na:0.0]
    at java.lang.reflect.Method.invoke(Native Method) ~[na:0.0]
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) ~[na:0.0]
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) ~[na:0.0] 

Let me know if you need anything else. Thanks.

stuckless commented 8 years ago

This is great... I can see that this is definately doing IO on the main UI thread... and to be honest, it should not be... so maybe the Android N checks are good :) I still wish they'd "warn" about it instead of just crashing the app.

This shoud be easy enough to fix, but, I won't really change the responsiveness of the app... might even slow it down by a few MS :(

Thanks again for reporting it... and espeically for the stack trace.

On Tue, 19 Jul 2016 at 20:53 jrmull notifications@github.com wrote:

@stuckless https://github.com/stuckless I wanted to wait and make sure that this is still an issue on Android N DP5 which they just pushed yesterday. It is, so here are the stack traces for the first two exceptions thrown:

java.net.SocketException: Socket closed at java.net.PlainDatagramSocketImpl.receive0(Native Method) ~[na:0.0] at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:147) ~[na:0.0] at java.net.DatagramSocket.receive(DatagramSocket.java:811) ~[na:0.0] at sagex.miniclient.ServerDiscovery.discoverServers(ServerDiscovery.java:63) ~[na:0.0] at sagex.miniclient.ServerDiscovery$1.run(ServerDiscovery.java:25) ~[na:0.0] at java.lang.Thread.run(Thread.java:761) ~[na:0.0]

android.os.NetworkOnMainThreadException: null at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303) ~[na:0.0] at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111) ~[na:0.0] at java.net.SocketOutputStream.write(SocketOutputStream.java:157) ~[na:0.0] at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) ~[na:0.0] at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) ~[na:0.0] at java.io.DataOutputStream.flush(DataOutputStream.java:123) ~[na:0.0] at sagex.miniclient.MiniClientConnection.postSageCommandEvent(MiniClientConnection.java:1270) ~[na:0.0] at sagex.miniclient.uibridge.EventRouter.postCommand(EventRouter.java:64) ~[na:0.0] at sagex.miniclient.android.NavigationFragment.buttonClick(NavigationFragment.java:157) ~[na:0.0] at sagex.miniclient.android.NavigationFragment$1.onClick(NavigationFragment.java:76) ~[na:0.0] at android.view.View.performClick(View.java:5609) ~[na:0.0] at android.view.View$PerformClick.run(View.java:22259) ~[na:0.0] at android.os.Handler.handleCallback(Handler.java:751) ~[na:0.0] at android.os.Handler.dispatchMessage(Handler.java:95) ~[na:0.0] at android.os.Looper.loop(Looper.java:154) ~[na:0.0] at android.app.ActivityThread.main(ActivityThread.java:6077) ~[na:0.0] at java.lang.reflect.Method.invoke(Native Method) ~[na:0.0] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) ~[na:0.0] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) ~[na:0.0]

Let me know if you need anything else. Thanks.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/OpenSageTV/sagetv-miniclient/issues/56#issuecomment-233809397, or mute the thread https://github.com/notifications/unsubscribe-auth/ABAfKZpF9eM9DLIt3Ps1Xm0nuq21MBA4ks5qXXGGgaJpZM4JOYYF .

Sent from Android