黑莓应用程序开发 - 应用程序停止工作16-18小时后

时间:2012-04-10 13:10:45

标签: web-services blackberry timer gps timertask

我在一开始就大声道歉,因为我知道回答这个问题就像将jello钉在墙上一样。我将尽可能多地提供详细信息,但没有太多可以给予。

我正在开发一款Blackberry应用程序,它使用GPS每隔xx分钟获取一个用户的位置(可能是15,30或60,具体取决于用户设置的偏好);它将位置数据发送到Web服务。

它运行正常并报告用户的位置正常,但只有大约16-18小时,然后应用程序停止报告,用户界面不再有效。不会抛出任何错误,它只会在重新启动应用程序之前不再响应用户选择。

对我来说很奇怪,应用程序崩溃是相当可预测的 - 它在8小时或10小时之后永远不会崩溃,它总是在16-18小时的窗口中,这告诉我崩溃与GPS / WebService报告。

基本上,如果我从GPS / WebService的角度来看,看起来应用程序可以设法向WebService报告36次(每半小时18小时),然后它就会死亡。

我会在这里发布一些代码,希望能引发某人的想法。

private void updateGPSLocation(){
    gps_interval_timer.scheduleAtFixedRate(new TimerTask() {
       public void run() {
         try{

           getGPSLocation();
           if(longitude != 0.0 && latitude != 0.0)
           {
             updateSubscriberLocation();
           }

          }catch(Exception ex){                 
             }
      }
  }, 0, gps_interval);
}

这是上一代码中引用的getGPSLocation()调用的代码:

public void getGPSLocation(){
     try{
          //GPS thread
           BlackBerryLocationProvider provider = (BlackBerryLocationProvider)LocationProvider.getInstance(new BlackBerryCriteria(GPSInfo.GPS_MODE_ASSIST));

          //geolocation thread
           BlackBerryLocationProvider provider1 = (BlackBerryLocationProvider)LocationProvider.getInstance(new BlackBerryCriteria(LocationInfo.GEOLOCATION_MODE_CELL));

        if (provider != null){
            provider.setLocationListener(new LocationListenerImpl(), _interval, 1, 1);
         }

         if(provider1 != null){
            provider1.setLocationListener(new LocationListenerImpl(), _interval, 1, 1);
         }
      }
      catch(Exception le){
       }        
}

再次,对不起,我知道这是一个开放式的问题。 Blackberry GPS有任何已知问题吗?因为我正在使用计时器任务来安排基于时间间隔的报告,我是否可能通过将预定的计时器任务放入队列来吸收所有可用内存?我是否需要使用cancel()方法显式处理计时器任务?类似的东西:

gps_interval_timer.scheduleAtFixedRate(new TimerTask() {
       public void run() {
         try{

           getGPSLocation();
           if(longitude != 0.0 && latitude != 0.0)
           {
             updateSubscriberLocation();
           }

          }catch(Exception ex){                 
             }
          finally
          {
             this.cancel();
          }

      }
  }, 0, gps_interval);

非常感谢任何帮助。谢谢!

使用LocationListener代码更新

private class LocationListenerImpl implements LocationListener { 
    public void locationUpdated(LocationProvider provider, Location location) {
    if(location.isValid()) {
       longitude = location.getQualifiedCoordinates().getLongitude();
       latitude = location.getQualifiedCoordinates().getLatitude(); 
     }
   }
    public void providerStateChanged(LocationProvider provider, int newState) {

    }
}

getGPSLocation()中使用的_interval变量设置为-1。

1 个答案:

答案 0 :(得分:1)

