BlackBerry Обновить местоположение через GPS или Cell Tower

Я пытаюсь обновить текущее местоположение одним нажатием кнопки. Местоположение может быть получено через GPS или Cell Tower, в зависимости от того, что доступно. Моя проблема в том, что я никогда не вижу "Экран загрузки". Я знаю, что это происходит, когда что-то появляется / закрывается мгновенно, а координаты остаются нулевыми. Может ли кто-нибудь мне помочь - что я делаю не так внизу?

Ни местоположение не обновляется, ни экран загрузки не появляется. Без экрана загрузки и несколькими нажатиями кнопки "Обновить" я получаю местоположение. Ниже приведен мой код для обработки нажатий на кнопку "Обновить":

FieldChangeListener refreshImgListener = new FieldChangeListener() {   
    public void fieldChanged(Field field, int context) 
    {
        Thread backgroundWorker = new Thread(new Runnable() {
            public void run() {
                refreshCoordinates();
            }
        });
        busyDialog.setEscapeEnabled(false);  
        busyDialog.show();
        backgroundWorker.start();
    }
};

И мой refreshCoordinates() метод, как показано ниже:

public void refreshCoordinates() {
    do
    {
        getLatitude(handleeGPS.latitude);
        getLongitude(handleeGPS.longitude);
    } while ((longi == "0.0" || lati == "0.0") || (longi.length() == 0 || lati.length()==0));

    UiApplication.getUiApplication().invokeLater( new Runnable()
    {
        public void run ()
        {
            lblLatitude.setText(lati);
            lblLongitude.setText(longi);
            busyDialog.cancel();
        }
    } );
}

public static String getLatitude(double value) 
{
    lati= Double.toString(value);
    return lati;
}
public static String getLongitude(double value) 
{
    longi= Double.toString(value);
    return longi;
}

Класс, который возвращает значения широты и долготы:

public class handleeGPS{

    static GPSThread gpsThread;
    public static double latitude;
    public static double longitude;

    public handleeGPS(){
        gpsThread = new GPSThread();
        gpsThread.start();
    }

