Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
opanasa
0 / 0 / 0
Регистрация: 12.12.2015
Сообщений: 15
#1

Получение данных с сервера, длинные запросы - Android

02.07.2016, 19:05. Просмотров 356. Ответов 7
Метки нет (Все метки)

Здравствуйте. Оговорюсь сразу, на сервере обычный php в цикле опрашивающий бд на изменения.
Взял приложение с хабры и с обычными запросами раз в 15 сек оно прекрасно пашет. накрутил на сервер лонгпул в моем понимании и приложение перестало работать корректно, то есть ответа от сервера еще нет, а оно сразу пишет что ответ пуст. притом основное - в браузере обычном все прекрасно и корректно работает. запросы обычные get.
Оговорюсь сразу, это копипаст с хабры немного переделанный. я пытался и циклы делать на инпутстрим и тп, итог один. он сразу, без ответа сервера выдает что ответ пуст

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
                while (true) { // стартуем бесконечный цикл
 
                    // глянем локальную БД на наличие сообщщений чата
                    cursor = chatDBlocal.rawQuery(
                            "SELECT * FROM chat ORDER BY data", null);
 
                    // если какие-либо сообщения есть - формируем запрос
                    // по которому получим только новые сообщения
                    if (cursor.moveToLast()) {
                        last_time = cursor.getLong(cursor
                                .getColumnIndex("data"));
                        lnk = server_name + "/chat.php?action=select&data=" + last_time.toString();
 
                        // если сообщений в БД нет - формируем запрос
                        // по которому получим всё
                    } else {
                        lnk = server_name + "/chat.php?action=select&data=1";
                    }
 
                    cursor.close();
 
                    // создаем соединение ---------------------------------->
                    try {
                        Log.i("chat",
                                "+ FoneService --------------- ОТКРОЕМ СОЕДИНЕНИЕ");
 
                        conn = (HttpURLConnection) new URL(lnk)
                                .openConnection();
                        conn.setReadTimeout(20000);
                        conn.setConnectTimeout(25000);
                        conn.setRequestMethod("GET");
                        //conn.setRequestProperty("User-Agent", "Mozilla/5.0");
                        conn.setDoInput(true);
                        conn.connect();
 
                    } catch (Exception e) {
                        Log.i("chat", "+ FoneService ошибка: " + e.getMessage());
                    }
                    // получаем ответ ---------------------------------->
                    
 
 
                    try {
                        InputStream is = conn.getInputStream();
                        while (is == null) {
                            is = conn.getInputStream();
                        }
                        BufferedReader br = new BufferedReader(
                                new InputStreamReader(is, "UTF-8"));
                        StringBuilder sb = new StringBuilder();
                        String bfr_st;
                        while ((bfr_st = br.readLine()) != null) {
                            sb.append(bfr_st);
                        }
 
                        Log.i("chat", "+ FoneService - полный ответ сервера:\n"
                                + sb.toString());
                        // сформируем ответ сервера в string
                        // обрежем в полученном ответе все, что находится за "]"
                        // это необходимо, т.к. json ответ приходит с мусором
                        // и если этот мусор не убрать - будет невалидным
                        ansver = sb.toString();
                        ansver = ansver.substring(0, ansver.indexOf("]") + 1);
 
                        is.close(); // закроем поток
                        br.close(); // закроем буфер
 
 
 
                    } catch (Exception e) {
                        Log.i("chat", "+ FoneService ошибка: " + e.getMessage());
                    } finally {
                        conn.disconnect();
                        Log.i("chat",
                                "+ FoneService --------------- ЗАКРОЕМ СОЕДИНЕНИЕ");
                    }
 
             
                }
прошу совета или подсказки. как реализовать чтобы было ожидание ответа, повторюсь - браузеры работают корректно - ждут ответа, и как только база меняется, скрипт его и выдает.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
04.07.2016, 16:12     Получение данных с сервера, длинные запросы #2
opanasa, привет!
Если отладчик запускать или логи выводить, где ошибка?
opanasa
0 / 0 / 0
Регистрация: 12.12.2015
Сообщений: 15
05.07.2016, 11:14  [ТС]     Получение данных с сервера, длинные запросы #3
ошибки нет.
В логах от сюда берется
Java
1
2
Log.i("chat", "+ FoneService - полный ответ сервера:\n"
                                + sb.toString());
Выводит - "Полный ответ сервера: "
то есть он пуст.
Если ответ сервер даёт сразу, то есть там были какие то новые сообщения, то все корректно отрабатывает- получает ответ, распарсит json и т.д. Но если ответ сервер не дает, а ждет изменения базы, то в приложении такой вот косяк, а в браузерах любых просто ожидание загрузки страницы, и как только база меняется, сервер отдает и страница грузится.

Если лог вешаешь на InputStream или на BufferedReader то в ответ что то типа:

