当应用程序在后台运行时无法找到位置更新

Posted

技术标签:

【中文标题】当应用程序在后台运行时无法找到位置更新【英文标题】:Unable to find location updates when an application is running in the background 【发布时间】:2012-04-20 16:06:58 【问题描述】:

我正在尝试创建一个应用程序,我想在其中连续运行 android 应用程序。

我创建了服务类以在后台运行应用程序以进行位置更新。 该服务不会连续运行,但会在一段时间后停止。下面是启动服务的 Boot 接收器类。

我已经把 Service 和 Boot Receiver 两个类都放到了。

我做错了什么还是错过了什么?

/********************Boot receiver********************/

import java.util.Calendar;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class BootReceiver extends BroadcastReceiver 
    @Override
    public void onReceive(Context context, Intent intent) 

        // TODO Auto-generated method stub
        Log.i("IntentReceiver", "Got intent " + intent.getAction() + " / data: " + intent.getDataString());

        try 
            Intent i = new Intent(context,MyService.class);

            PendingIntent  pendingIntent = PendingIntent.getService(context, 0, i, 0);

            AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            calendar.add(Calendar.SECOND, 20);
            alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000, pendingIntent);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startService(i);
        
        catch (Exception e) 
            e.printStackTrace();
        
    


/**********************Myservice*********************/

import java.util.Date;

import com.safecell.dataaccess.InteruptionRepository;
import com.safecell.dataaccess.TempTripJourneyWayPointsRepository;
import com.safecell.model.SCProfile;
import com.safecell.model.SCWayPoint;
import com.safecell.receiver.LockReceiver;
import com.safecell.utilities.DateUtils;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import android.location.Location;

import android.location.LocationListener;

import android.location.LocationManager;
import android.media.AudioManager;

public class MyService extends Service 
    private static LocationManager mlocManager;
    private static final String TAG = "MyService";
    public static double x=0.0 ,y=0.0,last_x=0.0,last_y=0.0;
    SharedPreferences sharedPreferences;
    public static int j=0;
    public static TrackingScreenActivity trackingScreenActivity = null;
    public static TrackingService trackingService;
    static TempTripJourneyWayPointsRepository tempTripJourneyWayPointsRepository;
    double speed = 0.0;
    private float lastDistanceInMiles = 0;

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

    @Override
    public void onCreate() 
        Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onCreate");
    

    @Override
    public void onDestroy() 
        Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onDestroy");
    

    @Override
    public void onStart(Intent intent, int startid) 
        //Toast.makeText(this, "start My Service Started", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onStart");

        if(SplashScreenActivity.act_flag)
        
        
        else
        
            Intent myStarterIntent = new Intent(getApplicationContext(), SplashScreenActivity.class);
            myStarterIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            getApplicationContext().startActivity(myStarterIntent);
        
        sharedPreferences = getSharedPreferences("TRIP", MODE_WORLD_READABLE);

        mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

        LocationListener mlocListener = new MyLocationListener();

        mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    

    /***********************To insert a record in an nsqlite table**********************/

    private void insertWaypoint(Location location) 
        // InteruptionRepository
        tempTripJourneyWayPointsRepository= new TempTripJourneyWayPointsRepository(
            getApplicationContext());

        double distanceInMiles = tempTripJourneyWayPointsRepository.getDistanceDifference(location);

        //Toast.makeText( getApplicationContext(),
        //                "didf=f"+distanceInMiles,
        //                Toast.LENGTH_SHORT).show();

        long currentTime = new Date().getTime();

        double timeDifference = tempTripJourneyWayPointsRepository.getTimeDiffernce(currentTime);
        double avarageSpeed = tempTripJourneyWayPointsRepository.getAvarageEstimatedSpeedForAutoTripStart();
        SharedPreferences sharedPreferences = getSharedPreferences("TRIP", MODE_WORLD_READABLE);

        boolean isTripStarted = sharedPreferences.getBoolean("isTripStarted", false);

        if (timeDifference != 0 && distanceInMiles!=0) 
            speed = distanceInMiles / timeDifference;
        

        Toast.makeText( getApplicationContext(), "didf=f"+speed, Toast.LENGTH_SHORT).show();

        boolean background = true;
        if (isTripStarted)
        
            AudioManager aManager = (AudioManager) getSystemService(AUDIO_SERVICE);
            aManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);

            SCWayPoint wayPoint =
                new SCWayPoint(0, 0,
                               DateUtils.getTimeStamp(currentTime),
                               location.getLatitude(), location.getLongitude(), speed,
                               background);

            tempTripJourneyWayPointsRepository.intsertWaypoint(wayPoint);
        // if trip started

        // trackingScreenActivity.dismProgressDialog();
    

    /* Class My Location Listener */
    public class MyLocationListener implements LocationListener
    
        @Override
        public void onLocationChanged(Location loc)
        
            Log.d(TAG, "onlocationchnage");
            x=loc.getLatitude();
            y=loc.getLongitude();
            int d3= calcDistance(last_x,last_y,x,y);
            double speed;
            if (d3>20) 
                speed = d3/20;
            
            else
            
                speed=0.0;
            
            j++;

            String Text ="My current location is: " +

            "Latitud1 = " +x +

            "Longitud1 = " +y+
            "Latitud2 = " + last_x +

            "Longitud2 = " + last_y+
            "j=" +j+
            "distance="+d3+" Speed  :  "+speed;

            Toast.makeText( getApplicationContext(), Text, Toast.LENGTH_SHORT).show();

            if(speed>10)
            
                TempTripJourneyWayPointsRepository tempTripJourneyWayPointsRepository =
                    new TempTripJourneyWayPointsRepository(getApplicationContext());
                tempTripJourneyWayPointsRepository.deleteTrip();
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean("isTripPaused", false);
                editor.putBoolean("isTripStarted", true);
                editor.commit();
                insertWaypoint(loc);
                if(speed < 10.0)
                
                    //Toast.makeText(getApplicationContext(), "hoooo service"+speed, Toast.LENGTH_LONG).show();
                    if(isMyServiceRunning())
                    
                        //trackingService.saveTripAsyncTask(getApplicationContext());
                        //      Toast.makeText(getApplicationContext(), "hiiiiiiiiiiiiiiii Service", Toast.LENGTH_LONG).show();
                        //trackingScreenActivity.btnStop.performClick();
                        //trackingScreenActivity.stoptripinservice();

                        //      AddTripActivity.addTripActivity=

                        //SharedPreferences.Editor editor = sharedPreferences.edit();
                        //editor.putBoolean("isTripSaved", true);
                        //editor.commit();
                    
                

                last_x=loc.getLatitude();
                last_y=loc.getLongitude();
            


        public  void editGenereateTripUniqueID(String uniqueId)
            SharedPreferences.Editor editorUniqueID =
                TrackingService.context.getSharedPreferences("TripJouneryUID", MODE_WORLD_WRITEABLE).edit();
            editorUniqueID.putString("UniqueIdForTrip", uniqueId);
            editorUniqueID.commit();
            //Log.v("Safecell : --UniqueIdForTrip", "ID = "+uniqueId);
        

        private Double distance(double lat1, double lon1, double lat2, double lon2)
        
            /* double theta = lon1 - lon2;
            double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) +
                          Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
            dist = Math.acos(dist);
            dist = rad2deg(dist);
            dist = dist * 60;
            dist = dist * 1852;*/
            double dlon = lon2 - lon1;
            double  dlat = lat2 - lat1;
            double a = Math.pow((Math.sin(dlat/2)),2) +
                       Math.cos(lat1) * Math.cos(lat2) *  Math.pow((Math.sin(dlon/2)),2);

            double c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a) );
            double d = 6373  * c;
            return (d);
        

        private boolean isMyServiceRunning() 
            ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
            for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
                if ("com.safecell.TrackingService".equals(service.service.getClassName())) 
                    return true;
                
            
            return false;
        

        public int calcDistance(double latA, double longA, double latB, double longB) 

            double theDistance = (Math.sin(Math.toRadians(latA)) *
                    Math.sin(Math.toRadians(latB)) +
                    Math.cos(Math.toRadians(latA)) *
                    Math.cos(Math.toRadians(latB)) *
                    Math.cos(Math.toRadians(longA - longB)));

            return new Double((Math.toDegrees(Math.acos(theDistance))) * 69.09*1.6093).intValue();
        

        private double deg2rad(double deg) 
            return (deg * Math.PI / 180.0);
        

        private double rad2deg(double rad) 
            return (rad * 180.0 / Math.PI);
        

        @Override
        public void onProviderDisabled(String provider)
        
            // Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
        

        @Override
        public void onProviderEnabled(String provider)

        
            // Toast.makeText( getApplicationContext(), "Gps Enabled",  Toast.LENGTH_SHORT).show();
        

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

        

    /* End of Class MyLocationListener */


