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

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

Войти
Регистрация
Восстановить пароль
 
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
#1

GPS координаты раздельно по времени и минимальному смещению - Android

09.09.2015, 16:45. Просмотров 418. Ответов 10
Метки нет (Все метки)

Стоит задача получать точность измерения (accuracy = location.getAccuracy() и отправлять ее для контроля, ну, скажем каждые 2 сек. В тоже время нужно при измениени положения на определенную величину, отсылать сообщение о новом местоположении.

Казалось бы все просто и достаточно вбить время и расстояние для обновления, типа так

Java
1
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_UPDATES, MIN_DISTANCE_FOR_UPDATES, this);
Но не все оказалось гладко.

При установке MIN_DISTANCE_CHANGE_FOR_UPDATES, координаты по времени не обновляются до тех пор пока премешение не превысит MIN_DISTANCE_FOR_UPDATES.

Получается что по факту обновление по времени выключено.

Как решит задачу?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.09.2015, 16:45     GPS координаты раздельно по времени и минимальному смещению
Посмотрите здесь:

Android Координаты GPS внутри service
Android Полные GPS координаты в мобильном
Android Подделать GPS координаты
gps и 2 устройства Android
Android Прослушка GPS
Android GPS трекер
Android GPS Location (GPS_PROVIDER) как получить координаты
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
YuraAAA
 Аватар для YuraAAA