    private static class GPSThread extends Thread{
        public void run() {
            Criteria myCriteria = new Criteria();
            myCriteria.setCostAllowed(false);
            int m_bbHandle = CodeModuleManager.getModuleHandle("net_rim_bb_lbs");
            if(m_bbHandle>0){
                try {
                    int cellID = GPRSInfo.getCellInfo().getCellId();
                    int lac = GPRSInfo.getCellInfo().getLAC();
                    String urlString2 = "http://www.google.com/glm/mmap";
                    // Open a connection to Google Maps API
                    ConnectionFactory connFact = new ConnectionFactory();
                    ConnectionDescriptor connDesc;
                    connDesc = connFact.getConnection(urlString2);
                    HttpConnection httpConn2;
                    httpConn2 = (HttpConnection)connDesc.getConnection();
                    httpConn2.setRequestMethod("POST");
                    // Write some custom data to Google Maps API
                    OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream();
                    WriteDataGoogleMaps(outputStream2, cellID, lac);
                    // Get the response
                    InputStream inputStream2 = httpConn2.openInputStream();//getInputStream();
                    DataInputStream dataInputStream2 = new DataInputStream(inputStream2);
                    // Interpret the response obtained
                    dataInputStream2.readShort();
                    dataInputStream2.readByte();
                    int code = dataInputStream2.readInt();
                    //Dialog.alert(code+"");
                    if (code == 0) {
                        latitude= dataInputStream2.readInt() / 1000000D;
                        longitude=dataInputStream2.readInt() / 1000000D;
                        //Dialog.alert(latitude+"-----"+longitude);
                        dataInputStream2.readInt();
                        dataInputStream2.readInt();
                        dataInputStream2.readUTF();
                    } else {
                        System.out.println("Error obtaining Cell Id ");
                    }
                    outputStream2.close();
                    inputStream2.close();
                } catch (Exception e) {
                    System.out.println("Error: " + e.getMessage());
                }
            } else {
                try {
                    LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria);
                    try {
                        Location myLocation = myLocationProvider.getLocation(300);
                        latitude  = myLocation.getQualifiedCoordinates().getLatitude();
                        longitude = myLocation.getQualifiedCoordinates().getLongitude();
                        if(latitude==0.0 && longitude==0.0){
                            try {
                                int cellID = GPRSInfo.getCellInfo().getCellId();
                                int lac = GPRSInfo.getCellInfo().getLAC();
                                String urlString2 = "http://www.google.com/glm/mmap";
                                // Open a connection to Google Maps API
                                ConnectionFactory connFact = new ConnectionFactory();
                                ConnectionDescriptor connDesc;
                                connDesc = connFact.getConnection(urlString2);
                                HttpConnection httpConn2;
                                httpConn2 = (HttpConnection)connDesc.getConnection();
                                httpConn2.setRequestMethod("POST");
                                // Write some custom data to Google Maps API
                                OutputStream outputStream2 = httpConn2.openOutputStream();
                                //getOutputStream();
                                WriteDataGoogleMaps(outputStream2, cellID, lac);
                                // Get the response
                                InputStream inputStream2 = httpConn2.openInputStream();
                                //getInputStream();
                                DataInputStream dataInputStream2 = new DataInputStream(inputStream2);
                                // Interpret the response obtained
                                dataInputStream2.readShort();
                                dataInputStream2.readByte();
                                int code = dataInputStream2.readInt();
                                //Dialog.alert(code+"");
                                if (code == 0) {
                                    latitude= dataInputStream2.readInt() / 1000000D;
                                    longitude=dataInputStream2.readInt() / 1000000D;
                                    //Dialog.alert(latitude+"-----"+longitude);
                                    dataInputStream2.readInt();
                                    dataInputStream2.readInt();
                                    dataInputStream2.readUTF();
                                } else {
                                    System.out.println("Error obtaining Cell Id ");
                                }
                                outputStream2.close();
                                inputStream2.close();
                            } catch (Exception e) {
                                System.out.println("Error: " + e.getMessage());
                            }
                        }
                    }
                    catch ( InterruptedException iex ) {
                        return;
                    }
                    catch ( LocationException lex ) {
                        return;
                    }
                } catch ( LocationException lex ) {
                    return;
                }
            }
            return;
        }
    }

    private static void WriteDataGoogleMaps(OutputStream out, int cellID, int lac)
    throws IOException {
        DataOutputStream dataOutputStream = new DataOutputStream(out);
        dataOutputStream.writeShort(21);
        dataOutputStream.writeLong(0);
        dataOutputStream.writeUTF("en");
        dataOutputStream.writeUTF("Android");
        dataOutputStream.writeUTF("1.0");
        dataOutputStream.writeUTF("Web");
        dataOutputStream.writeByte(27);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(3);
        dataOutputStream.writeUTF("");
        dataOutputStream.writeInt(cellID);
        dataOutputStream.writeInt(lac);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.flush();
    }
}

3 ответа

Решение

