Android 定位后台服务在其他手机上不起作用

Posted

技术标签:

【中文标题】Android 定位后台服务在其他手机上不起作用【英文标题】:Android background service for location is not working in other phones 【发布时间】:2017-04-13 12:35:03 【问题描述】:

位置检测的后台服务会在一段时间后关闭。我在onTaskRemoved 中有代码来设置挂起撤消的警报。我仍然无法解决问题。下面是我的后台服务类的代码:

public class MyService extends Service 
    public static final String BROADCAST_ACTION = "Hello World";
    private static final int TWO_MINUTES = 1000 * 60 *5;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;
    double latitude; // latitude
    double longitude; // longitude
    Intent intent;
    private static final String POST_URL = "http://api.url.com/oauth/api/v1/location/update";
    int counter = 0;
    public static boolean isRunning  = false;

    @Override
    public void onCreate() 
        super.onCreate();
        intent = new Intent(BROADCAST_ACTION);
    

    @Override
    public void onStart(Intent intent, int startId) 


        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        listener = new MyLocationListener();
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
    

    @Override
    public IBinder onBind(Intent intent) 
        super.onCreate();

        return (IBinder) intent;
    




    protected boolean isBetterLocation(Location location, Location currentBestLocation) 
        if (currentBestLocation == null) 
            return true;
        

        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        if (isSignificantlyNewer) 
            return true;
         else if (isSignificantlyOlder) 
            return false;
        

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) 
            return true;
         else if (isNewer && !isLessAccurate) 
            return true;
         else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) 
            return true;
        
        return false;
    


    /**
     * Checks whether two providers are the same
     */
    private boolean isSameProvider(String provider1, String provider2) 
        if (provider1 == null) 
            return provider2 == null;
        
        return provider1.equals(provider2);
    


    @Override
    public void onDestroy() 

        super.onDestroy();