1564 / 1306 / 269
Регистрация: 25.10.2009
Сообщений: 3,424
Записей в блоге: 2
09.09.2015, 20:19     GPS координаты раздельно по времени и минимальному смещению #2
zoleg, а покажите константы свои, время и расстояние.
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
10.09.2015, 16:50  [ТС]     GPS координаты раздельно по времени и минимальному смещению #3
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    schedule() ;
   if (isNetworkEnabled) {
                    //   locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("GPSListnerTracker", "Network Enabled");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            Log.d("GPSListnerTracker", "Control real update by shu");
//                            latitude = location.getLatitude();
//                            longitude = location.getLongitude();
                        }
                    }
                }
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void schedule() {
        if (tTask != null) tTask.cancel();
        if (interval > 0) {
            tTask = new TimerTask() {
                public void run() {
                    accuracy = location.getAccuracy();
                   // location.getAccuracy();
                    EventBus.getDefault().postSticky(new EventsGPS(accuracy));
                    android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG schedule OK accuracy="+accuracy+"");
                }
 
            };
            timer.schedule(tTask, 1000, interval);
        }
Переменные нарисованы так
Java
1
2
3
4
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = Integer.parseInt(TetATetSettingDate.GPS_UPDATE_DISTANCE); // meters
 
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * Integer.parseInt(TetATetSettingDate.GPS_UPDATE_SECONDS); // second
Конкретные значения указаны так
Java
1
2
public static String GPS_UPDATE_DISTANCE = "40";
public static String GPS_UPDATE_SECONDS = "3";
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
10.09.2015, 17:01  [ТС]     GPS координаты раздельно по времени и минимальному смещению #4
Весь код как есть (не чищенный, весь в тестах и пробах):
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
public class GPSListnerZoneTracker extends Service implements LocationListener {
 
    Context mContext;
    Intent intent;
    Timer timer = new Timer();
    TimerTask tTask;
    long interval = 1000;
 
    boolean isGPSEnabled = false;
    private String BROADCAST_ACTION;
    // flag for network status
    boolean isNetworkEnabled = false;
 
    boolean canGetLocation = false;
 
    Location location; // location
    double latitude; // latitude
    double longitude; // longitude
    double altitiude; // altitiude
    float accuracy; // accuracy
    float bearing; // bearing
    float speed; // speeed
    // The minimum distance to change Updates in meters
    public Location previousBestLocation = null;
    private IBinder mBinder;
 
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = Integer.parseInt(TetATetSettingDate.GPS_UPDATE_DISTANCE); // 10 meters
 
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * Integer.parseInt(TetATetSettingDate.GPS_UPDATE_SECONDS); // 1 minute
 
    // Declaring a Location Manager
    protected LocationManager locationManager;
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String action = getClass().getCanonicalName();
        int pos = action.lastIndexOf('.') + 1;
        String onlyClass = action.substring(pos);
        TetGpsData.GPSZoneListner_name = onlyClass;
        BROADCAST_ACTION = TetGpsData.GPSZoneListner_name;
        android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG onCreate BROADCAST_ACTION =" + BROADCAST_ACTION + "");
        intent = new Intent(BROADCAST_ACTION);
        EventBus.getDefault().registerSticky(this);
//        schedule("run");
        if ((flags & START_FLAG_RETRY) == 0) {
            // TODO Если это повторный запуск, выполнить какие-то действия.
        } else {
            android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG onStartCommand OK");
//            EventBus.getDefault().register(this);
//            EventBus.getDefault().registerSticky(this);
           // getLocation();
        }
        return Service.START_STICKY;
 
        // return super.onStartCommand(intent, flags, startId);
    }
 
    @Override
    public void onCreate() {
        android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG onCreate nethod OK");
        super.onCreate();
        String action = getClass().getCanonicalName();
        int pos = action.lastIndexOf('.') + 1;
        String onlyClass = action.substring(pos);
        TetGpsData.GPSZoneListner_name = onlyClass;
        BROADCAST_ACTION = TetGpsData.GPSZoneListner_name;
        android.util.Log.d("LocationService", "!!!!!!!!!!!!!!!!! DEBUG onCreate BROADCAST_ACTION =" + BROADCAST_ACTION + "");
        intent = new Intent(BROADCAST_ACTION);
        getLocation();
       // schedule();
    }
 
   public void schedule() {
        if (tTask != null) tTask.cancel();
        if (interval > 0) {
            tTask = new TimerTask() {
                public void run() {
                    accuracy = location.getAccuracy();
                   // location.getAccuracy();
                    EventBus.getDefault().postSticky(new EventsGPS(accuracy));
                    android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG schedule OK accuracy="+accuracy+"");
                }
 
            };
            timer.schedule(tTask, 1000, interval);
        }
    }
 
    @Override
    public void onDestroy() {
//        EventBus.getDefault().register(this);
//        EventBus.getDefault().registerSticky(this);
        Timer timer;
        TimerTask tTask;
       // schedule("stop");
        tTask = null;
        long interval = 1000;
        super.onDestroy();
    }
 
    public GPSListnerZoneTracker(Context context) {
        this.mContext = context;
        getLocation();
    }
 
    public GPSListnerZoneTracker() {
        android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG onStartCommand OK");
//        EventBus.getDefault().register(this);
//        EventBus.getDefault().registerSticky(this);
        getLocation();
    }
 
    @Override
    public IBinder onBind(Intent arg0) {
        android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG onBind nethod OK");
        getLocation();
        return null;
    }
 
 
    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
 
            // getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
 
            // getting network status
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG GPS  isGPSEnabled=" + isGPSEnabled + " isNetworkEnabled=" + isNetworkEnabled + "");
            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
                this.canGetLocation = false;
            } else {
                // First get location from Network Provider
                if (isNetworkEnabled) {
                    //   locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("GPSListnerTracker", "Network Enabled");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            Log.d("GPSListnerTracker", "Посылаем апдате из этого места");
//                            latitude = location.getLatitude();
//                            longitude = location.getLongitude();
                        }
                    }
                }
                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                0,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPSListnerTracker", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                canGetLocation = true;
                                Log.d("GPSListnerTracker", "Посылаем апдате из этого места");