java.util.zip.GZIPInputStream@b304b538
java.io.BufferedReader@b304bad0
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723
05.07.2016, 19:18     Получение данных с сервера, длинные запросы #4
opanasa, давно этим не занимался. Там ещё тайм-аут выставляется. И почему у вас сразу после скачивания закрывается поток?
opanasa
0 / 0 / 0
Регистрация: 12.12.2015
Сообщений: 15
05.07.2016, 22:50  [ТС]     Получение данных с сервера, длинные запросы #5
По логике в коде он коннектится раз в 15 сек и получает данные.
А закрыв соединение, в ansver записаны строки с новыми данными с сервера, раскидывает jsonarray и отправляет всё это в другое активити. далее ждет 15 сек и заново коннект, инпутстрим и т.д.
Все это висит в памяти и опрашивает сервер.
Не знаю поможет ли более полный код:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
 
import org.json.JSONArray;
import org.json.JSONObject;
 
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.util.Log;
 
public class FoneService extends Service {
 
    // ИМЯ СЕРВЕРА (url зарегистрированного нами сайта)
    String server_name = "http://mysite.ru";
    
    SQLiteDatabase chatDBlocal;
    HttpURLConnection conn;
    Cursor cursor;
    Thread thr;
    ContentValues new_mess;
    Long last_time; // время последней записи в БД, отсекаем по нему что нам
                    // тянуть с сервера, а что уже есть
 
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
 
