HttpURLConnection congela após esperar resposta do servidor por mais de 60 segundos

Estou desenvolvendo um app que conecta em um WebService(TOMCAT) para baixar um JSON. Quando a conexão acontece em menos de 60 segundos o arquivo é baixado e atualizo o app, porém quando a conexão demora mais de 60 segundos para responder o app “congela” e preciso forçar seu encerramento. Esta é a rotina que utilizo para conexão com o WS:

            try {
                url = new URL(strings[0]);
                conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(20000);
                conn.setConnectTimeout(10000);
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");
                int responseCode = conn.getResponseCode();
                if (responseCode == 200) {
                   tamanhoarquivo = Integer.valueOf(conn.getHeaderField("Tamanho"));
                   BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                   String line;
                   int total = 0;
                   while ((line = bufferedReader.readLine()) != null) {
                       content.append(line + "\n");
                       total = +line.length();
                       if (tamanhoarquivo > 0) {
                            publishProgress((int) (total * 100 / tamanhoarquivo));
                        }
                    }
                    bufferedReader.close();
                }
            } catch (UnsupportedEncodingException e) {
              e.printStackTrace();
              return "Erro:" + e;
            } catch (MalformedURLException e) {
              // Eh bom tratar as exceptions :D
              e.printStackTrace();
              return "Erro:" + e;
            } catch (ProtocolException e) {
              e.printStackTrace();
              return "Erro:" + e;
            } catch (IOException e) {
              e.printStackTrace();
              return "Erro:" + e;
            } finally {
              if (conn != null) {
                 conn.disconnect();
            }

Debugando o app o responseCode recebe o valor de -1. Quando a atualização é completa recebo 11 mil registros(não funciona), porém quando a atualização é parcial recebo uma quantidade menor de registros(funciona). A rotina de conexão acima acontece dentro de uma classe AsyncTask.

Neste caso, o debug pode interferir, visto que, o comportamento será um pouco diferente.
Sugiro, então, que você utilize de saídas de log para identificar quais informações são geradas para cada situação.

Obrigado por responder. Darlan realmente não sei onde colocar informações de log, pois quando executo o comando:
conn.getResponseCode();

já não tenho mais resposta alguma, e do lado do servidor o processamento ainda esta ocorrendo. No tomcat configurei timeout=“3600000” e connectionTimeout=“100000” imaginado ser problema no tempo de espera do servidor.
Para realizar testes, na rotina que acontece do lado do servidor coloquei tempos de espera para observar em que momento ele faz o app parar e realmente após 60 segundos é que acontece o problema. Me parece ser alguma questão de timeout.

Estes 60 segundos não saem do nada. Em algum lugar esse valor foi configurado (ou não, não me recordo se é o tempo padrão do tomcat).
De qualquer maneira, seria bom dar uma olhada nisso.
Além do mais, paginar o resultado é uma ideia bem necessária, assim você pede a página X e a quantidade Y de registros. Cada requisição durará menos tempo para processar e você terá que fazer mais requisições.

O app será utilizado para contagem de estoque, a solicitação pede o cadastro de produtos da empresa, dessa maneira não creio que seria possível usar a paginação, pois no momento da contagem eu preciso ter no app todos os produtos que a empresa tem no cadastro. De repente eu esteja trabalhando com algum conceito errado, mas a idéia é pegar os produtos do cadastro da empresa e colocá-los no app, se for possível fazer de outra forma, aceito sugestões.

11 mil registros, do tipo

{ "codigo" : 123, "quantidade": 2000 }

Deveria funcionar.
O problema é a quantidade de informação que está sendo processada nessa requisição.
Obviamente o timeout ocorre devido a demora no processamento destes dados.
Existem algumas opções, como manter um cache desses dados na memória ou mesmo realizar a paginação dos resultados, como eu mencionei anteriormente.
Eu não conheço todos os detalhes deste negócio, logo, estou falando de coisas genéricas e, neste sentido, considero que você não vai apresentar 11000 linhas no mesmo momento ao usuário. Ainda mais num sistema mobile.

Realmente existe uma demora no processamento dos dados antes deles se tornarem o Json de retorno. O retorno é isso mesmo:

    {"Codigo":123, "Descricao": "fralda descartável", "Embalagem": "pacote com 100 unidades"}

Seria possível eu solicitar o processamento dos dados e determinar que após 2 minutos eu busque apenas o Json ? Já fiz um teste onde eu primeiro solicito a geração dos dados e após isso eu solicito novamente a busca do Json, porém quando eu solicito os dados e a demora vai além dos 60 segundos o processo não continua, fiz dessa forma:

             try {
                url = new URL("http://192.168.0.101:8080/contaestoquewebservice/webresources/Estoque/gerarProdutos/"+editText.getText().toString());
                conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(10000);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                conn.setRequestProperty("Accept-Encoding", "");
                conn.addRequestProperty("Content-Type", "text/plain");
                conn.addRequestProperty("keepAlive", "false");
                int responseCode = conn.getResponseCode();

              if (responseCode != 200) {
                System.out.println("Fase Erro");
                Log.i("Serverside", "Mensagem:"+responseCode);
                return "Erro:"+responseCode;
              } else {
                url = new URL("http://192.168.0.101:8080/contaestoquewebservice/webresources/Estoque/getprodutosdata/"+editText.getText().toString());
                conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(20000);
                conn.setConnectTimeout(10000);
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");
                responseCode = conn.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_OK) {
                    Log.i("Serverside", "Mensagem:" + responseCode);
                    return "Erro:" + responseCode;
                } else {
                    tamanhoarquivo = Integer.valueOf(conn.getHeaderField("Tamanho"));
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String line;
                    int total = 0;
                    while ((line = bufferedReader.readLine()) != null) {
                        content.append(line + "\n");
                        total = +line.length();
                        if (tamanhoarquivo > 0) {
                            publishProgress((int) (total * 100 / tamanhoarquivo));
                        }
                    }
                    bufferedReader.close();
                }
              }
           } catch (UnsupportedEncodingException e) {
             e.printStackTrace();
             return "Erro:" + e;
           } catch (MalformedURLException e) {
              // Eh bom tratar as exceptions :D
              e.printStackTrace();
              return "Erro:" + e;
          } catch (ProtocolException e) {
             e.printStackTrace();
             return "Erro:" + e;
          } catch (IOException e) {
             e.printStackTrace();
             return "Erro:" + e;
          } finally {
              if (conn != null) {
                conn.disconnect();
              }
          }

