App在解析Google表格数据时崩溃。

huangapple go评论65阅读模式
英文:

App crashes while parsing data from google sheet

问题

I) 以下是从Google表格异步解析数据的代码,只要互联网速度良好,就能正常工作,但在速度较慢时会崩溃。如何解决这个问题?我已经解决了没有互联网的问题。

II) 如果Google表格正在更新(每次一行),系统尝试打开时会崩溃。如何跳过不可访问(或正在更新)的行?

III) 有没有办法找到Google表格最后更新的时间?

IV) 如何告诉Google地图在解析完成之前不要打开地图?

这是关于从GitHub上的DownloadWebpageTask.java的代码。

Stacktrace:
08/03 06:41:06: 在vivo vivo 1902上启动'MapsActivity'。
$ adb shell am start -n "com.example.fmtxstatus/com.example.fmtxstatus.MapsActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER 等待进程上线... 已连接到设备'vivo-vivo_1902-CIEMU8KRPFLFHEBU'。从应用程序中捕获和显示logcat消息。可以在“调试器”设置页面的“Logcat输出”部分禁用此行为。

英文:

I) Below is code for parsing data async from google sheet and works fine as long as the internet speed is good but crashes on slow speed. How to address this? I have fixed for no internet.

II) If the google sheet is opened for update ( one a row at a time), the system crashes on trying to open. How can I skip the rows which are not assessible ( or updating) ?

III) Is there any way to find time when the google sheet was last updated ?

IV) How to tell google maps not to open the map till the parsing is done?

protected void ReadGoogleSheetAsync(){
        new DownloadWebpageTask(new AsyncResult() {
            @Override
            public void onResult(JSONObject object) {
                processJson(object);
            }
        }).execute("https://spreadsheets.google.com/tq?key=mykey");
    }