Итак, хотя мой первоначальный ответ был действительным, у нового кода, который вы опубликовали, есть некоторые другие проблемы, поэтому я публикую второй ответ. Было достаточно вещей, которые выглядели не так, что я просто переписал handleeGPS учебный класс. Я объясню основные изменения, которые я сделал, один за другим:

  1. Попробуйте использовать соглашения об именах Java. Это помогает нам помочь вам. Перед тем, как вы разместили код в своем handleeGPS класс, я думал, что это переменная, потому что строчные имена обычно используются для переменных, а не классов.

  2. Избегайте дублирования кода. handleeGPS У класса было много кода для чтения, но в основном это был код для определения местоположения через веб-сервис Google, который вы дублировали в двух местах. Просто создайте метод, который содержит только этот код, и вызовите его дважды.

  3. Я переименовал ваш handleeGPS класс для GPSHandler, Я не уверен, если handlee была ошибка, или если это слово на другом языке, который вы использовали. В любом случае имя должно начинаться с заглавной буквы.

  4. Избегайте много static переменные и методы. Иногда действительно должно быть только одно из чего-то. Класс обработки GPS, вероятно, является хорошим примером этого, потому что устройство имеет только одну систему GPS. Но, чтобы обеспечить выполнение этой конструкции кода, не помечайте все как static, Просто сделайте класс Singleton, который включает в себя создание только одного static переменная-член (_instance) и один статический метод (getInstance()). В моем коде вы получите доступ к классу следующим образом: GPSHandler gps = GPSHandler.getInstance();,

  5. Я считаю, что проверка, была ли у вас установлена ​​карта BB, на самом деле была обратной. Вы посмотрели вверх net_rim_bb_lbs модуля, и если он был больше нуля (что означает, что BB Maps установлен), то вы обратились непосредственно к веб-сервису Google. Я думаю, что вы хотите наоборот (попробуйте устройство GPS, если установлены BB Maps). Кроме того, начиная с 6.0, вы должны проверить net_rim_bb_maps, тоже.

  6. Прежде чем вы разместили обновление, я думал, что ваш getLatitude() а также getLongitude() методы фактически выбирали местоположение устройства. Это было плохое предположение с моей стороны. Они просто конвертировали числа в строки. Таким образом, нет никаких причин для этого в фоновом режиме (с Thread). Вы уже написали свой handleeGPS класс, чтобы использовать фоновый поток, что хорошо. Одной фоновой нити достаточно. Пользовательский интерфейс, который использует информацию о местоположении, также не должен иметь фона Thread, Я изменил код, чтобы добавить GPSListener интерфейс. Этот интерфейс должен быть реализован вашим кодом пользовательского интерфейса, чтобы получать обновления местоположения. Нет причин продолжать цикл, спрашивая, не совпадает ли местоположение с {0.0, 0.0}. Это неэффективно. С моим кодом вы просто получите уведомление, когда местоположение действительно изменится.

  7. Оригинальный код не был потокобезопасным. handleeGPSlatitude а также longitude переменные были установлены в фоновом потоке и доступны в потоке пользовательского интерфейса. Это не безопасно. Два потока не должны одновременно считывать и записывать один и тот же фрагмент данных. Изменяя код, чтобы передать данные о местоположении в GPSListenerЭто позволяет избежать этой проблемы.

  8. Я раскомментировал Dialog.alert() код у вас внутри handleeGPS класс, который не работал бы для вас, потому что вы не можете делать вызовы пользовательского интерфейса из фона. Я окружил эти звонки UiApplication.getUiApplication().invokeLater() сделать их безопасными.

Чтобы использовать этот класс, в своем коде пользовательского интерфейса вы должны сделать это вместо использования Thread запустить свой refreshCoordinates() метод:

public void fieldChanged(Field field, int context) 
    // this is called when your location refresh button is clicked
    GPSHandler.getInstance().setListener(this); 
    GPSHandler.getInstance().requestLocationUpdates();
    busyDialog.setEscapeEnabled(false);  
    busyDialog.show();
}

...

public void onLocationReceived(Coordinates location) {
    lblLatitude.setText(Double.toString(location.getLatitude()));               
    lblLongitude.setText(Double.toString(location.getLongitude()));               
    busyDialog.cancel();               
}     

Убедитесь, что класс, в который вы положили этот код (выше), также implements GPSListener, который является интерфейсом, определенным здесь:

public interface GPSListener {
    public void onLocationReceived(Coordinates location);
}

и, наконец, GPSHandler:

public class GPSHandler { 

   private GPSThread _gpsThread;
   private Coordinates _location;
   private boolean _gotLocation;
   private GPSListener _listener;