Toast.makeText(getApplicationContext(),"onDestroy",Toast.LENGTH_LONG).show();
Log.d("onDestroy","onDestroy");

        Intent myIntent = new Intent(getApplicationContext(), MyService.class);

        PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);

        AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);

        Calendar calendar = Calendar.getInstance();

        calendar.setTimeInMillis(System.currentTimeMillis());

        calendar.add(Calendar.SECOND, 1);

        alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent);



    


    @Override
    public void onTaskRemoved(Intent rootIntent) 
        super.onTaskRemoved(rootIntent);
        Toast.makeText(getApplicationContext(),"onTaskRemoved",Toast.LENGTH_LONG).show();
        Log.d("onTaskRemoved", "onTaskRemoved");
        Intent myIntent = new Intent(getApplicationContext(), MyService.class);

        PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);

        AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);

        Calendar calendar = Calendar.getInstance();

        calendar.setTimeInMillis(System.currentTimeMillis());

        calendar.add(Calendar.SECOND, 1);

        alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent) ;




    


    public class MyLocationListener implements LocationListener 

        public void onLocationChanged(final Location loc) 
            if (isBetterLocation(loc, previousBestLocation)) 
                latitude = loc.getLatitude();
                longitude = loc.getLongitude();
                intent.putExtra("Latitude", loc.getLatitude());
                intent.putExtra("Longitude", loc.getLongitude());
                intent.putExtra("Provider", loc.getProvider());
                sendBroadcast(intent);


                SharedPreferences check = getApplicationContext().getSharedPreferences("Access_token", Context.MODE_PRIVATE);
                final String access_token = check.getString("access_token", "N/A");

                StringRequest stringRequest = new StringRequest(Request.Method.POST, POST_URL,
                        new Response.Listener<String>() 
                            @Override
                            public void onResponse(String response) 

Toast.makeText(getApplicationContext(),""+response,Toast.LENGTH_LONG).show();
                            
                        ,
                        new Response.ErrorListener() 
                            @Override
                            public void onErrorResponse(VolleyError error) 

                                Toast.makeText(getApplicationContext(),""+error,Toast.LENGTH_LONG).show();

                            
                        ) 
                    @Override
                    protected Map<String, String> getParams() 
                        Map<String, String> params = new HashMap<String, String>();
                        params.put("access_token", access_token);
                        params.put("latitude", String.valueOf(latitude));
                        params.put("longitude", String.valueOf(longitude));
                        return params;
                    

                ;
                stringRequest.setRetryPolicy(new DefaultRetryPolicy(1 * 500000,
                        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
                RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
                requestQueue.add(stringRequest);
            


        

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

        

        @Override
        public void onProviderEnabled(String provider) 

        

        @Override
        public void onProviderDisabled(String provider) 

        
    


【问题讨论】:

我发现您的代码存在一些问题。您不能从onBind() 呼叫super.onCreate()。不要使用onStart(),因为它在 100 年前已被弃用。实现onStartCommand() 并返回START_STICKY 你知道哪些设备有这个问题吗? 【参考方案1】:

在 onbind 方法中返回 null 因为返回某些内容意味着您希望将其绑定到组件,这可能导致关闭该组件时停止服务。也使用 onStartCommand 代替 onStart。如果您需要 OnStartCommand 方法中的意图,则返回 START_REDELIVER_INTENT 标志,否则使用 START_STICKY 重新启动服务。

public class MyService extends Service 
  public static final String BROADCAST_ACTION = "Hello World";
  private static final int TWO_MINUTES = 1000 * 60 *5;
  public LocationManager locationManager;
  public MyLocationListener listener;
  public Location previousBestLocation = null;
  double latitude; // latitude
  double longitude; // longitude
  Intent intent;
  private static final String POST_URL = "http://api.url.com/oauth/api/v1/location/update";
  int counter = 0;
  public static boolean isRunning  = false;

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) 
    this.intent = new Intent(BROADCAST_ACTION);
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    listener = new MyLocationListener();
    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
      // TODO: Consider calling
      //    ActivityCompat#requestPermissions
      // here to request the missing permissions, and then overriding
      //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
      //                                          int[] grantResults)
      // to handle the case where the user grants the permission. See the documentation
      // for ActivityCompat#requestPermissions for more details.
    
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
    return START_STICKY;
  

  protected boolean isBetterLocation(Location location, Location currentBestLocation) 
    if (currentBestLocation == null) 
      return true;
    

    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    if (isSignificantlyNewer) 
      return true;
     else if (isSignificantlyOlder) 
      return false;
    

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
        currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) 
      return true;
     else if (isNewer && !isLessAccurate) 
      return true;
     else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) 
      return true;
    
    return false;
  


  /**
   * Checks whether two providers are the same
   */
  private boolean isSameProvider(String provider1, String provider2) 
    if (provider1 == null) 
      return provider2 == null;
    
    return provider1.equals(provider2);
  


  @Override
  public void onDestroy() 

    super.onDestroy();

    Toast.makeText(getApplicationContext(),"onDestroy", Toast.LENGTH_LONG).show();
    Log.d("onDestroy","onDestroy");

    Intent myIntent = new Intent(getApplicationContext(), MyService.class);

    PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);

    AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();

    calendar.setTimeInMillis(System.currentTimeMillis());

    calendar.add(Calendar.SECOND, 1);

    alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent);



  

  @Nullable
  @Override
  public IBinder onBind(Intent intent) 
    return null;
  


  @Override
  public void onTaskRemoved(Intent rootIntent) 
    super.onTaskRemoved(rootIntent);
    Toast.makeText(getApplicationContext(),"onTaskRemoved",Toast.LENGTH_LONG).show();
    Log.d("onTaskRemoved", "onTaskRemoved");
    Intent myIntent = new Intent(getApplicationContext(), MyService.class);

    PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);

    AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();

    calendar.setTimeInMillis(System.currentTimeMillis());

    calendar.add(Calendar.SECOND, 1);

    alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent) ;

  


  public class MyLocationListener implements LocationListener 

    public void onLocationChanged(final Location loc) 
      if (isBetterLocation(loc, previousBestLocation)) 
        latitude = loc.getLatitude();
        longitude = loc.getLongitude();
        intent.putExtra("Latitude", loc.getLatitude());
        intent.putExtra("Longitude", loc.getLongitude());
        intent.putExtra("Provider", loc.getProvider());
        sendBroadcast(intent);


        SharedPreferences check = getApplicationContext().getSharedPreferences("Access_token", Context.MODE_PRIVATE);
        final String access_token = check.getString("access_token", "N/A");

        StringRequest stringRequest = new StringRequest(Request.Method.POST, POST_URL,
            new Response.Listener<String>() 
              @Override
              public void onResponse(String response) 

                Toast.makeText(getApplicationContext(),""+response,Toast.LENGTH_LONG).show();
              
            ,
            new Response.ErrorListener() 
              @Override
              public void onErrorResponse(VolleyError error) 

                Toast.makeText(getApplicationContext(),""+error,Toast.LENGTH_LONG).show();

              
            ) 
          @Override
          protected Map<String, String> getParams() 
            Map<String, String> params = new HashMap<String, String>();
            params.put("access_token", access_token);
            params.put("latitude", String.valueOf(latitude));
            params.put("longitude", String.valueOf(longitude));
            return params;
          

        ;
        stringRequest.setRetryPolicy(new DefaultRetryPolicy(1 * 500000,
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
        requestQueue.add(stringRequest);
      


    

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

    

    @Override
    public void onProviderEnabled(String provider) 

    

    @Override
    public void onProviderDisabled(String provider) 

    
  


【讨论】:

以上是关于Android 定位后台服务在其他手机上不起作用的主要内容,如果未能解决你的问题,请参考以下文章

加速度计服务在 Android TV Box 上不起作用

Cordova 地理定位插件在 android 设备上不起作用

地理定位 API 在某些 Android 设备上不起作用

onPress 事件在 Android 上的 TouchableOpacity 上不起作用

FCM 推送通知在 Android 4.4 上不起作用

Bootstrap 折叠按钮在智能手机上不起作用