自己实现的一个Socket聊天app,这个app是在17年的时候写的(当时也是随便写的,没注意太多细节),那个时候还是android4.4系统的手机,然后写完在真机上调试没有问题,最近时隔两年想拿出来完善下,结果装在android7.1系统的手机上发现能与服务端connect,但是每次输完信息一点登入的时候发现闪退,并且没有报任何的错误,然后感觉很奇怪,打开虚拟机,测试Android4.4版本的,发现没问题啊,能正常登入,然后找了很久的bug,无奈之下只能连接电脑打印真机上的系统日志了,具体如下:
cmp=com.example.socketchatclient/com.example.login.LoginActivity bnds=[27,1433][232,1723] (has extras)} from uid 10017 on display 0
03-20 19:42:19.737 1262 1297 I ActivityManager: Start proc 26019:com.example.socketchatclient/u0a75 for activity com.example.socketchatclient/com.example.login.LoginActivity
03-20 19:42:19.895 1262 1262 W NotificationService: Object died trying to hide notification android.app.ITransientNotification$Stub$Proxy@bcc7256 in package com.example.socketchatclient
03-20 19:42:19.895 1262 1262 W WindowManager: Attempted to remove non-existing token: android.os.Binder@5059ee8
03-20 19:42:19.936 26019 26037 D test1 : 连接成功
03-20 19:42:19.945 26019 26036 I Adreno-EGL: : EGL 1.4 QUALCOMM build: Nondeterministic_AU_msm8974_LA.BF.1.1.3_RB1__release_AU (Ia6c73e7530)
03-20 19:42:19.945 26019 26036 I Adreno-EGL: OpenGL ES Shader Compiler Version: E031.29.00.00
03-20 19:42:19.945 26019 26036 I Adreno-EGL: Build Date: 12/04/15 Fri
03-20 19:42:19.945 26019 26036 I Adreno-EGL: Local Branch: mybranch17080070
03-20 19:42:19.945 26019 26036 I Adreno-EGL: Remote Branch: quic/LA.BF.1.1.3_rb1.5
03-20 19:42:19.945 26019 26036 I Adreno-EGL: Local Patches: NONE
03-20 19:42:19.945 26019 26036 I Adreno-EGL: Reconstruct Branch: NOTHING
03-20 19:42:19.948 26019 26036 I OpenGLRenderer: Initialized EGL, version 1.4
03-20 19:42:19.948 26019 26036 D OpenGLRenderer: Swap behavior 1
03-20 19:42:19.960 26019 26019 D test1 : Broadcast
03-20 19:42:19.976 26019 26041 D test1 : read
03-20 19:42:20.019 1262 1364 I ActivityManager: Displayed com.example.socketchatclient/com.example.login.LoginActivity: +293ms
03-20 19:42:21.974 1262 1262 W WindowManager: Attempted to remove non-existing token: android.os.Binder@7a00573
03-20 19:42:23.407 27630 27630 W InputMethodService: Window size has been changed. This may cause jankiness of resizing window: -1 -> -2
03-20 19:42:29.691 26019 26019 D AndroidRuntime: Shutting down VM
03-20 19:42:29.692 26019 26019 E AndroidRuntime: FATAL EXCEPTION: main
03-20 19:42:29.692 26019 26019 E AndroidRuntime: Process: com.example.socketchatclient, PID: 26019
03-20 19:42:29.692 26019 26019 E AndroidRuntime: android.os.NetworkOnMainThreadException
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.io.BufferedWriter.flush(BufferedWriter.java:254)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.example.login.LoginActivity.setLogin(LoginActivity.java:136)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.example.login.LoginActivity$2.onClick(LoginActivity.java:217)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.view.View.performClick(View.java:5637)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:22433)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:751)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6236)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
03-20 19:42:29.694 1262 8760 W ActivityManager: Force finishing activity com.example.socketchatclient/com.example.login.LoginActivity
03-20 19:42:29.699 1262 8760 W ContextImpl: Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:877 com.android.server.am.AppErrors.crashApplicationInner:375 com.android.server.am.AppErrors.crashApplication:309 com.android.server.am.ActivityManagerService.handleApplicationCrashInner:13767 com.android.server.am.ActivityManagerService.handleApplicationCrash:13749
03-20 19:42:29.700 23695 23695 E AppCrashReceiver: com.example.socketchatclient stopped unexpectedly...
03-20 19:42:29.700 26019 26019 I Process : Sending signal. PID: 26019 SIG: 9
03-20 19:42:29.711 1262 1413 W InputDispatcher: channel 'db55de2 com.example.socketchatclient/com.example.login.LoginActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
03-20 19:42:29.712 1262 1413 E InputDispatcher: channel 'db55de2 com.example.socketchatclient/com.example.login.LoginActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
03-20 19:42:29.712 1262 14065 D GraphicsStats: Buffer count: 8
03-20 19:42:29.712 1262 14065 I WindowManager: WIN DEATH: Window{db55de2 u0 com.example.socketchatclient/com.example.login.LoginActivity}
03-20 19:42:29.712 1262 14065 W InputDispatcher: Attempted to unregister already unregistered input channel 'db55de2 com.example.socketchatclient/com.example.login.LoginActivity (server)'
03-20 19:42:29.716 1262 15305 I ActivityManager: Process com.example.socketchatclient (pid 26019) has died
03-20 19:42:29.716 1262 15305 D ActivityManager: cleanUpApplicationRecord -- 26019
03-20 19:42:29.716 1262 15305 W ActivityManager: Scheduling restart of crashed service com.example.socketchatclient/.SocketConnectService in 1000ms
关键句应该是:
第一部分:
03-20 19:42:29.692 26019 26019 E AndroidRuntime: android.os.NetworkOnMainThreadException
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at java.io.BufferedWriter.flush(BufferedWriter.java:254)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.example.login.LoginActivity.setLogin(LoginActivity.java:136)
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.example.login.LoginActivity$2.onClick(LoginActivity.java:217)
第二部分:
03-20 19:42:29.711 1262 1413 W InputDispatcher: channel 'db55de2 com.example.socketchatclient/com.example.login.LoginActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
03-20 19:42:29.712 1262 1413 E InputDispatcher: channel 'db55de2 com.example.socketchatclient/com.example.login.LoginActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
03-20 19:42:29.712 1262 14065 D GraphicsStats: Buffer count: 8
03-20 19:42:29.712 1262 14065 I WindowManager: WIN DEATH: Window{db55de2 u0 com.example.socketchatclient/com.example.login.LoginActivity}
03-20 19:42:29.712 1262 14065 W InputDispatcher: Attempted to unregister already unregistered input channel 'db55de2 com.example.socketchatclient/com.example.login.LoginActivity (server)'
03-20 19:42:29.716 1262 15305 I ActivityManager: Process com.example.socketchatclient (pid 26019) has died
然后范围缩小后再定位下,应该是:
03-20 19:42:29.692 26019 26019 E AndroidRuntime: at com.example.login.LoginActivity.setLogin(LoginActivity.java:136)
在项目中具体实现是:
messagebean.getBw().write(json + "\n");
messagebean.getBw().flush();
messagebean是实现的一个单例模式,里面封装了BufferedReader对象,为了图方便,一开始客户端和服务端建立连接的时候就把BufferedReader用单例模式封装了起来,方便后面时候。
但是没想到会出现这样的情况,现在再来看整个项目,发现整个项目的耦合程度太高了,没有把各个模块分的很细,很清楚。
然后现在后期维护也挺麻烦的,所以才意识到设计模式的重要性。
以后在做项目的时候一定要把各个模块分开写清楚了。
以上扯了那么多,就是我为了图方便,在主线程中实现了OutputStreamWriter导致意外闪退。因为前面把BufferedReader对象封装了起来了,所以后面使用起来的时候特别方便,随便哪里想写入就写入。。。。
怎么解决就不具体说了吧,可以单独写个模块,用来OutputStreamWriter,当然要开辟子线程实现,不然还是会这样。在android6.0之后必须开辟子线程来实现OutputStreamWriter和InputStreamReader,不然就GG了,作为一名程序员找bug的能力还是很重要的,要学会看日志文件,日志文件往往是一个很好的途径。