我认为您需要重新考虑代码。您正在使用计时器以gps_interval指定的速率创建BlackBerryLocationProvider,该速率将以_interval指定的速率获取位置,并调用LocationListenerImpl的locationUpdated()方法(您为每个BlackBerryLocationProvider创建新方法。至少存在两个潜在问题这里:

  1. 我怀疑_interval与gps_interval有关,在这种情况下,在gps_interval创建一个位置提供程序之后,在向侦听器提供位置之前等待_interval时间量。到目前为止,您的计时器可能已经过期,导致另一个位置提供程序被创建...消耗的资源超出了必要的数量。
  2. 您尚未向我们展示您的LocationListener实现。如果您没有关闭BlackBerryLocationProvider并释放LocationListenerImpl,那么每次计时器到期时,您将创建消耗更多资源的新对象,而不会释放旧资源。
  3. 调用setLocationListener()有一个interval参数的原因之一是支持你想要做的事情,即定期提供一个位置。使用此功能可让操作系统更智能地处理GPS如何处理GPS,如果使用不当,这将是一个重要的电池消耗。

    因此,当您需要位置时,请创建提供程序,为您指定侦听器所需的时间间隔,然后处理侦听器中的位置。确保在单独的线程上连接到后端Web服务。如果停止等待服务器响应的事件线程,则会给系统带来更多麻烦。

    编辑:

    这可能是getGPSLocation()的一个实现,可以满足您的需求。它将尝试一组标准,然后是另一组标准。它仍然依赖于间隔的计时器,但不使用位置提供程序的间隔/回调属性。由于它没有注册监听器,一旦提供者超出范围,它将受到垃圾收集。

    public void getGPSLocation(){
       try{
          //GPS thread
          BlackBerryLocationProvider provider =
             (BlackBerryLocationProvider)LocationProvider.getInstance(
             new BlackBerryCriteria(GPSInfo.GPS_MODE_ASSIST));
    
           if (provider != null){
              try {
                 Location location = provider.getLocation(timeout);
                 // process location
                 return;
              } catch (LocationException le) {
              } catch (Exception e) {
              }
           }
    
           provider =
              (BlackBerryLocationProvider)LocationProvider.getInstance(
              new BlackBerryCriteria(LocationInfo.GEOLOCATION_MODE_CELL));
    
           if (provider != null){
              try {
                 Location location = provider.getLocation(timeout);
                 // process location
              } catch (LocationException le) {
              } catch (Exception e) {
              }
           }
        }
        catch(Exception le){
        }        
     }
    

    说过更好的方法可能是用(来自API文档)替换updateGPSPosition和getGPSPositioin:

    public void updateGPSPosition() {
       BlackBerryCriteria bbCriteria;
       BlackBerryLocationProvider bbProvider;
    
       try { //setup Criteria
          bbCriteria = new BlackBerryCriteria()); // use default mode on the device
          bbCriteria.enableGeolocationWithGPS();  // retrieve geolocation fix if GPS fix unavailable
       } catch (UnsupportedOperationException uoe) {}
    
       try { //setup LocationProvider
          bbProvider = (BlackBerryLocationProvider)LocationProvider.getInstance(bbCriteria);
          bbprovider.setLocationListener(new LocationListenerImpl(), interval, timeout, maxage);
       } catch (LocationException le) {}
    
    }
    

    您可能希望将bbCriteria和bbProvider保存在以后可以更改间隔的位置,或者只是停止获取位置。

    很难找到在providerStateChanged()内部做什么这是我通常使用的:

    public void providerStateChanged(LocationProvider provider, int newState) {
        if (newState == LocationProvider.TEMPORARILY_UNAVAILABLE)
        {
            if (unavailableCount < 3) {
                System.err.println("TEMPORARILY_UNAVAILABLE Reset " + Integer.toString(unavailableCount));
    
                // de-register listener, reset the provider and re-register
                locationProvider.setLocationListener(null, -1, -1, -1);
                locationProvider.reset();
                locationProvider.setLocationListener(this, 1, -1, -1);
                unavailableCount++;
            } else {
                System.err.println("TEMPORARILY_UNAVAILABLE Suspend");
                locationProvider.setLocationListener(null, -1, -1, -1);
            }
        }
        else if (newState == LocationProvider.AVAILABLE)
        {
            unavailableCount = 0;
        }
        else {
            System.err.println("OUT_OF_SERVICE");
            locationProvider.setLocationListener(null, -1, -1, -1);
        }
    }