    public void onStart(Intent intent, int startId) {
 
        Log.i("chat", "+ FoneService - запуск сервиса");
 
        chatDBlocal = openOrCreateDatabase("chatDBlocal.db",
                Context.MODE_PRIVATE, null);
        chatDBlocal
                .execSQL("CREATE TABLE IF NOT EXISTS chat (_id integer primary key autoincrement, author, client, data, text)");
 
        // создадим и покажем notification
        // это позволит стать сервису "бессмертным"
        // и будет визуально видно в трее
        Intent iN = new Intent(getApplicationContext(), MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pI = PendingIntent.getActivity(getApplicationContext(),
                0, iN, PendingIntent.FLAG_CANCEL_CURRENT);
        Notification.Builder bI = new Notification.Builder(
                getApplicationContext());
 
        bI.setContentIntent(pI)
                .setSmallIcon(R.drawable.ic_launcher)
                .setLargeIcon(
                        BitmapFactory.decodeResource(getApplicationContext()
                                .getResources(), R.drawable.ic_launcher))
                .setAutoCancel(true)
                .setContentTitle(getResources().getString(R.string.app_name))
                .setContentText("работаю...");
 
        Notification notification = bI.build();
        startForeground(101, notification);
 
        startLoop();
    }
 
    // запуск потока, внутри которого будет происходить
    // регулярное соединение с сервером для чтения новых
    // сообщений.
    // если сообщения найдены - отправим броадкаст для обновления
    // ListView в ChatActivity
    private void startLoop() {
 
        thr = new Thread(new Runnable() {
 
            // ansver = ответ на запрос
            // lnk = линк с параметрами
            String ansver, lnk;
 
            public void run() {
 
                while (true) { // стартуем бесконечный цикл
 
                    // глянем локальную БД на наличие сообщщений чата
                    cursor = chatDBlocal.rawQuery(
                            "SELECT * FROM chat ORDER BY data", null);
 
                    // если какие-либо сообщения есть - формируем запрос
                    // по которому получим только новые сообщения
                    if (cursor.moveToLast()) {
                        last_time = cursor.getLong(cursor
                                .getColumnIndex("data"));
                        lnk = server_name + "/chat.php?action=select&data="
                                + last_time.toString();
 
                        // если сообщений в БД нет - формируем запрос
                        // по которому получим всё
                    } else {
                        lnk = server_name + "/chat.php?action=select";
                    }
 
                    cursor.close();
 
                    // создаем соединение ---------------------------------->
                    try {
                        Log.i("chat",
                                "+ FoneService --------------- ОТКРОЕМ СОЕДИНЕНИЕ");
 
                        conn = (HttpURLConnection) new URL(lnk)
                                .openConnection();
                        conn.setReadTimeout(10000);
                        conn.setConnectTimeout(15000);
                        conn.setRequestMethod("POST");
                        conn.setRequestProperty("User-Agent", "Mozilla/5.0");
                        conn.setDoInput(true);
                        conn.connect();
 
                    } catch (Exception e) {
                        Log.i("chat", "+ FoneService ошибка: " + e.getMessage());
                    }
                    // получаем ответ ---------------------------------->
                    try {
                        InputStream is = conn.getInputStream();
                        BufferedReader br = new BufferedReader(
                                new InputStreamReader(is, "UTF-8"));
                        StringBuilder sb = new StringBuilder();
                        String bfr_st = null;
                        while ((bfr_st = br.readLine()) != null) {
                            sb.append(bfr_st);
                        }
 
                        Log.i("chat", "+ FoneService - полный ответ сервера:\n"
                                + sb.toString());
                        // сформируем ответ сервера в string
                        // обрежем в полученном ответе все, что находится за "]"
                        // это необходимо, т.к. json ответ приходит с мусором
                        // и если этот мусор не убрать - будет невалидным
                        ansver = sb.toString();
                        ansver = ansver.substring(0, ansver.indexOf("]") + 1);
 
                        is.close(); // закроем поток
                        br.close(); // закроем буфер
 
                    } catch (Exception e) {
                        Log.i("chat", "+ FoneService ошибка: " + e.getMessage());
                    } finally {
                        conn.disconnect();
                        Log.i("chat",
                                "+ FoneService --------------- ЗАКРОЕМ СОЕДИНЕНИЕ");
                    }
 
                    // запишем ответ в БД ---------------------------------->
                    if (ansver != null && !ansver.trim().equals("")) {
 
                        Log.i("chat",
                                "+ FoneService ---------- ответ содержит JSON:");
 
                        try {
                            // ответ превратим в JSON массив
                            JSONArray ja = new JSONArray(ansver);
                            JSONObject jo;
 
                            Integer i = 0;
 
                            while (i < ja.length()) {
 
                                // разберем JSON массив построчно
                                jo = ja.getJSONObject(i);
 
                                Log.i("chat",
                                        "=================>>> "
                                                + jo.getString("author")
                                                + " | "
                                                + jo.getString("client")
                                                + " | " + jo.getLong("data")
                                                + " | " + jo.getString("text"));
 
                                // создадим новое сообщение
                                new_mess = new ContentValues();
                                new_mess.put("author", jo.getString("author"));
                                new_mess.put("client", jo.getString("client"));
                                new_mess.put("data", jo.getLong("data"));
                                new_mess.put("text", jo.getString("text"));
                                // запишем новое сообщение в БД
                                chatDBlocal.insert("chat", null, new_mess);
                                new_mess.clear();
 
                                i++;
 
                                // отправим броадкаст для ChatActivity
                                // если она открыта - она обновить ListView
                                sendBroadcast(new Intent(
                                        "by.andreidanilevich.action.UPDATE_ListView"));
                            }
                        } catch (Exception e) {
                            // если ответ сервера не содержит валидный JSON
                            Log.i("chat",
                                    "+ FoneService ---------- ошибка ответа сервера:\n"
                                            + e.getMessage());
                        }
                    } else {
                        // если ответ сервера пустой
                        Log.i("chat",
                                "+ FoneService ---------- ответ не содержит JSON!");
                    }
 
                    try {
                        Thread.sleep(15000);
                    } catch (Exception e) {
                        Log.i("chat",
                                "+ FoneService - ошибка процесса: "
                                        + e.getMessage());
                    }
                }
            }
        });
 
        thr.setDaemon(true);
        thr.start();
 
    }
}
Alexvp
107 / 71 / 8
Регистрация: 03.08.2014
Сообщений: 344
05.07.2016, 22:56     Получение данных с сервера, длинные запросы #6
ИХМО. 15 секунд мало.
Попробуйте готовить ответ на сервере с опережением. Т.е. сразу отдавать приложению данные по предшествующему запросу, а по текущему готовить данные, которые отдадите при следующем запросе.
Паблито
2240 / 1813 / 564
Регистрация: 12.05.2014
Сообщений: 6,456
Завершенные тесты: 1
06.07.2016, 10:45     Получение данных с сервера, длинные запросы #7
Цитата Сообщение от opanasa Посмотреть сообщение
Выводит - "Полный ответ сервера: "
то есть он пуст.
если сформированную строку-урл вбить в браузере, что будет?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2016, 16:09     Получение данных с сервера, длинные запросы
Еще ссылки по теме:

Получение текста с сервера Android
Получение списка файлов с ftp сервера с авторизацией Android
SocketServer, Client. Получение ответа от сервера Android
Получение данных из cursor Android
Получение данных с квадрокоптера Android

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
opanasa
0 / 0 / 0
Регистрация: 12.12.2015
Сообщений: 15
06.07.2016, 16:09  [ТС]     Получение данных с сервера, длинные запросы #8
В браузере все прекрасно и на пк и на андроид. Видимо в нем немного другой алгоритм обработки запросов.
Господа, проблема решена. Этот код на андроид в принципе рабочий. Естественно не без костылей, но в корне он работает. Ошибка была именно на сервере, хотел отписать результаты сюда как при очередной проверке заметил несостыковку. - если последним смс писал я, то в базе на сервере дата сообщения была равна дате, передаваемой в запросе, а тут чисто косяк мой - условия были прописаны мной: выдать сообщения из базы, если дата на сервере больше даты последнего сообщения в телефоне, передаваемой в запросе. если дата на сервере меньше, то ждать изменения в БД на появление новых записей(ну как бы и есть long polling). А варианта то что даты равны не было, в итоге сервер сразу выдавал ошибку так как не знал что выдавать, которую приложение интерпретировало за ответ, притом пустой.
Всем спасибо за помощь. Этот вопрос решен, можно закрывать.
Yandex
Объявления
06.07.2016, 16:09     Получение данных с сервера, длинные запросы
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru