2

画面がオフで電話がポケットに入っている場合でも、ロケーションマネージャーと gps プロバイダーを使用して毎秒ロケーションの更新を取得するスポーツ追跡アプリを開発しています。

ユーザーがアクティビティで開始ボタンを押すと、フォアグラウンドでサービスが開始され、通知が表示され、ロケーション リスナーが登録されます。

サービスが位置情報更新の受信を開始し、それらをトラック ファイルに書き込みます。

突然、「Power manager idle mode: true」というログ メッセージが表示され、電話が Doze モードになり、電話が復帰するまでサービスが位置情報の更新を停止します。

Doze モードに関するドキュメントを読んだところ、位置情報サービスに影響を与えるべきではないことがわかりましたが、私の場合はそうです。

私は何か間違ったことをしているのかもしれません。これが私のサービスのコードです。どんな助けも本当に感謝しています。

public class LocService
    extends Service
implements LocationListener, GpsStatus.Listener
{

private String mName;
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private LocationManager locationManager;

public LocService(String name)
{
    super();
    mName = name;
}

private final class ServiceHandler extends Handler
{
    public ServiceHandler(Looper looper)
    {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg)
    {
        if (msg != null && msg.obj != null)
        {
            onHandleIntent((Intent)msg.obj);
        }
        else
        {
            logMessage("msg for intent is not good");
        }
    }
}

@Override
public void onCreate()
{
    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    {
        logMessage("Enabling Doze mode listener");
        IntentFilter filter = new IntentFilter();
        filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
        registerReceiver(new BroadcastReceiver()
        {
            @Override
            public void onReceive(Context context, Intent intent)
            {
                onDeviceIdleChanged();
            }
        }, filter);
    }

    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
}

@TargetApi(Build.VERSION_CODES.M)
private void onDeviceIdleChanged()
{
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    if(powerManager != null)
    {
        logMessage("Power manager idle mode: " + powerManager.isDeviceIdleMode());
    } else
    {
        logMessage("Power manager idle changed to ?");
    }
}

protected void onHandleIntent(Intent intent)
{
    //call start/stop location logging on proper intent
    if(intent.getIntExtra("cmd", -1) == 1)
    {
        startLogging();
    } else
    {
        stopLogging();
    }
}

private void startLogging()
{
    logMessage("LocationService.startLogging");
    try
    {
        locationManager.addGpsStatusListener(this);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 0, this);
        logMessage("requesting gps updates");

        startForeground(ONGOING_NOTIFICATION, getNotification(-1, -1, true, false));
        logMessage("Sending foreground service notification");

    }
    catch (SecurityException ex)
    {
        logMessage(" SecurityException while requesting location info: " + ex);
    }
}

private void stopLogging()
{
    try
    {
        locationManager.removeUpdates(this);

        stopForeground(true);
        notificationManager.cancel(ONGOING_NOTIFICATION);
    }
    catch (SecurityException ex)
    {
        logMessage(" SecurityException on stopLogging with location manager: " + ex);
    }

}


@Override
public void onLocationChanged(Location location)
{
    //save location lat, lon directly to track file
    //flush file
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
    //do nothing
}

@Override
public void onProviderEnabled(String provider)
{
    logMessage("Location provider enabled " + provider);
}

@Override
public void onProviderDisabled(String provider)
{
    logMessage("Location provider disabled " + provider);
}

@Override
public void onGpsStatusChanged(int event)
{
    try
    {
        logMessage(" *** onGpsStatusChanged with " + event);
        GpsStatus status = locationManager.getGpsStatus(null);
        int inFix = 0;
        int total = 0;
        for (GpsSatellite satellite : status.getSatellites())
        {
            if (satellite.usedInFix()) inFix++;
            total++;
        }
        logMessage(" Sats: " + total + " in fix " + inFix);
    }
    catch (SecurityException sex)
    {
    }
    catch (Exception ex)
    {
    }
}

@Override
public void onStart(Intent intent, int startId)
{
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    onStart(intent, startId);
    return START_STICKY;
}

@Override
public void onDestroy()
{
    mServiceLooper.quit();
    try
    {
        locationManager.removeUpdates(this);
    }
    catch (SecurityException ex)
    {
        logMessage(" SecurityException on Destroy service with location manager: " + ex);
    }
}

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

private void logMessage(String msg)
{
    Log.i("LocServ", msg);
}
}
4

1 に答える 1