   /** this class will be a Singleton, as the device only has one GPS system */
   private static GPSHandler _instance;

   /** @return the Singleton instance of the GPSHandler */
   public static GPSHandler getInstance() {
      if (_instance == null) {
         _instance = new GPSHandler();
      }
      return _instance;
   }

   /** not publicly accessible ... use getInstance() */
   private GPSHandler() { 
   }

   /** call this to trigger a new location fix */
   public void requestLocationUpdates() {
       if (_gpsThread == null || !_gpsThread.isAlive()) {
          _gpsThread = new GPSThread();
          _gpsThread.start(); 
       }
   }

   public void setListener(GPSListener listener) {
      // only supports one listener this way
      _listener = listener;   
   }

   private void setLocation(final Coordinates value) {
      _location = value;
      if (value.getLatitude() != 0.0 || value.getLongitude() != 0.0) {
         _gotLocation = true;
         if (_listener != null) {
            // this assumes listeners are UI listeners, and want callbacks on the UI thread:
            UiApplication.getUiApplication().invokeLater(new Runnable() {
               public void run() {
                  _listener.onLocationReceived(value);
               }
            });
         }
      }
   }

   private class GPSThread extends Thread {

      private void getLocationFromGoogle() {
         try { 
            int cellID = GPRSInfo.getCellInfo().getCellId(); 
            int lac = GPRSInfo.getCellInfo().getLAC(); 

            String urlString2 = "http://www.google.com/glm/mmap"; 

            // Open a connection to Google Maps API  
            ConnectionFactory connFact = new ConnectionFactory(); 
            ConnectionDescriptor connDesc; 
            connDesc = connFact.getConnection(urlString2); 

            HttpConnection httpConn2; 
            httpConn2 = (HttpConnection)connDesc.getConnection(); 
            httpConn2.setRequestMethod("POST"); 

            // Write some custom data to Google Maps API  
            OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream(); 
            writeDataGoogleMaps(outputStream2, cellID, lac); 

            // Get the response   
            InputStream inputStream2 = httpConn2.openInputStream();//getInputStream(); 
            DataInputStream dataInputStream2 = new DataInputStream(inputStream2); 

            // Interpret the response obtained  
            dataInputStream2.readShort(); 
            dataInputStream2.readByte(); 

            final int code = dataInputStream2.readInt(); 
            UiApplication.getUiApplication().invokeLater(new Runnable() {
               public void run() {
                  Dialog.alert(code + "");   
               }
            });                        

            if (code == 0) { 
               final double latitude = dataInputStream2.readInt() / 1000000D; 
               final double longitude = dataInputStream2.readInt() / 1000000D; 
               setLocation(new Coordinates(latitude, longitude, 0.0f));

               UiApplication.getUiApplication().invokeLater(new Runnable() {
                  public void run() {
                     Dialog.alert(latitude+"-----"+longitude);   
                  }
               });

               dataInputStream2.readInt(); 
               dataInputStream2.readInt(); 
               dataInputStream2.readUTF(); 
            } else { 
               System.out.println("Error obtaining Cell Id "); 
            } 
            outputStream2.close(); 
            inputStream2.close(); 
         } catch (Exception e) { 
            System.out.println("Error: " + e.getMessage()); 
         } 
      }

      private void tryGetLocationFromDevice() {
         _gotLocation = false;
         try {
            Criteria myCriteria = new Criteria(); 
            myCriteria.setCostAllowed(false); 
            LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria); 

            try { 
               Location myLocation = myLocationProvider.getLocation(300); 
               setLocation(myLocation.getQualifiedCoordinates()); 
            } catch ( InterruptedException iex ) { 
               System.out.println(iex.getMessage());
            } catch ( LocationException lex ) { 
               System.out.println(lex.getMessage());
            } 
         } catch ( LocationException lex ) { 
            System.out.println(lex.getMessage());
         }