【问题讨论】:

【参考方案1】:

我没有信心,但我有一个想法。

    您应该设置 TIMEZONE_CHANGED 的广播。更改日期和时间时,PF 可能会重置警报管理器。并且某些 Android 设备默认日期和时间设置是自动的!

    您应该在 Service#onCreate() 上从低内存杀手编写重启操作代码。重新启动服务时,也许 PF 会调用 Service#onCreate()。 PF 注册终止了你的服务并重新启动了你的服务。

    您可能会考虑将您的服务作为前台服务来执行。因此,低内存杀手杀死的优先级/潜力很低。 您可以在Service#onStart() 重新检查您关于NullPointerException 的代码。 PF 可能会将 null 设置为 onStart 意图参数。 您可以考虑设置PowerManager#WakeLock。 PF 休眠时服务无法运行。

PS:您可以查看以下有关 PowerManager 和前台服务的 Android 错误。

WakeLock Timeout causes WakeLock under-locked on Timeout Notification won't be created as ongoing when starting foreground service

【讨论】:

如果你想创建低内存杀手的情况并重置AlarmManager。你尝试关注 [重置 AlarmManager 测试]。 1:断网。 2:关闭数据和时间的自动。 3:更改日期。但具体的依赖设备。 [Low Memory Kill Test] 我推荐使用我的应用程序。这个应用程序很容易创建低内存状态。 github.com/kyorohiro/KyoroHelloAndroidKyoroStress.apk 或play.google.com/store/apps/…

以上是关于当应用程序在后台运行时无法找到位置更新的主要内容,如果未能解决你的问题,请参考以下文章

当应用程序处于后台或终止状态时,如何找到用户位置?

后台位置更新

基于位置的应用程序无法在后台 iPhone 中运行

应用程序未运行时的iOS后台模式?

在后台永远运行Swift 2.0应用程序以更新服务器的位置

当应用程序移到后台时,在前台服务中获取位置更新不起作用