使用带有 GPS 提供程序的 requestLocationUpdates 永远不会调用 onLocationChanged

Posted

技术标签:

【中文标题】使用带有 GPS 提供程序的 requestLocationUpdates 永远不会调用 onLocationChanged【英文标题】:onLocationChanged is never called by using requestLocationUpdates with GPS provider 【发布时间】:2013-09-11 15:52:16 【问题描述】:

我正在开发一个应用程序,通过使用服务来跟踪用户的位置并将数据发送到后台的服务器。这是基于 GPS 的应用程序。当我的程序使用 GPS 提供程序调用 requestLocationUpdates 时,永远不会调用 onLocationChanged。但是,requestLocationUpdates 与我的应用程序上的网络提供商一起工作得很好。请看我的代码。

安卓版本:4.1.2 设备:Galaxy nexus S

Tracker.java

private void init() 
    locationListener = new MyLocationListener();
    mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    NOTIFICATION = R.string.local_service_started;
    arrivedStatus = false;
    activity = TrackerActivity.getAppActivity();


@Override
public void onCreate() 
    super.onCreate();
    init();
    Log.i(tag, "Start Tracking");
    showStartNotification();


@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    Log.i("LocalService", "Received start id " + startId + ": " + intent);
    tripID = intent.getExtras().getInt("tripID") + "";
    locationInterval = intent.getExtras().getInt("locationInterval")
            * MILLISECONDS_PER_SECOND;
    //lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
    //      locationInterval, 0, locationListener);
    getLocation();
    return START_STICKY;


@Override
public void onDestroy() 
    super.onDestroy();
    Log.e("STOP_SERVICE", "Service has stopped");
    mNM.cancel(R.string.local_service_started);
    lm.removeUpdates(locationListener);
    stopSelf();


private void getLocation() 
    lm = (LocationManager) getApplicationContext().getSystemService(
            Context.LOCATION_SERVICE);

    // getting GPS status
    isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);

    // getting network status
    isNetworkEnabled = lm
            .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

    if (!isGPSEnabled && !isNetworkEnabled) 
        // no network provider is enabled
        Log.e(tag, "Non providers are enabled");
     else 

        if (isGPSEnabled) 
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                    locationInterval, 0, locationListener);
            Log.d(tag, "GPS Enabled");
        

        if (isNetworkEnabled) 
            if (lm == null) 
                lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                        locationInterval, 0, locationListener);
                Log.d(tag, "Network Enabled");
            
        
    


@Override
public IBinder onBind(Intent intent) 
    // TODO Auto-generated method stub
    return null;


@SuppressWarnings("deprecation")
private void showStartNotification() 
    // In this sample, we'll use the same text for the ticker and the
    // expanded notification
    CharSequence text = getText(R.string.local_service_started);

    // Set the icon, scrolling text and timestamp
    Notification notification = new Notification(R.drawable.cameral, text,
            System.currentTimeMillis());

    // The PendingIntent to launch our activity if the user selects this
    // notification+
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, TrackerActivity.class), 0);

    // Set the info for the views that show in the notification panel.
    notification.setLatestEventInfo(this,
            getText(R.string.local_service_label), text, contentIntent);

    // Send the notification.
    mNM.notify(NOTIFICATION, notification);


/**
 * private void showStopSpecification()  CharSequence text =
 * getText(R.string.local_service_cancel); Notification notification = new
 * Notification(R.drawable.btn_save_dialog, text,
 * System.currentTimeMillis()); mNM.notify(NOTIFICATION, notification); 
 */

private void checkResult(JSONObject json) 
    try 
        if (json.getString(KEY_SUCCESS) != null) 
            String res = json.getString(KEY_SUCCESS);
            if (Integer.parseInt(res) == 1) 
                Log.v(tag, "Store data successfully");
                activity.findViewById(R.id.tracker_info)
                        .setBackgroundResource(R.color.blue4);
                if (json.getInt(ARRIVED_STATUS) == 1) 
                    setArrivedStatus(true);
                 else 
                    setArrivedStatus(false);
                
             else if (json.getString(KEY_ERROR).equals("1")) 
                // Error in login
                String error_msg = json.getString(KEY_ERROR_MSG);
                Log.e(tag, error_msg);
                setArrivedStatus(false);
             else 
                Log.e(tag, "Something is wrong");
                setArrivedStatus(false);
            
         else 
            Log.e(tag, "Something is wrong");
            setArrivedStatus(false);
        
     catch (JSONException e) 
        e.printStackTrace();
    


public void setArrivedStatus(boolean status) 
    arrivedStatus = status;


public boolean getArrivedStatus() 
    return arrivedStatus;


private class MyLocationListener implements LocationListener 

    @Override
    public void onLocationChanged(Location location) 
        // TODO Auto-generated method stub
        currentLat = location.getLatitude() + "";
        currentLng = location.getLongitude() + "";
        Log.v(tag, LOCATION_CHANGED + " lat=" + currentLat + ", lon="
                + currentLng);
        try 
            JSONObject json = new LogInfo().execute(
                    new String[]  tripID, currentLat, currentLng ).get();
            checkResult(json);
            if (getArrivedStatus() == true) 
                Log.v(tag, "User has arrived safely");
                onDestroy();
            
         catch (InterruptedException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         catch (ExecutionException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        

    

    @Override
    public void onProviderDisabled(String provider) 
        // TODO Auto-generated method stub

    

    @Override
    public void onProviderEnabled(String provider) 
        // TODO Auto-generated method stub

    

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) 
        // TODO Auto-generated method stub

    


我也已经在我的清单中添加了权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

谢谢

【问题讨论】:

【参考方案1】:

当你调用这个函数时,你看到设备通知栏上的 GPS 图标了吗?如果是这样,这意味着它试图获取一个位置,而你只是在一个没有 GPS 接收的地方。

无论如何,你都可以使用谷歌的方式来获取位置,这里:https://developers.google.com/events/io/sessions/324498944

另外,什么是“Tracker”类?是服务吗?如果是这样,你不应该让它引用一个活动,因为它会导致内存泄漏。而是使用正确的绑定。

您还应该避免调用 "onDestroy" ,因为调用它并不会真正关闭您的服务。而是调用“stopSelf”,并确保没有绑定任何活动。

如果你愿意,我很久以前就问过这类问题(通过服务获取位置)here。

【讨论】:

非常感谢。您的回答和建议对我很有帮助。 但是,绑定服务是否意味着在执行绑定服务方法的过程中服务必须停止一段时间? @user2503808 我不明白这个问题。该服务只有在它自己真正停止后才会被视为停止,并且只有在它没有任何实时绑定后才会发生这种情况。检查此链接:developer.android.com/guide/components/services.html#Lifecycle(如果您愿意,请滚动到图表)或此链接:developer.android.com/reference/android/app/Service.html

以上是关于使用带有 GPS 提供程序的 requestLocationUpdates 永远不会调用 onLocationChanged的主要内容,如果未能解决你的问题,请参考以下文章

调用 requestLocation() 时的“线程 1:信号 Sigabrt”

requestLocation() 不请求许可,即使“下次询问”被勾选

网络应用 GPS 轮询

模拟 GPS 位置和适用于 Android 的 Chrome

禁用后虚假 GPS 位置仍然存在

使用 requestLocation 只请求一次用户的位置