         if (!_gotLocation) { 
            getLocationFromGoogle();
         } 
      }

      public void run() { 
         int bbMapsHandle = CodeModuleManager.getModuleHandle("net_rim_bb_lbs");    // OS < 6.0
         int bbMapsHandle60 = CodeModuleManager.getModuleHandle("net_rim_bb_maps"); // OS 6.0+
         if (bbMapsHandle > 0 || bbMapsHandle60 > 0) { 
            tryGetLocationFromDevice();
         } else {
            getLocationFromGoogle();
         }
      } 
   } 

   private void writeDataGoogleMaps(OutputStream out, int cellID, int lac) throws IOException { 
      DataOutputStream dataOutputStream = new DataOutputStream(out); 
      dataOutputStream.writeShort(21); 
      dataOutputStream.writeLong(0); 
      dataOutputStream.writeUTF("en"); 
      dataOutputStream.writeUTF("Android"); 
      dataOutputStream.writeUTF("1.0"); 
      dataOutputStream.writeUTF("Web"); 
      dataOutputStream.writeByte(27); 
      dataOutputStream.writeInt(0); 
      dataOutputStream.writeInt(0); 
      dataOutputStream.writeInt(3); 
      dataOutputStream.writeUTF(""); 

      dataOutputStream.writeInt(cellID); 
      dataOutputStream.writeInt(lac); 

      dataOutputStream.writeInt(0); 
      dataOutputStream.writeInt(0); 
      dataOutputStream.writeInt(0); 
      dataOutputStream.writeInt(0); 
      dataOutputStream.flush(); 
   } 

} 

Там много кода, который мы не можем увидеть (например, getLatitude(), getLongitude(), refreshDetails()). Так что там может быть что-то не так. Кроме того, в коде, который вы разместили, я не вижу экрана загрузки, поэтому не могу сказать, почему он не отображается.

Но вот что-то, что выглядит не так:

        synchronized (Application.getEventLock())
        {
            busyDialog.show();
        }

Если вы прочитаете этот вопрос на форуме BlackBerry, вы увидите, что попытка синхронизации при блокировке событий приложения из основного потока (UI) может привести к зависанию вашего приложения. public void fieldChanged(Field field, int context) метод всегда вызывается в потоке пользовательского интерфейса, потому что это поток пользовательского интерфейса, который отслеживает нажатия кнопок и вызывает ваши обработчики кликов, например fieldChanged(),

Вы также можете прочитать документы BlackBerry API для приложений, в которых объясняется, что getEventLock() предназначен для рабочих (также называемых фоновыми) потоков, а не для основного потока (или пользовательского интерфейса).

Таким образом, нет необходимости использовать специальные методы для блокировки событий в коде, который уже выполняется в потоке пользовательского интерфейса. Вместо приведенного выше кода, просто сделайте это:

            busyDialog.show();

Обе эти техники:

        synchronized (Application.getEventLock())
        {
            busyDialog.show();
        }

или же

        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
               busyDialog.show();  
            }
        });

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

Попробуйте исправить это и посмотрите, исчезнет ли ваша проблема.

Редактировать: также, ваш код проверяет имя пользователя и пароль перед обновлением местоположения. Это действительно то, что вы хотите? Я не думаю, что это как-то связано с вашей проблемой, но обычно я не ожидаю, что для доступа к службам определения местоположения потребуется имя пользователя или пароль. Конечно, я не знаю вашу заявку, так что это на самом деле просто комментарий с моей стороны.

Я думаю, что ты простой ответ, здесь ошибка:

((longi == "0.0" || lati == "0.0") || (longi.length() == 0 || lati.length()==0));

Вы должны использовать String.equals() вместо == оператор.

После первого звонка longi а также lati иметь "0.0" значение. Но == вернусь false потому что он сравнивает ссылки по умолчанию, и они разные, потому что это разные объекты.

Другие вопросы по тегам