//                                latitude = location.getLatitude();
//                                longitude = location.getLongitude();
//                                altitiude = location.getAltitude();
//                                accuracy = location.getAccuracy();
                            }
                        }
                    }
                }
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return location;
 
    }
 
 
    ////////////////////////////////////////////////////////////////////////
    @Override
    public void onLocationChanged(Location loc) {
        BROADCAST_ACTION = TetGpsData.GPSZoneListner_name;
        Intent intent = new Intent(BROADCAST_ACTION);
        android.util.Log.d("GPSListnerTracker", "!!!!!!!!!!!!!!!!! DEBUG onLocationChanged nethod OK BROADCAST_ACTION = " + BROADCAST_ACTION + " Accuracy=" + loc.getAccuracy() + "");
        Log.i(getClass().getCanonicalName(), "Location changed Latitude=" + loc.getLatitude() + " Longitude=" + loc.getLongitude() + " ");
        if (isBetterLocation(loc, previousBestLocation)) {
//            loc.getLatitude();
//            loc.getLongitude();
//            intent.putExtra(TetGpsData.latitude_key, loc.getLatitude());
//            intent.putExtra(TetGpsData.longitude_key, loc.getLongitude());
//            intent.putExtra(TetGpsData.altitiude_key, loc.getAltitude());
//            intent.putExtra(TetGpsData.accuracy_key, loc.getAccuracy());
//            intent.putExtra(TetGpsData.bearing_key, loc.getBearing());
//            intent.putExtra(TetGpsData.speed_key, loc.getSpeed());
//            intent.putExtra(TetGpsData.provider_key, loc.getProvider());
//            intent.putExtra(TetGpsData.gpsTime_key, loc.getTime());
//            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
            TetGpsData.latitude_current = loc.getLatitude();
            TetGpsData.longitude_current = loc.getLongitude();
            TetGpsData.altitiude_current = loc.getAltitude();
            TetGpsData.accuracy_current = loc.getAccuracy();
            TetGpsData.bearing_current = loc.getBearing();
            TetGpsData.speed_current = loc.getSpeed();
            TetGpsData.provider_current = loc.getProvider();
            TetGpsData.gpsTime_current = loc.getTime();
          //  EventsGPS.ZoneLocationDates = loc;
            // Send Message with TAG about position changing
            EventBus.getDefault().post(new EventsGPS(loc), TetGpsData.gpsZone_tag);
        }
 
    }
 
    @Override
    public void onProviderDisabled(String provider) {
        Toast.makeText(getApplicationContext(), R.string.gpsIsOFF, Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onProviderEnabled(String provider) {
        Toast.makeText(getApplicationContext(), R.string.gpsIsON, Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
 
 
    ///////////////////////////////////////////////////////////////////////////////////
 
    /**
     * Function to get latitude
     */
    public double getLatitude() {
        if (location != null) {
            latitude = location.getLatitude();
        }
 
        // return latitude
        return latitude;
    }
 
    /**
     * Function to get longitude
     */
    public double getLongitude() {
        if (location != null) {
            longitude = location.getLongitude();
        }
 
        // return longitude
        return longitude;
    }
 
 
    public double getAltitude() {
        if (location != null) {
            altitiude = location.getAltitude();
        }
        return altitiude;
    }
 
    public float getAccuracy() {
        if (location != null) {
            accuracy = location.getAccuracy();
        }
 
        // return longitude
        return accuracy;
    }
 
 
    public float getBearing() {
        if (location != null) {
            bearing = location.getBearing();
 
        }
 
        // return longitude
        return bearing;
    }
 
 
    public float getSpeed() {
        if (location != null) {
            speed = location.getSpeed();
        }
 
        // return longitude
        return speed;
    }
 
 
    /**
     * Function to check if best network provider
     *
     * @return boolean
     */
    public boolean canGetLocation() {
 
        return this.canGetLocation;
    }
 
    /**
     * Function to show settings alert dialog
     */
    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
 
        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");
 
        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
 
        // Setting Icon to Dialog
        //alertDialog.setIcon(R.drawable.delete);
 
        // On pressing Settings button
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });
 
        // on pressing cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
 
        // Showing Alert Message
        alertDialog.show();
    }
 
    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     */
    public void stopUsingGPS() {
        if (locationManager != null) {
            locationManager.removeUpdates(GPSListnerZoneTracker.this);
 
        }
    }
 
    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }
 
        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > MIN_TIME_BW_UPDATES;
        boolean isSignificantlyOlder = timeDelta < -MIN_TIME_BW_UPDATES;
        boolean isNewer = timeDelta > 0;
 
        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return true;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return false;
        }
 
        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;
 
 
        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());
 
        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }
 
    /**
     * Checks whether two providers are the same
     */
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
21.09.2015, 17:10  [ТС]     GPS координаты раздельно по времени и минимальному смещению #5
И чё ? Никто не знает как?
Паблито
резкий
1960 / 1695 / 525
Регистрация: 12.05.2014
Сообщений: 6,046
Завершенные тесты: 1
21.09.2015, 18:39     GPS координаты раздельно по времени и минимальному смещению #6
дергай координаты по времени и если разница старой и новой координаты превысит порог - отсылай
profit