private void processJson(JSONObject object) {
    try {
        JSONArray rows = object.getJSONArray("rows");
        for (int r = 0; r < rows.length(); ++r) {
            JSONObject row = rows.getJSONObject(r);
            JSONArray columns = row.getJSONArray("c");
            UserData ud = new UserData();
            ud.setId(columns.getJSONObject(0).getString("f"));
            ud.setName(columns.getJSONObject(1).getString("v"));
            ud.setState(columns.getJSONObject(2).getString("v"));
        }
     catch (JSONException e) {
        e.printStackTrace();
    }
}

This is based on DownloadWebpageTask.java from git.

Stacktrace:

08/03 06:41:06: Launching 'MapsActivity' on vivo vivo 1902.
$ adb shell am start -n "com.example.fmtxstatus/com.example.fmtxstatus.MapsActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER Waiting for process to come online... Connected to process 6659 on device 'vivo-vivo_1902-CIEMU8KRPFLFHEBU'. Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page. D/VivoTheme: load old package name start I/mple.fmtxstatu: The ClassLoaderContext is a special shared library. W/mple.fmtxstatu: JIT profile information will not be recorded: profile file does not exits.
JIT profile information will not be recorded: profile file does not exits. D/NightModeController: com.example.fmtxstatus = true
disable nightmode package:com.example.fmtxstatus I/FtBuild: getRomVersion mRomVer=9.0 D/VivoPhoneWindow: DEBUG_ALIENSCREEN:getRotation mRotation=0 I/PhoneWindow: initSystemUIColor I/zzbz: Making Creator dynamically W/mple.fmtxstatu: Unsupported class loader W/mple.fmtxstatu: Skipping duplicate class check due to unsupported classloader I/DynamiteModule: Considering local module com.google.android.gms.maps_dynamite:0 and remote module com.google.android.gms.maps_dynamite:202614000 I/DynamiteModule: Selected remote version of com.google.android.gms.maps_dynamite, version >= 202614000 V/DynamiteModule: Dynamite loader version >= 2, using loadModule2NoCrashUtils I/DynamiteLoaderV2: [71] Mapsdynamite W/mple.fmtxstatu: Unsupported class loader W/mple.fmtxstatu: Skipping duplicate class check due to unsupported classloader I/Google Maps Android API: Google Play services client version: 12451000 I/Google Maps Android API: Google Play services package version: 202614029 W/mple.fmtxstatu: Accessing hidden field Ljava/nio/Buffer;->address:J (light greylist, reflection) I/mple.fmtxstatu: The ClassLoaderContext is a special shared library. E/libc: Access denied finding property "persist.vendor.log.tel_dbg" W/com.example.fmtxstatus: type=1400 audit(0.0:118917): avc: denied { read } for comm=4173796E635461736B202332 name="u:object_r:mtk_em_tel_log_prop:s0" dev="tmpfs" ino=6814 scontext=u:r:untrusted_app:s0:c252,c256,c512,c768 tcontext=u:object_r:mtk_em_tel_log_prop:s0 tclass=file permissive=0 D/NetworkSecurityConfig: No Network Security Config specified, using platform default D/OpenGLRenderer: Dumper init 4 threads <0x7a04d12b40> D/OpenGLRenderer: <com.example.fmtxstatus> is running.
Skia GL Pipeline I/SurfaceFactory: [static] sSurfaceFactory = com.mediatek.view.impl.SurfaceFactoryImpl@5b77117 D/ViewRootImpl[MapsActivity]: hardware acceleration = true , fakeHwAccelerated = false, sRendererDisabled = false, forceHwAccelerated = false, sSystemRendererDisabled = false V/PhoneWindow: DecorView setVisiblity: visibility = 0, Parent = android.view.ViewRootImpl@ff0122, this = DecorView@13807b3[MapsActivity] V/PhoneWindow: DecorView setVisiblity: visibility = 0, Parent = android.view.ViewRootImpl@ff0122, this = DecorView@13807b3[MapsActivity] I/CatcherGestureDetector: DecorView onAttached D/yuan: onVisibilityChanged----com.google.maps.api.android.lib6.impl.ci{2c1c49c G.ED..C.. ......I. 0,0-0,0} D/Surface: Surface::allocateBuffers(this=0x79f461d000) I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0 I/OpenGLRenderer: Initialized EGL, version 1.4 D/OpenGLRenderer: Swap behavior 2 D/Surface: Surface::connect(this=0x79f461d000,api=1) D/TextureView: getHardwareLayer, createNewSurface:true I/BufferQueue: [unnamed-6659-0](this:0x7a03285800,id:0,api:0,p:-1,c:-1) BufferQueue core=(6659:com.example.fmtxstatus) W/mple.fmtxstatus: type=1400 audit(0.0:118918): avc: denied { read } for name="u:object_r:graphics_debug_prop:s0" dev="tmpfs" ino=6754 scontext=u:r:untrusted_app:s0:c252,c256,c512,c768 tcontext=u:object_r:graphics_debug_prop:s0 tclass=file permissive=0 E/libc: Access denied finding property "vendor.debug.sf.stc_interval" W/mple.fmtxstatus: type=1400 audit(0.0:118919): avc: denied { read } for name="u:object_r:debug_bq_dump_prop:s0" dev="tmpfs" ino=6713 scontext=u:r:untrusted_app:s0:c252,c256,c512,c768 tcontext=u:object_r:debug_bq_dump_prop:s0 tclass=file permissive=0 E/libc: Access denied finding property "vendor.debug.bq.dump" W/System: ClassLoader referenced unknown path: system/framework/mediatek-cta.jar I/BufferQueueConsumer: [unnamed-6659-0](this:0x7a03285800,id:0,api:0,p:-1,c:6659) connect(C): consumer=(6659:com.example.fmtxstatus) controlledByApp=true E/libc: Access denied finding property "vendor.debug.bq.dump" W/mple.fmtxstatus: type=1400 audit(0.0:118920): avc: denied { read } for name="u:object_r:debug_bq_dump_prop:s0" dev="tmpfs" ino=6713 scontext=u:r:untrusted_app:s0:c252,c256,c512,c768 tcontext=u:object_r:debug_bq_dump_prop:s0 tclass=file permissive=0 I/BufferQueueConsumer: [unnamed-6659-0](this:0x7a03285800,id:0,api:0,p:-1,c:6659) setConsumerName: unnamed-6659-0 E/libc: Access denied finding property "vendor.debug.bq.line" W/mple.fmtxstatus: type=1400 audit(0.0:118921): avc: denied { read } for name="u:object_r:graphics_debug_prop:s0" dev="tmpfs" ino=6754 scontext=u:r:untrusted_app:s0:c252,c256,c512,c768 tcontext=u:object_r:graphics_debug_prop:s0 tclass=file permissive=0 E/libc: Access denied finding property "vendor.debug.bq.dump" I/BufferQueueConsumer: [SurfaceTexture-0-6659-0](this:0x7a03285800,id:0,api:0,p:-1,c:6659) setConsumerName: SurfaceTexture-0-6659-0 W/mple.fmtxstatus: type=1400 audit(0.0:118922): avc: denied { read } for name="u:object_r:debug_bq_dump_prop:s0" dev="tmpfs" ino=6713 scontext=u:r:untrusted_app:s0:c252,c256,c512,c768 tcontext=u:object_r:debug_bq_dump_prop:s0 tclass=file permissive=0 I/System.out: e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaHttp I/BufferQueueConsumer: [SurfaceTexture-0-6659-0](this:0x7a03285800,id:0,api:0,p:-1,c:6659) setDefaultBufferSize: width=720 height=1404 D/OpenGLRenderer: 0x7a032fb740 setSurfaceTexture: 0x0 to 0x7a032d1800 D/Linux: [Posix_connect Debug]Process com.example.fmtxstatus :443  E/ion: ioctl c0044901 failed with code -1: Invalid argument I/GLConsumer: [SurfaceTexture-0-6659-0] attachToContext D/OpenSSLLib: OpensslErr:Module:12(177:); file:external/boringssl/src/crypto/asn1/asn1_lib.c ;Line:168;Function:ASN1_get_object D/OpenSSLLib: OpensslErr:Module:12(177:); file:external/boringssl/src/crypto/asn1/asn1_lib.c ;Line:168;Function:ASN1_get_object I/System.out: [OkHttp] sendRequest>> I/System.out: [OkHttp] sendRequest<< E/Google Maps Android API: Authorization failure.  Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map. E/Google Maps Android API: In the Google Developer Console (https://console.developers.google.com)
com.example.fmtxstatus W/System: ClassLoader referenced unknown path: system/framework/mediatek-cta.jar I/System.out: e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaHttp D/Linux: [Posix_connect Debug]Process com.example.fmtxstatus :443  D/OpenSSLLib: OpensslErr:Module:12(177:); file:external/boringssl/src/crypto/asn1/asn1_lib.c ;Line:168;Function:ASN1_get_object D/OpenSSLLib: OpensslErr:Module:12(177:); file:external/boringssl/src/crypto/asn1/asn1_lib.c ;Line:168;Function:ASN1_get_object I/System.out: [OkHttp] sendRequest>> I/System.out: [OkHttp] sendRequest<< W/DynamiteModule: Local module descriptor class for com.google.android.gms.googlecertificates not found. I/DynamiteModule: Considering local module com.google.android.gms.googlecertificates:0 and remote module com.google.android.gms.googlecertificates:5
Selected remote version of com.google.android.gms.googlecertificates, version >= 5 I/DynamiteLoaderV2: [71] Googlecertificates W/mple.fmtxstatu: Unsupported class loader W/mple.fmtxstatu: Skipping duplicate class check due to unsupported classloader I/System.out: [OkHttp] sendRequest>> I/System.out: [OkHttp] sendRequest<< I/System.out: [OkHttp] sendRequest>> I/System.out: [OkHttp] sendRequest<< I/Choreographer: Skipped 52 frames!  The application may be doing too much work on its main thread.

答案1

得分: 3

The issue seems to be related to poor handling of HttpURLConnection object. There are issues in the downloadUrl() method implementation in the class DownloadWebpageTask, which may be relevant to the queries 1-3, the variable responseCode is never used.

If the response is not HttpURLConnection.HTTP_OK, try reconnecting (or till a custom timeout) or return a null string. On slow internet or bad connection, the response will not be HttpURLConnection.HTTP_OK, hence trying to reference the json-object may lead to undefined behavior.

private String downloadUrl(String urlString) throws IOException {
/.../
conn.connect();
responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// do something
} else {
// retry or return null string
}
}

The function processJson(object) in the snippet should be called only if the json-object is not null. Issues under queries 1 to 3 should be taken care of with these modifications.

protected void ReadGoogleSheetAsync() {
new DownloadWebpageTask(new AsyncResult() {
@Override
public void onResult(JSONObject object) {
if (object) processJson(object);
}
}).execute("https://spreadsheets.google.com/tq?key=mykey");
}

For query 4 related to google maps api, OnMapReadyCallback is called when the map is ready to be used. Override onMapReady() method to find if the map is ready or not.

英文:

The issue seems to be related to poor handling of HttpURLConnection object. There are issues in the downloadUrl() method implementation in the class DownloadWebpageTask, which may be relevant to the queries 1-3, the variable responseCode is never used.

If the response is not HttpURLConnection.HTTP_OK , try reconnecting ( or till a custom timeout) or return a null string. On slow internet or bad connection, the response will not be HttpURLConnection.HTTP_OK, hence trying to reference the json-object may lead to undefined behavior.

    private String downloadUrl(String urlString) throws IOException {
/*...*/
conn.connect();
responseCode = conn.getResponseCode();
if( responseCode == HttpURLConnection.HTTP_OK) 
{
// do something
}
else
{
// retry or return null string
}
}

The function processJson(object) in the snippet should be called only if json-object is not null. Issues under queries 1 to 3 should be taken care of with these modifications.

protected void ReadGoogleSheetAsync(){
new DownloadWebpageTask(new AsyncResult() {
@Override
public void onResult(JSONObject object) {
if(object) processJson(object);
}
}).execute("https://spreadsheets.google.com/tq?key=mykey");
}

For query 4 related to google maps api, OnMapReadyCallback is called when the map is ready to be used. Override onMapReady() method to find if the map is ready or not.

huangapple
  • 本文由 发表于 2020年7月31日 10:52:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63185096.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定