Сервис блокирует свою деятельность, когда вызывающая форма уходит в фоновом режиме. - PullRequest
0 голосов
/ 10 июня 2018

Я разработал приложение для путешествий (api 25), которое использует местоположение телефона для расчета скорости (и других параметров).Позиция занята службой, которая заботится о печати (и сохранении в БД) различных параметров.У меня проблема с управлением сервисами на android oreo, сервис блокирует свою деятельность, когда форма вызова уходит в фоновом режиме.Приложение прекрасно работает на Android-N, но, к сожалению, на Android-O у меня есть эта проблема.

часть формы вызова является следующим:

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        LocationUpdatesService.LocalBinder binder = (LocationUpdatesService.LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mService = null;
        mBound = false;
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    Intent serviceIntent = new Intent(this, LocationUpdatesService.class);

    if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
        startForegroundService(serviceIntent);
    }
    bindService(serviceIntent, mServiceConnection,
            Context.BIND_AUTO_CREATE);

    }

    start_stop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );

            if (start_stop.getText().toString() == "start") {
                //chiedo aggiornamenti
                requestLocationUpdatesON();

                start_stop.setText("stop");
            }
            else {
                requestLocationUpdatesOFF();
            }
        }
    });

    mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFrag.getMapAsync(this);

}

public void requestLocationUpdatesOFF(){
    mService.removeLocationUpdates();
    //mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
public void requestLocationUpdatesON(){

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {

            //Location Permission already granted
            //mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
            mService.requestLocationUpdates();
            mGoogleMap.setMyLocationEnabled(true);
        } else {
            //Request Location Permission
            checkLocationPermission();
        }
    }
    else {
        //mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
        mService.requestLocationUpdates();
        mGoogleMap.setMyLocationEnabled(true);
    }

}


@Override
protected void onDestroy() {
    NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.cancel(3129999);
    unbindService(mServiceConnection);
    super.onDestroy();
}

служба:

    @Override
public void onCreate() {

    //wake-lock per impedire la chiusura dell'app in sleepmode
    mPM = (PowerManager)getSystemService(Context.POWER_SERVICE);
    mWL = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.ON_AFTER_RELEASE,
            "MyWakelockTag");
    mWL.acquire(10000);
    Log.i("MyWakeLockTag", "onCreate");


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel1 = new NotificationChannel(
                CHANNEL_1_ID,
                "Channel 1",
                NotificationManager.IMPORTANCE_MIN
        );
        channel1.setDescription("This is Channel 1");
        channel1.setSound(null,null);
        channel1.enableLights(false);
        channel1.setLightColor(Color.BLUE);
        channel1.enableVibration(false);

        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel1);
    }
}

public void requestLocationUpdates() {

    //sendNotification();

    if(!primaVoltaCronometro){
        resumeCronometro();
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        sendNotificationOreo();
    }
    else {
        sendNotification();

    }
    Log.i("Servizio", "Requesting location updates");
    //Utils.setRequestingLocationUpdates(this, true);
    startService(new Intent(getApplicationContext(), LocationUpdatesService.class));
    try {
        mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                mLocationCallback, Looper.myLooper());
    } catch (SecurityException unlikely) {
        //Utils.setRequestingLocationUpdates(this, false);
        Log.e("Servizio", "Lost location permission. Could not request updates. " + unlikely);
    }
}

public void sendNotificationOreo() {

    //mi serve per far aprire il MapsActivity al click della notifica
    Intent notificationIntent = new Intent(this, MapsActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent intent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    notificationManager = NotificationManagerCompat.from(this);

    Notification notification = new NotificationCompat.Builder(this, CHANNEL_1_ID)
            .setSmallIcon(android.R.color.transparent)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setCategory(NotificationCompat.CATEGORY_MESSAGE)
            .setContentIntent(intent)
            .setOngoing(true)
            .setContent(contentView)
            .build();

    if(primaVoltaCronometro) {
        startForeground(1,notification);

        long BasePerIcronometri = SystemClock.elapsedRealtime();

        cronometroInvisibile.setBase(BasePerIcronometri);
        contentView.setChronometer(R.id.chronometerNot, BasePerIcronometri, "\uD83C\uDFC3%s\uD83D\uDCA8", true);
        cronometroInvisibile.start();
        primaVoltaCronometro=false;
    }
    notificationManager.notify(1, notification);
}

@Override
public void onDestroy() {
    mWL.release();
    Log.i("MyWakeLockTag", "onCreate");
    super.onDestroy();
}

Я знаю, что Android Oreo сильно ограничивает сервис, я надеюсь, что смогу помочь кому-то с подобной проблемой

1 Ответ

0 голосов
/ 10 июня 2018

Я помню это, когда читал «Руководство по фоновой обработке» в руководстве разработчика.

Android 8.0 (уровень API 26) дополнительно ограничивал поведение фона, например, получение местоположения в фоновом режиме.и освобождение кэшированных wakelocks.


src : https://developer.android.com/guide/background/
это не решение, но надеюсь, что оно поможет ...

...