Добавлено через 15 минут
и еще мысль, которую проверять лень
а что если два раза прописать locationManager.requestLocationUpdates с разными параметрами и самое главное - с разными слушателями, в первом случае там передается this, а во втором сделать другого слушателя и передать его

при передаче первого настроить что бы получал по времени, а второго - параметры по минимальному расстоянию
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
22.09.2015, 12:32  [ТС]     GPS координаты раздельно по времени и минимальному смещению #7
Цитата Сообщение от Паблито Посмотреть сообщение
а что если два раза прописать locationManager.requestLocationUpdates с разными параметрами
Пробовал. ТОгда все обновляется по принципу "что раньше". Вся фишка в том что мне нужно инфу отправлять на сервер только в случаи если объект сместился на расстояние большее требования (типа SOS или аларм). Если он в пределах допуска, тогда он юзает для себя простое обновление по времени и не отправляет ничего на сервер - работает автономно.
Valakin
 Аватар для Valakin
430 / 96 / 15
Регистрация: 21.02.2015
Сообщений: 718
22.09.2015, 13:29     GPS координаты раздельно по времени и минимальному смещению #8
не используйте MIN_DISTANCE_CHANGE_FOR_UPDATES, как уже писали
дистанцию можно ведь и самому считать
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
22.09.2015, 13:39  [ТС]     GPS координаты раздельно по времени и минимальному смещению #9
Цитата Сообщение от Valakin Посмотреть сообщение
не используйте MIN_DISTANCE_CHANGE_FOR_UPDATES, как уже писали
дистанцию можно ведь и самому считать
От чего считать и как?

Можно получить только предыдущее измерение и текущее.

кажды раз текущее автоматом становиться предыдущим при следующем апдэйте. Тоесть объект может медленно смещаться по 0.n метров а нам не будет понятно от какого из обновлений отсчитать лимит за которым нужно послать аларм.

Вот такую задачу не могу решить.

Но раз ее решает ПО датчика (обновления по смещению) значит решение существует!?
Паблито
резкий
1960 / 1695 / 525
Регистрация: 12.05.2014
Сообщений: 6,046
Завершенные тесты: 1
22.09.2015, 13:53     GPS координаты раздельно по времени и минимальному смещению #10
origX, origY - оригинальные координаты (типа текущая позиция)
delta - расстояние, до которого программа не реагирует на изменение координат
каждый раз, по времени прилетают новые координаты, никуда их прибавлять не нужно

как только разница по X илиY станет больше чем дельта - запоминаем эти координаты как origX/Y и отсылаем сообщение что сместились
что трудного?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.09.2015, 15:41     GPS координаты раздельно по времени и минимальному смещению
Еще ссылки по теме:

Координаты gps (структура) Android
Как передавать динамические данные (координаты GPS) из активити в диалог? Android
Не получается получить координаты с GPS Android
Android Сбросить координаты GPS при потере сигнала
Получить координаты GPS Android

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

Или воспользуйтесь поиском по форуму:
zoleg
14 / 14 / 1
Регистрация: 10.01.2012
Сообщений: 117
22.09.2015, 15:41  [ТС]     GPS координаты раздельно по времени и минимальному смещению #11
Порешал простым копипасте - забадяжил два сервиса: GPSbyTimeListner GPSListnerZone - полет нормальный
Yandex
Объявления
22.09.2015, 15:41     GPS координаты раздельно по времени и минимальному смещению
Ответ Создать тему
Опции темы

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