Android Job Scheduler Задание не выполняется после закрытия приложения - PullRequest
0 голосов
/ 05 февраля 2020

Моя работа выполняется отлично, если приложение открыто, но если я закрываю приложение, служба заданий никогда не выполняется. Я следовал за учебником здесь; Job Scheduler - Code In Flow и он просто не запускается (или, может быть, он работает, и мы не знаем, что он работает?). Я включил в свои методы уведомления и методы Log.d, чтобы я мог видеть, выполняется ли задание, и пока приложение открыто, регистрируйте сообщения MSG и уведомления через sh, как и ожидалось.

Любая помощь будет оценена. Спасибо

ОБНОВЛЕНИЕ 2
===============
Я обнаружил, так как задание запускается, пока приложение открыто , если я закрою приложение, работа будет отменена без вызова onStopJob. Теоретически, если я не ошибаюсь, планировщик заданий должен продолжать работу независимо от того, запущено приложение или нет. сообщения Log.d выглядят так

D/global_PEA: Job Scheduled //Schedule Job Button Pressed
D/global_PEA: Job Started //ExJobService runs
D/global_PEA: run: 0
D/global_PEA: run: 1
D/global_PEA: run: 2
D/global_PEA: run: 3
D/global_PEA: run: 4
// App closed and the output and notifications stop
// in theory it should continue till 9

=======

ОБНОВЛЕНИЕ
========== =====
Вот дамп оболочки adb моего приложения. это выглядит как запланировано? adb_shellDump

Я не могу получить никаких уведомлений или сообщений Log.d, когда я принудительно запускаю задание из adb, вот так
adb shell cmd jobscheduler run -f com.raaif.pea 902

, что приводит меня думать, что, возможно, задание действительно выполняется, но пользователю ничего не показывается, как уведомление. Есть ли способ, которым он мог бы уведомить приложение, даже если оно открывает приложение, когда работа выполнена?

==============

здесь мои файлы кодов

public class HomeFragment extends Fragment {

    private Context mContext;

    private Button btn1;
    private Button btn2;

    @Override
    public void onAttach(Context context) {
        mContext = context;
        super.onAttach(context);
    }

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        View root = inflater.inflate(R.layout.fragment_home, container, false);

        btn1 = root.findViewById(R.id.button1);
        btn2= root.findViewById(R.id.button2);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                scheduleJob();
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cancelJob();
            }
        });


        return root;
    }

    public void scheduleJob(){
        ComponentName componentName = new ComponentName(mContext, ExJobService.class);
        JobInfo info = new JobInfo.Builder(JOB_ID_1, componentName)
                .setRequiresCharging(false)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                .setPersisted(true)
                .setPeriodic(15 * 60 * 1000)
                .build();

        JobScheduler scheduler = (JobScheduler) mContext.getSystemService(JOB_SCHEDULER_SERVICE);
        int resultcode = scheduler.schedule(info);
        if(resultcode==JobScheduler.RESULT_SUCCESS){
            Log.d(globals.appTag,"Job Scheduled");
        }else{
            Log.d(globals.appTag,"Job Scheduling failed");
        }
    }

    public void cancelJob(){
        JobScheduler scheduler = (JobScheduler)getContext().getSystemService(JOB_SCHEDULER_SERVICE);
        scheduler.cancel(JOB_ID_1);
        Log.d(globals.appTag,"Job cancelled");
    }
}

А вот мой класс JobService

import android.app.Notification;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.util.Log;

import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import static com.raaif.pea.Constants.CHANNEL_ID_NOTIFICATION_HIGH;
import static com.raaif.pea.Constants.HIGH_NOTIF_ID;

public class ExJobService extends JobService {
    private Globals globals = Globals.getInstance();
    private boolean jobcancelled = false;
    private boolean reschedulestatus = false;

    @Override
    public boolean onStartJob(JobParameters params) {
        Log.d(globals.appTag, "Job Started");
        //output low notification
        notify("Scheduled JobService", "Starting Background Work");
        doBackgroundWork(params);
        return true;
    }

    private void doBackgroundWork(final JobParameters params) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    if (jobcancelled) return;
                    Log.d(globals.appTag, "run: " + i);
                    ExJobService.this.notify("Thread Iterator",
                            String.format("Iteration Count: %d", i));
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Log.d(globals.appTag, "Job Finished");
                ExJobService.this.notify("Scheduled JobService", "Background Work Finished");
                jobFinished(params, reschedulestatus);
                Log.d(globals.appTag, "Job Service Params returned with " + reschedulestatus);
                ExJobService.this.notify("Scheduled JobService", "Job Params returned");
            }
        }).start();
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        Log.d(globals.appTag, "Job Cancelled before completion");
        jobcancelled = true;
        notify("OnStopJob", "Job Cancelled");
        return false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //return Service.START_STICKY;
        return super.onStartCommand(intent, flags, startId);
    }

    public void notify(String title, String content) {
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

        Notification notification =
                new NotificationCompat.Builder(ExJobService.this, CHANNEL_ID_NOTIFICATION_HIGH)
                .setSmallIcon(R.drawable.ic_memory_black_24dp)
                .setContentTitle(title)
                .setContentText(content)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setOnlyAlertOnce(false)
                .build();
        notificationManager.notify(HIGH_NOTIF_ID, notification);
    }

}

Манифест. xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.raaif.pea">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <application
        android:name=".App"
        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"
        tools:ignore="GoogleAppIndexingWarning">

        <!-- SERVICES -->
       <service android:name=".ExJobService"
           android:permission="android.permission.BIND_JOB_SERVICE" />

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

Я вижу здесь проблема, но я не знаю, как вы справляетесь с этим ?! посмотрите на это:

public class ExJobService extends JobService {
    ...
    private boolean reschedulestatus = false;

    @Override
    public boolean onStartJob(JobParameters params) {
        ....
        doBackgroundWork(params);
        return true;
    }

    private void doBackgroundWork(final JobParameters params) {
        new Thread(new Runnable() {
                ....
                jobFinished(params, reschedulestatus);
                ....
        }).start();
    }
}

Вы передаете false методу jobFinished, который непреднамеренно не переносит задание.

0 голосов
/ 05 февраля 2020

При выполнении вещи периодически в фоновом режиме - JobScheduler, WorkManager, AlarmManager et c. - вы должны принять во внимание, что ваш процесс может не наступить, когда вам пора выполнять свою работу. Android создаст для вас процесс, но он «начинается с нуля». Все, что ваш пользовательский интерфейс мог установить в памяти, например, база данных, было бы для какого-то предыдущего процесса и не могло быть настроено в новом процессе.

...