Android: устройства Samsung Galaxy Tab и Android 2.2, отображающие дату GPS на 1 день раньше, чем 1 января 2012 г.

У меня есть Galaxy Tab GT-P1000 7 дюймов с прошивкой версии 2.3.3 и телефоны под управлением Android 2.2. В обеих версиях, когда я пытаюсь узнать время по GPS, он показывает опережение на 1 день с 1 января 2012 года. Тот же код отлично работает на телефонах Samsung, LG и Motorola.

Пример кода для приложения:

package com.vxceed.dateTime;


import java.util.Calendar;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class SampleDateTimeActivity extends Activity {

    private LocationManager locationManager;
    private  TextView tv;
    String varTime="";

    /**
     * Location Listener 
     */
    LocationListener locationListener = new LocationListener() {

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Toast.makeText(SampleDateTimeActivity.this,"GPS off", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onLocationChanged(Location location) {
            setCurrentLocation(location);

        }
    };



    private void setCurrentLocation(Location location) {

          varTime=String.valueOf(location.getTime());

    }


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        locationManager=(LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,0, locationListener);

         tv=(TextView)findViewById(R.id.textView1);

    }


     public void refreshTime(View v)
     {
        String currentGPSTime="";
        currentGPSTime=varTime;
        if(currentGPSTime.compareTo("")==0)
        {
            tv.setText("Time Not Available");
        }
        else
        {
            Calendar cal=Calendar.getInstance();
            cal.setTimeInMillis(new Long(currentGPSTime));

            long currentDeviceTime=Calendar.getInstance().getTimeInMillis();

            Calendar cal2=Calendar.getInstance();
            cal2.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE)-1,cal.get(Calendar.HOUR_OF_DAY),cal.get(Calendar.MINUTE));
            long currentGPSTime_less_one_Day=cal2.getTimeInMillis();

            tv.setText( "GPSTIME:"+cal.getTime().toString() +" \n GPS_TIME_in_Millis:"+varTime+"\nDevice_Time_in_millis:"+String.valueOf(currentDeviceTime) +"\nGPS Time -1 day:"+String.valueOf(currentGPSTime_less_one_Day));
        }
     }


    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        if (locationManager != null && locationListener != null){
            locationManager.removeUpdates(locationListener);
            locationManager = null;
        }
    }


}

Я искал в Google, а затем, сославшись на официальный документ NMEA, выяснил, как использовать данные NMEA. Вот рабочий код для прослушивателя NMEA:

NmeaListener nmeaListener = new NmeaListener() {

        @Override
        public void onNmeaReceived(long timestamp, String nmea) {

            parse(nmea);
        }
    };


    private boolean parse(String strNMEA) {

        // Discard the sentence if its checksum does not match our calculated
        // checksum
        boolean bStatus = false;
        try {
            if (!IsValid(strNMEA)) {

                return false;
            }
            String[] sArrNMEA = strNMEA.split(",");
            String strNMEAType = sArrNMEA[0];
            if (strNMEAType.equals("$GPRMC")) {

                bStatus = ParseGPRMC(sArrNMEA);
            } else {

                bStatus = false;
            }

            sArrNMEA = null;
        } catch (Exception e) {

        }
        return bStatus;

    }

    private boolean ParseGPRMC(String[] sArrNMEA) {

        boolean result = false;
        try {
            if (sArrNMEA.length > 9) {
                int Hr = 0;
                int Mins = 0;
                int Secs = 0;

                if (!sArrNMEA[1].equals("")) {

                    Hr = Integer.parseInt(sArrNMEA[1].substring(0, 2));
                    Mins = Integer.parseInt(sArrNMEA[1].substring(2, 4));

                    if (sArrNMEA[1].length() > 6) {

                        Secs = Integer.parseInt(sArrNMEA[1].substring(4, 6));
                    } else {
                        Secs = Integer.parseInt(sArrNMEA[1].substring(4));
                    }

                }
                if (!sArrNMEA[9].equals("")) {
                    int Day = Integer.parseInt(sArrNMEA[9].substring(0, 2));
                    int Month = Integer.parseInt(sArrNMEA[9].substring(2, 4));
                    if (Month > 0) {
                        Month = Month - 1;
                    }
                    int Year = Integer.parseInt(sArrNMEA[9].substring(4));
                    Year = 2000 + Year;

                    if (!sArrNMEA[1].equals("")) {

                        Calendar cal = Calendar.getInstance(TimeZone
                                .getTimeZone("UTC"));
                        cal.set(Year, Month, Day, Hr, Mins, Secs);

                        nmeaTime = String.valueOf(cal.getTimeInMillis());

                    }

                }



                result = true;
            }
        } catch (Exception e) {

        }

        return result;

    }

        private boolean IsValid(String strNMEA) {
        // Compare the characters after the asterisk to the calculation
        strNMEA = strNMEA.replace("\r", "");
        strNMEA = strNMEA.replace("\n", "");
        return strNMEA.substring(0, strNMEA.length())
                .substring(strNMEA.indexOf("*") + 1)
                .equalsIgnoreCase(GetChecksum(strNMEA));
    }

 private String GetChecksum(String strNMEA) {
    // Loop through all chars to get a checksum

    int Checksum = 0;
    try {
        char ch = '\0';
        for (int i = 0; i < strNMEA.length(); i++) {
            ch = strNMEA.charAt(i);
            if (ch == '$') {
                // Ignore the dollar sign
            } else if (ch == '*') {
                // Stop processing before the asterisk
                break;
            } else {
                // Is this the first value for the checksum?
                if (Checksum == 0) {
                    // Yes. Set the checksum to the value
                    Checksum = (byte) ch;
                } else {
                    // No. XOR the checksum with this character's value
                    Checksum = Checksum ^ (byte) ch;
                }
            }
        }
    } catch (Exception e) {

    }
    // Return the checksum formatted as a two-character hexadecimal
    return Integer.toHexString(Checksum);
}

