BlackBerry刷新位置通过GPS或Cell Tower

时间:2012-08-14 06:20:00

标签: blackberry java-me gps location gps-time

我正试图通过点击按钮刷新当前位置。可以通过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 个答案:

答案 0 :(得分:5)

好的,所以虽然我的原始答案是有效的,但您发布的代码有一些不同的问题,所以我发布了第二个答案。有足够的事情看起来不对,我刚刚重写了你的handleeGPS课程。我将逐一解释我所做的重大改变:

  1. 尝试使用Java naming conventions。这使我们更容易为您提供帮助。在将代码发布到handleeGPS类之前,我认为它是一个变量,因为小写名称通常用于变量,而不是类。

  2. 避免重复代码。 handleeGPS课程有很多代码可供阅读,但大部分都是从Google的网络服务获取位置的代码,您可以在两个地方复制这些代码。只需创建一个只包含该代码的方法,然后调用它两次。

  3. 我将您的handleeGPS课程重命名为GPSHandler。我不确定handlee是否是错误,或者是否是您使用的其他语言的单词。无论如何,名称至少应以大写字母开头。

  4. 避免使用大量static变量和方法。有时,确实应该只有一个东西。 GPS处理类可能就是一个很好的例子,因为该设备只有一个GPS系统。但是,要强制执行此代码构造,请不要将所有内容标记为static。仅make the class a Singleton,其中只涉及创建一个static成员变量(_instance)和一个静态方法(getInstance())。在我的代码中,您将访问类:GPSHandler gps = GPSHandler.getInstance();

  5. 我相信你对是否安装了BB地图的检查实际上是倒退了。您查找了net_rim_bb_lbs模块,如果它大于零(这意味着安装了BB地图),那么您就直接访问了Google网络服务。我认为你想要反过来(如果安装了BB地图,请尝试设备GPS)。此外,自6.0起,您还需要检查net_rim_bb_maps

  6. 在您发布更新之前,我认为您的getLatitude()getLongitude()方法实际上是在获取设备位置。这对我来说是一个糟糕的假设。他们只是将数字转换为字符串。所以,没有理由在后台完成(使用Thread)。您已经编写了handleeGPS类来使用后台线程,这很好。一个后台线程就足够了。使用位置信息的用户界面不应该还需要背景Thread。我更改了代码以添加GPSListener接口。该接口应由您的UI代码实现,以接收位置更新。没有理由继续循环,询问位置是否不等于{0.0,0.0}。那效率很低。使用我的代码,您只需在位置发生变化时收到通知。

  7. 原始代码不是线程安全的。 handleeGPS latitudelongitude变量在后台线程上设置,并在UI线程上访问。那不安全。两个线程不应该同时读取和写入同一条数据。通过更改代码以将位置数据推送到GPSListener,可以避免此问题。

  8. 我取消注释了Dialog.alert()课程中的handleeGPS代码,这对您没有用,因为您不允许从后台进行UI调用。我用UiApplication.getUiApplication().invokeLater()包围了这些电话,以确保它们安全。

  9. 要在您的UI代码中使用此类,您可以执行此操作,而不是使用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(); 
       } 
    
    } 
    

答案 1 :(得分:2)

我们看不到很多代码(例如getLatitude()getLongitude()refreshDetails())。所以,那里可能会出现问题。此外,我在您发布的代码中看不到任何加载屏幕,所以我不能说为什么没有显示。

但是,这看起来不对劲:

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

If you read this BlackBerry forum question,您会看到尝试同步应用事件锁来自主(UI)线程会导致您的应用冻结。始终在UI线程上调用public void fieldChanged(Field field, int context)方法,因为它是监视点击按钮的UI线程,并回调您的点击处理程序,如fieldChanged()

您还可以阅读the BlackBerry API docs for Application,其中说明getEventLock()适用于 worker (也称为后台)主题,而不是主要内容(又名 UI )线程。

因此,在已经在UI线程上运行的代码中,不需要使用特殊技术来获取事件锁定。而不是上面的代码,只需这样做:

            busyDialog.show();

这两种技术都是:

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

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

安全后台主题调用UI方法的方法。但是,您不应该在已经在UI线程上运行的代码中使用它们。

尝试修复它,看看问题是否消失。

编辑,在刷新位置之前,您的代码正在检查用户名和密码。这真的是你想要的吗?我不认为这与您的问题有任何关系,但通常情况下,我不希望需要用户名或密码来访问位置服务。当然,我不知道你的申请,所以这只是我的评论。

答案 2 :(得分:2)

我认为你的答案很简单就是错误:

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

您必须使用String.equals()代替==运营商。

首次通话后longilati"0.0"值。但是==会返回false,因为默认情况下它会比较引用,但它们是不同的,因为它是不同的对象。