Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android JobIntentService似乎已重新启动_Android_Jobintentservice - Fatal编程技术网

Android JobIntentService似乎已重新启动

Android JobIntentService似乎已重新启动,android,jobintentservice,Android,Jobintentservice,我有一个广播接收器,可以监听电源连接事件。每当设备接通电源时,我都会尝试将应用程序中的文件传输到运行Ubuntu的机器中的服务器上。文件通过蓝牙传输。由于文件传输非常重要,如果由于任何原因传输出现错误,或者第一次尝试连接未成功,我将重试最多6次,每次尝试间隔3分钟 一开始,我使用的是一个asynctask,只要我们仍然有可用的重试,并且文件传输没有成功完成,它就一直保持活动状态。我读到,在广播接收器中使用asynctask不是一个完全有意义的好做法,特别是因为我强制任务长时间运行。因此,我决定改

我有一个广播接收器,可以监听电源连接事件。每当设备接通电源时,我都会尝试将应用程序中的文件传输到运行Ubuntu的机器中的服务器上。文件通过蓝牙传输。由于文件传输非常重要,如果由于任何原因传输出现错误,或者第一次尝试连接未成功,我将重试最多6次,每次尝试间隔3分钟

一开始,我使用的是一个asynctask,只要我们仍然有可用的重试,并且文件传输没有成功完成,它就一直保持活动状态。我读到,在广播接收器中使用asynctask不是一个完全有意义的好做法,特别是因为我强制任务长时间运行。因此,我决定改为JobIntentService,这样每当接收器捕捉到电源连接事件时,我都会发出将文件传输到计算机的作业。在作业中,在文件传输完成或失败后,我会设置一个警报,向广播发送挂起的意图,然后再次调用作业

我正在运行这个程序,我注意到(与以前不同)在传输过程中出现了太多的“由对等方重置连接”错误,这让我怀疑作业是在完成之前停止的还是类似的?。在我以前的实现中,这些错误通常不会发生。然后,我还注意到,由于某种原因,操作系统似乎再次单独启动了JobIntentService(没有启动它的事件),这导致我的代码不一致,并导致我丢失了一些文件(我不允许同时运行此作业的多个实例)

我的问题是,为什么你认为服务被重新启动了?在BT传输期间,操作系统是否可能完成并重新启动JobIntentService?文件很重,因此从应用程序传输到计算机需要几分钟的时间。我想尝试一个前台服务,而不是JobIntent,并为该服务发出通知,或者返回到我以前的实现

有什么建议吗

这就是我所说的意向工作

FileTransferJob.isJobAlreadyRunning = true;
Intent intent = new Intent(context, FileTransferJob.class);
intent.putExtra(TRANSFER_DATA_RETRIES, retries);
FileTransferJob.enqueueWork(context,intent);
这是JobIntentService类

public class FileTransferJob extends JobIntentService {
/**
 * Unique job ID for this service.
 */
public static boolean isJobAlreadyRunning = false; //This flag will remain true as soon as this JOB is called and as long as retries are still available
public static final int JOB_ID = 1000;
public static int MAX_NUM_OF_RETRIES = 6;//How many times are we going to retry to send the data
private int MINUTES_TO_WAIT = 3; //The minutes we wait between each attempt
public String TAG = "FileTransferJob";

/**
 * Convenience method for enqueuing work in to this service.
 */
public static void enqueueWork(Context context, Intent work) {
    enqueueWork(context, FileTransferJob.class, JOB_ID, work);
}

@Override
protected void onHandleWork(Intent intent) {

    int retriesRemaining = intent.getIntExtra(TRANSFER_DATA_RETRIES,1); //Get the number of retries we have. Default to 1 (this one)
    Log.d(TAG, "onHandleWork: About to attempt transfer with remaining retries " + String.valueOf(retriesRemaining));


    try {
        BluetoothFileTransfer btio = new BluetoothFileTransfer();
        Log.d(TAG, "onHandleWork: About to send data over Bluetooth");
        btio.sendData(FileTransferJob.this.getApplicationContext());
        FileTransferJob.isJobAlreadyRunning = false; //Success, then this is no longer running
        Log.d(TAG, "onHandleWork: The data has been sent over Bluetooth");
    }catch (Exception e){
        Log.d(TAG, "onHandleWork: There was a problem with the BT transfer: " + e.getMessage());

        retriesRemaining--; //We reduce the number of retries we have

        //If no more retries available, simply do nothing
        if (retriesRemaining > 0) {
            Log.d(TAG, "onHandleWork: Setting up alarm. Retries ramaining: " + String.valueOf(retriesRemaining));
            AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
            Intent alarmIntent = new Intent(this.getApplicationContext(), DataCollectReceiver.class);
            alarmIntent.setAction(TRANSFER_DATA);
            alarmIntent.putExtra(TRANSFER_DATA_RETRIES, retriesRemaining);

            PendingIntent alarmPendingIntent = PendingIntent.getBroadcast( this.getApplicationContext(), PENDING_INTENT_CODE_FILE_TRANSFER_JOB, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            int totalTime = MINUTES_TO_WAIT*60*1000;
            if(alarmManager != null){
                alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
                        System.currentTimeMillis() + totalTime,
                        alarmPendingIntent);
                Log.d(TAG, "onHandleWork: Alarm is set, waiting " + String.valueOf(totalTime) + " minutes for next attempt...");
            }else{
                Log.d(TAG, "onHandleWork: Alarm could not be set. Alarm manager is NULL");
            }

        }else{
            Log.d(TAG, "onHandleWork: There are no more retries");
            FileTransferJob.isJobAlreadyRunning = false;
        }
    }
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy: The file transfer JOB has finished");
}

}
logcat。突出显示的部分显示了我认为操作系统正在创建JobService的新实例并运行它


让我试着回答这个问题,因为我注意到了这种行为。JobIntentService/JobService/Worker将仅运行10分钟,之后它们将被停止,如果是JobService/JobIntentService,您可以在onStopJob/onStopCurrentWork上获得回拨,如果是Worker,您可以在onStopJob上获得回拨

虽然android文档仅为Worker解释了此行为,但JobService/JobIntentServie的行为方式相同

工人最多有十分钟完成其执行并返回ListenableWorker.Result。该时间到期后,工人将收到停止的信号

因此,我可以假设您的任务没有在10分钟内完成,Android正在破坏JobIntentService。 现在的问题是,所有这些Jobservice/JobIntentService/Worker在指数退避时间(即30秒、1分钟、2分钟、4分钟)后再次启动(如果过早停止)

虽然奇怪的是,运行10分钟后死亡的旧线程开始了解释,但由于手工再次调用,它再次启动另一个线程,复制线程完成的工作,这就是为什么我认为您会看到不一致


建议你以一种在10分钟内就能完成的方式来完成你的工作。或者我们可以等待谷歌团队解决此问题。

您的问题可以由WorkManager解决。您是否尝试过改用WorkManager?您可以参考我关于的回答,&服务是否重新启动或似乎已重新启动?请准确一点。请不要在一个问题中问那么多问题。再说一遍,要准确,否则没人会回答。@Roger,你找到解决办法了吗?在启动JobIntentService从服务器下载文件时,我在应用程序中遇到了类似的行为。它将在10分钟后重新启动并复制下载,之前的下载仍在运行。您知道对此的修复方法吗?不幸的是,我的服务无法在10分钟内完成下载工作,因为它在很大程度上取决于服务器和连接速度。