person Shashi kant Singh    schedule 03.01.2012    source источник
comment
Я решил указанную выше проблему: используйте прослушиватель местоположения NMEA в Android. Это даст правильное время GPS.   -  person Shashi kant Singh    schedule 05.01.2012
comment
На трех устройствах, на которых я тестировал прослушиватель местоположения NMEA, дата, указанная прослушивателем, всегда была завтрашней.   -  person MiG62    schedule 08.01.2012
comment
Вы можете использовать следующий код для прослушивателя NMEA   -  person Shashi kant Singh    schedule 11.01.2012
comment
Мне просто интересно: если это показывает один день ВПЕРЕДИ, могу ли я просто проверить, есть ли receivedLocationTimestamp > new Date().getTime()? если бы он вернул true, я бы вычел 24 часа (в миллисекундах) из receivedLocationTimestamp. Как вы думаете, это может работать в долгосрочной перспективе? (@МиГ62)   -  person alex    schedule 04.09.2012
comment
@ShashikantSingh Как вы реализуете метод GetChecksum()?   -  person Bobs    schedule 15.10.2012
comment
Вот полный код с реализацией функции GetChecksum()   -  person Shashi kant Singh    schedule 07.11.2012
comment
Это ошибка Android или ошибка Samsung?   -  person Bobs    schedule 10.08.2014


Ответы (4)


Похоже, это влияет на все стандартные прошивки Samsung, я сообщаю Samsung об этом. Кажется, он изолирован для устройств Samsung. Так что если можно протестировать на другом устройстве, или поставить кастомную прошивку. оба они работали для меня. и ваш код выглядит хорошо, в этом нет ничего плохого, это проблема прошивки

РЕДАКТИРОВАТЬ: я связался с корейскими инженерами - они сказали, что не знали о проблеме, но исправили ее, и она должна быть исправлена ​​в последнем обновлении для SGS и других затронутых продуктов. (если, конечно, это устройство не обновлялось какое-то время - так что не уверен насчет SGT) Они сказали, что проблема связана с устройствами, использующими чипы Broadcomm ... так что да

Используйте приведенный выше код. у меня вроде работает, надо будет проверить на нескольких других устройствах, но да

person SeanSWatkins    schedule 05.01.2012
comment
У меня 92 устройства различных моделей Samsung и HTC. Среди этих устройств проблема ограничена теми, у которых есть процессор Hummingbird. Отмечу, что в некоторых версиях Samsung Galaxy Tab используется процессор Hummingbird. Не уверен, что ваш среди них. - person MiG62; 06.01.2012
comment
Это очень интересно. Интересно, почему прошивка так делает только на аппаратах с этим процессором. Кастомная прошивка решает эту проблему, но Samsung нужно выпустить исправление. - person SeanSWatkins; 09.01.2012

Я подозреваю, что Samsung надеялась, что это проблема високосного года, которая просто исчезнет после 1 марта 2012 года.

Жаль разочаровывать - но это не так! Мы наблюдаем эту проблему с приложением PhoneTrack, установленным на телефонах Samsung с 1 января, и она существует до сих пор.

Надеемся, что теперь Samsung будет действовать ответственно и выпустит обновления для всех устройств, затронутых этой ошибкой драйвера GPS.

person mayfly    schedule 02.03.2012

Я столкнулся с этой ошибкой на своем Nexus S под управлением Android 4.0.3 (раздражающе вызывая неправильную отметку времени для целого набора данных).

Вчера я обновился до 4.0.4, и это, кажется, решило проблему. Не уверен, что планируется выпуск исправлений для предыдущих версий Android.

Настоящий воющий жук, однако...

person tomtheguvnor    schedule 04.04.2012
comment
не могли бы вы взглянуть на мой комментарий (под вопросом)? Мне интересно, может ли этот подход работать (вместо этого NMEA). - person alex; 04.09.2012
comment
спс за обмен, проверяю. Какой досадный баг - person sivi; 21.04.2015

У меня это сработало, и я заменил метод IsValid(String strNMEA) этой функцией:

private boolean checksum(String strNMEA)
    {
        int checksum = 0;

        strNMEA = strNMEA.replace("\r", "");
        strNMEA = strNMEA.replace("\n", "");

        String strChecksum = strNMEA.substring(strNMEA.indexOf("*") + 1);

        String str = strNMEA.substring(1, strNMEA.indexOf("*"));

        for (int i = 0; i < str.length(); i++) {
            checksum = checksum ^ str.charAt(i);
        }

        return checksum == Integer.valueOf(strChecksum, 16);

    }
person Bobs    schedule 16.10.2012