No servidor WS fiz da seguinte forma:

Etapa 1:

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("gerarProdutos/{database}")
    public Response gerarProdutos(@PathParam("database") String database) {
        ProdutoDAO.preparaDadosProduto(database);
        return Response.status(200).entity("Sucesso").build();         
    }

Etapa 2:

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("getprodutosdata/{database}")
public Response getProdutosData(@PathParam("database") String database) {
    List<Produto> produto;
    produto = ProdutoDAO.listarProduto(database);
    Gson g = new Gson();
    int var = g.toJson(produto).length();
    return Response.ok(g.toJson(produto)).header("Tamanho", var).build();        
}

Porém a demora na primeira etapa já congela a aplicação.

Basta você ter os serviços separados e, no lado do client (mobile) criar as chamadas separadas por um Thread.sleep(120000);

Vou tentar dessa forma. Obrigado !

Realizei alguns testes e percebi o seguinte: quando eu utilizo um celular com api 27 o processo acontece com sucesso, porem quando utilizo um celular com api 24, ele congela na primeira etapa do processo, que é a etapa de preparação dos dados, onde o processo é demorado:

@Path("gerarProdutos/{database}")

No momento em que solicito o int responseCode = conn.getReponsecode(); o celular deixa de responder.
Alguma idéia ?

Veja, você está implementando o processamento dos dados de forma síncrona no backend, assim sendo, quando você dispara uma requisição a ele, só consegue se desvinvular quando ela é encerrada, ou seja, após realizar todo processamento.
Neste caso, seria bacana criar o processo em uma thread separada, que iria ser executada mesmo após o retorno do método que corresponde ao serviço.

Sim, concordo, porém o processo “congela” e não continua. Pois como você comentou “só consegue se desvinvular quando ela é encerrada”, porém o processo não continua e trava o restante dos processos. O processo que estou utilizando pra fazer a solicitação dos dados ao Webservice esta correta, fiz depois de estudar vários tutoriais. O detalhe é o tempo de espera que o processo leva, pois quando é menor de 60 segundos ele vai, independente de API, mas trava quando na API 24 e leva mais de 60 segundos ! Eu ja utilizei o metodo “HEAD” na primeira etapa onde mando gerar os dados, para depois realizar um “GET” e fazer o download. Mesmo assim quando demora mais de 60 segundos na API 24 trava e não continua. Verifiquei os logs do tomcat e ele mostra que foi solicitado o metodo “gerarProdutos” e nada mais. Quando consulto a documentação do comando getRespondeCode, ele mostra Andoid API 28 Platform, mas esta funcionando na API 27.

Ainda não consegui resolver a situação ! Mudei o servidor para Glassfish e o problema ainda persiste. Se alguém mais tiver alguma idéia, site, qualquer informação que possa ajudar eu agradeço !