Skip to content

Commit

Permalink
Merge pull request #664 from F43nd1r/scheduler
Browse files Browse the repository at this point in the history
Advanced scheduling
  • Loading branch information
F43nd1r committed May 4, 2018
2 parents 5c2e584 + c547290 commit 2c77a12
Show file tree
Hide file tree
Showing 22 changed files with 471 additions and 84 deletions.
27 changes: 27 additions & 0 deletions acra-advanced-scheduler/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2018
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'

dependencies {
api project(':acra-core')
implementation "com.evernote:android-job:$jobVersion"
compileOnly "com.google.auto.service:auto-service:$autoServiceVersion"
annotationProcessor project(':annotationprocessor')
compileOnly project(':annotations')
}
17 changes: 17 additions & 0 deletions acra-advanced-scheduler/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!--
~ Copyright (c) 2018
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<manifest package="org.acra.scheduler"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2018
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.acra.annotation;

import android.support.annotation.NonNull;
import com.evernote.android.job.JobRequest;

import java.lang.annotation.*;

/**
* @author F43nd1r
* @since 18.04.18
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Configuration
public @interface AcraScheduler {
/**
* Network constraint for report sending
*
* @return networkType required to allow report sending
* @since 5.2.0
*/
@NonNull JobRequest.NetworkType requiresNetworkType() default JobRequest.NetworkType.ANY;

/**
* Charging constraint for report sending
*
* @return if reports should only be sent while charging
* @since 5.2.0
*/
boolean requiresCharging() default false;

/**
* Idle constraint for report sending
*
* @return if reports should only be sent while the device is idle
* @since 5.2.0
*/
boolean requiresDeviceIdle() default false;

/**
* Battery constraint for report sending
*
* @return if reports should only be sent while battery isn't low
* @since 5.2.0
*/
boolean requiresBatteryNotLow() default false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2018
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.acra.scheduler;

import android.content.Context;
import android.support.annotation.NonNull;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.google.auto.service.AutoService;
import org.acra.config.ConfigUtils;
import org.acra.config.CoreConfiguration;
import org.acra.config.SchedulerConfiguration;
import org.acra.file.ReportLocator;
import org.acra.plugins.ConfigBasedAllowsDisablePlugin;
import org.acra.sender.SenderService;

import java.util.concurrent.TimeUnit;

/**
* Utilizes evernotes android-job to delay report sending
*
* @author F43nd1r
* @since 18.04.18
*/
public class AdvancedSenderScheduler implements SenderScheduler {
static final String TAG = "org.acra.report.Job";
private final Context context;
private final CoreConfiguration config;

private AdvancedSenderScheduler(@NonNull Context context, @NonNull CoreConfiguration config) {
this.context = context;
this.config = config;
}

@Override
public void scheduleReportSending(boolean onlySendSilentReports) {
if(new ReportLocator(context).getApprovedReports().length == 0) {
return;
}
SchedulerConfiguration schedulerConfiguration = ConfigUtils.getPluginConfiguration(config, SchedulerConfiguration.class);
PersistableBundleCompat extras = new PersistableBundleCompat();
extras.putBoolean(SenderService.EXTRA_ONLY_SEND_SILENT_REPORTS, onlySendSilentReports);
new JobRequest.Builder(TAG)
.setExecutionWindow(1, TimeUnit.MINUTES.toMillis(1))
.setExtras(extras)
.setRequirementsEnforced(true)
.setRequiredNetworkType(schedulerConfiguration.requiresNetworkType())
.setRequiresCharging(schedulerConfiguration.requiresCharging())
.setRequiresDeviceIdle(schedulerConfiguration.requiresDeviceIdle())
.setRequiresBatteryNotLow(schedulerConfiguration.requiresBatteryNotLow())
.setUpdateCurrent(true)
.build()
.schedule();
}

@AutoService(SenderSchedulerFactory.class)
public static class Factory extends ConfigBasedAllowsDisablePlugin implements SenderSchedulerFactory {

public Factory() {
super(SchedulerConfiguration.class);
}

@NonNull
@Override
public SenderScheduler create(@NonNull Context context, @NonNull CoreConfiguration config) {
JobManager.create(context).addJobCreator(tag -> TAG.equals(tag) ? new Job() {
@NonNull
@Override
protected Result onRunJob(@NonNull Params params) {
boolean sendOnlySilentReports = params.getExtras().getBoolean(SenderService.EXTRA_ONLY_SEND_SILENT_REPORTS, false);
new DefaultSenderScheduler(getContext(), config).scheduleReportSending(sendOnlySilentReports);
return Result.SUCCESS;
}
} : null);
return new AdvancedSenderScheduler(context, config);
}
}
}
10 changes: 1 addition & 9 deletions acra-core/src/main/java/org/acra/ACRA.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import org.acra.config.ACRAConfigurationException;
import org.acra.config.CoreConfiguration;
import org.acra.config.CoreConfigurationBuilder;
Expand All @@ -31,7 +30,6 @@
import org.acra.log.AndroidLogDelegate;
import org.acra.prefs.SharedPreferencesFactory;
import org.acra.reporter.ErrorReporterImpl;
import org.acra.util.ApplicationStartupProcessor;
import org.acra.util.StreamReader;
import org.acra.util.StubCreator;

Expand Down Expand Up @@ -225,15 +223,9 @@ public static void init(@NonNull Application app, @NonNull CoreConfiguration con
final boolean enableAcra = supportedAndroidVersion && SharedPreferencesFactory.shouldEnableACRA(prefs);
// Indicate that ACRA is or is not listening for crashes.
log.i(LOG_TAG, "ACRA is " + (enableAcra ? "enabled" : "disabled") + " for " + app.getPackageName() + ", initializing...");
ErrorReporterImpl reporter = new ErrorReporterImpl(app, config, enableAcra, supportedAndroidVersion);
ErrorReporterImpl reporter = new ErrorReporterImpl(app, config, enableAcra, supportedAndroidVersion, checkReportsOnApplicationStart);
errorReporterSingleton = reporter;

// Check for approved reports and send them (if enabled).
// NB don't check if senderServiceProcess as it will gather these reports itself.
if (checkReportsOnApplicationStart) {
new ApplicationStartupProcessor(app, config).checkReports(enableAcra);
}

// register after initAcra is called to avoid a
// NPE in ErrorReporter.disable() because
// the context could be null at this moment.
Expand Down
8 changes: 8 additions & 0 deletions acra-core/src/main/java/org/acra/ErrorReporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.acra.scheduler.SenderScheduler;

/**
* This interface contains methods used to interact with ACRA after it has been initialized
Expand Down Expand Up @@ -79,4 +80,11 @@ public interface ErrorReporter {
* @param e The {@link Throwable} to be reported. If null the report will contain a new Exception("Report requested by developer").
*/
void handleException(@Nullable Throwable e);

/**
* Access point to manual report scheduling
*
* @return current SenderScheduler
*/
SenderScheduler getReportScheduler();
}
22 changes: 11 additions & 11 deletions acra-core/src/main/java/org/acra/builder/ReportExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.Toast;

import org.acra.ACRA;
import org.acra.ACRAConstants;
import org.acra.config.CoreConfiguration;
Expand All @@ -32,13 +31,13 @@
import org.acra.file.CrashReportPersister;
import org.acra.file.ReportLocator;
import org.acra.interaction.ReportInteractionExecutor;
import org.acra.sender.SenderServiceStarter;
import org.acra.plugins.PluginLoader;
import org.acra.scheduler.SchedulerStarter;
import org.acra.util.ProcessFinisher;
import org.acra.util.ToastSender;

import java.io.File;
import java.util.*;
import java.util.List;

import static org.acra.ACRA.LOG_TAG;
import static org.acra.ReportField.IS_SILENT;
Expand All @@ -55,6 +54,7 @@ public class ReportExecutor {
private final CoreConfiguration config;
private final CrashReportDataFactory crashReportDataFactory;
private final List<ReportingAdministrator> reportingAdministrators;
private final SchedulerStarter schedulerStarter;

// A reference to the system's previous default UncaughtExceptionHandler
// kept in order to execute the default exception handling after sending the report.
Expand All @@ -74,13 +74,14 @@ public class ReportExecutor {
* @param processFinisher used to end process after reporting
*/
public ReportExecutor(@NonNull Context context, @NonNull CoreConfiguration config, @NonNull CrashReportDataFactory crashReportDataFactory,
@Nullable Thread.UncaughtExceptionHandler defaultExceptionHandler, @NonNull ProcessFinisher processFinisher) {
@Nullable Thread.UncaughtExceptionHandler defaultExceptionHandler, @NonNull ProcessFinisher processFinisher, @NonNull SchedulerStarter schedulerStarter) {
this.context = context;
this.config = config;
this.crashReportDataFactory = crashReportDataFactory;
this.defaultExceptionHandler = defaultExceptionHandler;
this.processFinisher = processFinisher;
reportingAdministrators = new PluginLoader(config).load(ReportingAdministrator.class);
this.schedulerStarter = schedulerStarter;
}

/**
Expand Down Expand Up @@ -157,15 +158,15 @@ public final void execute(@NonNull final ReportBuilder reportBuilder) {
saveCrashReportFile(reportFile, crashReportData);

final ReportInteractionExecutor executor = new ReportInteractionExecutor(context, config);
StrictMode.setThreadPolicy(oldPolicy);
if (reportBuilder.isSendSilently()) {
//if size == 0 we have no interaction and can send all reports
startSendingReports(executor.hasInteractions());
//if no interactions are present we can send all reports
sendReport(reportFile, executor.hasInteractions());
} else {
if (executor.performInteractions(reportFile)) {
startSendingReports(false);
sendReport(reportFile, false);
}
}
StrictMode.setThreadPolicy(oldPolicy);
} else {
if (ACRA.DEV_LOGGING) ACRA.log.d(LOG_TAG, "Not sending crash report because of ReportingAdministrator " + blockingAdministrator.getClass().getName());
try {
Expand Down Expand Up @@ -225,10 +226,9 @@ private void endApplication(@Nullable Thread uncaughtExceptionThread, Throwable
*
* @param onlySendSilentReports If true then only send silent reports.
*/
private void startSendingReports(boolean onlySendSilentReports) {
private void sendReport(@NonNull File report, boolean onlySendSilentReports) {
if (enabled) {
final SenderServiceStarter starter = new SenderServiceStarter(context, config);
starter.startService(onlySendSilentReports, true);
schedulerStarter.scheduleReports(report, onlySendSilentReports);
} else {
ACRA.log.w(LOG_TAG, "Would be sending reports, but ACRA is disabled");
}
Expand Down
16 changes: 16 additions & 0 deletions acra-core/src/main/java/org/acra/plugins/AllowsDisablePlugin.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright (c) 2018
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.acra.plugins;

import android.support.annotation.NonNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright (c) 2018
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.acra.plugins;

import android.support.annotation.NonNull;
Expand Down
Loading

0 comments on commit 2c77a12

Please sign in to comment.