Не удается периодически выполнять работу в фоновом режиме с помощью alarmmanager - PullRequest
0 голосов
/ 02 января 2019

Я хочу позвонить в фоновую службу по часам.

Первая проблема в том, что диспетчер аварийных сигналов не работает гладко. Таймер ужасен, иногда рано, иногда позже.

вторая проблема, RemoteServiceException: Context.startForegroundService () не вызывал Service.startForeground (), я не могу понять, почему я получаю это исключение

MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        Intent intent1 = new Intent(MainActivity.this, AlarmReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60 * 60 * 1000L, pendingIntent);
    }
}

AlarmReceiver

public class AlarmReceiver extends BroadcastReceiver {

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onReceive(Context context, Intent intent) {

        Intent downloadService = new Intent(context, CallService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(downloadService);
        } else {
            context.startService(downloadService);
        }

    }

}

CallService

public class CallService extends IntentService {

    public CallService() {
        super("");
    }

    public CallService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent workIntent) {
        Log.d("Now : ", Calendar.getInstance().getTime().toString());



    }
}

Manifest

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <receiver android:name=".AlarmReceiver"/>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".CallService"
            android:exported="false"/>

Извините за мой ужасный английский. Спасибо за любую помощь или предложение. Я не знаю, как я могу сделать по-другому. Я просто периодически звоню в службу

Ответы [ 2 ]

0 голосов
/ 04 января 2019

AlarmManager будет работать нормально на API 27 (Oreo 8.1) и менее. Просто настройте что-то вроде этого:

public void setupAlarm(Context context, long triggerAtMillis) {
    PendingIntent pendingIntent = getPendingIntent(context);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
    } else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
    } else {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
    }
}

Не забывайте, что вам нужно заново устанавливать будильник каждый раз, когда срабатывает ваш AlarmReceiver . Но этот код не будет работать на API 28 и более (пирог 9.0). Это происходит из-за функции Управление питанием , представленной в Android Pie. Строгие ограничения введены для приложений, работающих в фоновом режиме. Эти ограничения объяснены здесь . Попробуйте использовать JobScheculer для вызова IntentService на переднем плане.

Как насчет вашего второго вопроса. Вам необходимо сделать уведомление в вашем CallService . Просто добавьте это наСоздание к вашему IntentService :

@Override
public void onCreate() {
    super.onCreate();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel chan = new NotificationChannel("test", "your_channel_name", NotificationManager.IMPORTANCE_NONE);
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (manager != null) {
            manager.createNotificationChannel(chan);
        }

        Notification.Builder notificationBuilder = new Notification.Builder(context, "test");
        notificationBuilder.setOngoing(true);
        notificationBuilder.setContentTitle("Updatig")
                .setContentText("Wait for finish updating")
        startForeground(NOTIFICATION_ID, notificationBuilder.build());
    }
}

RemoteServiceException будет выдано, если вы не будете вызывать startForeground в службе (у вас есть 5 секунд, чтобы сделать этот вызов) после startForegroundService.

0 голосов
/ 04 января 2019

У меня была такая же проблема с диспетчером тревоги.Вы можете переключиться на Интервал RxJava.

protected fun startCountdown(period: Long, timeUnit: TimeUnit): Observable<Long> {
        return Observable.interval(period, timeUnit)
            .subscribeOn(Schedulers.io())
            .observeOn(Schedulers.io())
    }

использование;

startCountdown(MEDIA_LOCATION_CHANGE_PERIOD, TimeUnit.MILLISECONDS)
        .subscribe {
            fireSomethingUp()
        }
...