4

Google은 모바일 추적 앱을 개발 중입니다. 위치 업데이트의 경우 융합 위치 API가 높은 정확도와 우선 순위로 사용됩니다.화면이 꺼져있을 때 Android 배경 위치 업데이트가 수행되지 않습니다.

화면이 꺼져 있어도 위치 업데이트가 필요합니다. 그래서 배경은 Service입니다. 배경 Service도 부분 WakeLock을 획득하므로 장치가 절전 상태가되지 않습니다. 백그라운드에서 Service은 보류중인 업데이트가 Service 인 위치 업데이트를 요청합니다.

문제는 화면이 켜져있을 때만 위치 업데이트를 수신한다는 것입니다. 화면이 꺼지 자마자 위치 업데이트가 중단됩니다. 또한 Service에 의해 운영되는 Thread이 있습니다. 어느 지점에서든 죽이지는 않습니다.

화면이 꺼져있을 때 위치 요청을 다시 생성하면 BroadcastReceiver이 작동하지 않습니다.

private static final String TAG = "RouteExecution"; 

private static RouteExecution routeExecution = null; 

private static GoogleApiClient mGoogleApiClient; 
private static PendingIntent pendingIntent = null; 
private PowerManager.WakeLock waitLock; 
/** 
* Creates an IntentService. Invoked by your subclass's constructor. 
*/ 
public RouteExecution() { 
    super(TAG); 

    RouteExecution.routeExecution = this; 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 

    mGoogleApiClient = new GoogleApiClient.Builder(this) 
      .addApi(LocationServices.API) 
      .addConnectionCallbacks(this) 
      .addOnConnectionFailedListener(this) 
      .build(); 

    mGoogleApiClient.connect(); 

    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); 
    filter.addAction(Intent.ACTION_SCREEN_OFF); 
    BroadcastReceiver mReceiver = new PowerButtonReceiver(); 
    registerReceiver(mReceiver, filter); 

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 
    waitLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 
    waitLock.acquire(); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 

    if (LocationResult.hasResult(intent)) { 

     LocationResult locationResult = LocationResult.extractResult(intent); 
     Location location = locationResult.getLastLocation(); 

     GPSLocation gpsLocation = new GPSLocation(location); 

     Log.d(TAG, "Location Accuracy: " + location.getAccuracy() + " " 
       + " has: " + location.hasAccuracy() + " Provider: " + location.getProvider() 
       + " long: " + location.getLongitude() + " lat: " + location.getLatitude()); 
    } 
} 



public boolean checkLocationPermission() { 

    if (ActivityCompat.checkSelfPermission(routeExecution, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED 
      && ActivityCompat.checkSelfPermission(routeExecution, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     // 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 false; 
    } 

    return true; 
} 

public void createLocationListener() { 

    if (!this.checkLocationPermission()) { 
     return; 
    } 

    LocationRequest mLocationRequest = LocationRequest.create(); 
    mLocationRequest.setInterval(5000); 
    mLocationRequest.setFastestInterval(5000); 
    mLocationRequest.setSmallestDisplacement(0); 
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 

    PendingResult<Status> statusPendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, 
      mLocationRequest, pendingIntent); 
} 

@Override 
public void onConnected(@Nullable Bundle bundle) { 

    Log.d(TAG, mGoogleApiClient.isConnected() + " On Connected"); 
    synchronized (this) { 

      createLocationListener(); 
    } 
} 


public static GoogleApiClient getmGoogleApiClient() { 
    return mGoogleApiClient; 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 


    waitLock.release(); 
    mGoogleApiClient.disconnect(); 
} 

public static RouteExecution getRouteExecution() { 
    return routeExecution; 
} 

public static void setPendingIntent(PendingIntent pendingIntent) { 
    RouteExecution.pendingIntent = pendingIntent; 
} 

ServiceAlarmManager를 사용하기 시작한다 :

다음은 배경 Service 클래스 (RouteExecution)입니다.

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
Intent updateServiceIntent = new Intent(context, RouteExecution.class); 
PendingIntent pendingUpdateIntent = PendingIntent.getService(context, 0, updateServiceIntent, 0); 
RouteExecution.setPendingIntent(pendingUpdateIntent); 
alarmManager.set(AlarmManager.RTC_WAKEUP, 50000, pendingUpdateIntent); 

BroadcastReceiver : 화면이 꺼져있을 경우에도 위치를 얻고 유지하는 방법

public class PowerButtonReceiver extends BroadcastReceiver { 
    private static final String TAG = "PowerButton"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 

     Log.d(TAG, "Power Button"); 
     if (RouteExecution.getRouteExecution() != null) { 
      RouteExecution.getRouteExecution().createLocationListener(); 
     } 
    } 
} 

이 업데이트 여기에 추출합니다.

도움 주셔서 감사합니다.

+1

어떻게 '서비스'를 시작 하시겠습니까? 'Service'와'BroadcastReceiver' 코드를 모두 보여줍니다. – earthw0rmjim

+0

http : // stackoverflow뿐만 아니라이 질문을 확인하십시오.com/questions/17613888/locationclient-does-give-callback-when-screen-light-go-off-but-my-wakefulth – abbath

답변

0

우선, 을 Service에 묻는 것은 전혀 신뢰할 수 없습니다. 해당 코드가 실행되기 전에 장치가 다시 잠자기 상태가 될 수 있습니다.

나는 WakeLock 기술적 onReceive() 동안 보장되어 있기 때문에, 대신 PendingIntent.getService()PendingIntent.getBroadcast()을 호출하고 거기에서 Service을 시작합니다.

중 하나는이 WakeLockonReceive()에서, 당신의 Service을 시작 aquire과 Service,에서 WakeLock을 떼면 그 논리의 대부분을 구현하지 않고 적절한

또는

사용 WakefulBroadcastReceiver, 기본적으로 동일한 않는, 당신 자신.

또 다른 가능한 문제는 마시맬로 장치에서 AlarmManager.set()을 사용하는 것입니다.

Doze이 활성화 된 경우이 방법으로 설정된 경보는 이러한 장치에서 실행되지 않습니다.

API 레벨 23+에서 set() 대신 setAndAllowWhileIdle()을 사용하십시오.