Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increasing flexibility of CrashDialog #502

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
<uses-sdk android:minSdkVersion="8"/>

<application>
<!--suppress AndroidDomInspection -->
<activity
android:name="org.acra.dialog.CrashReportDialogImpl"
android:theme="@android:style/Theme.Dialog"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:finishOnTaskLaunch="true"
android:process=":acra"/>

<activity
android:name="org.acra.dialog.CrashReportDialog"
android:theme="@android:style/Theme.Dialog"
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/org/acra/IAcraApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2016
*
* 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;

import org.acra.config.ConfigurationBuilder;

/**
* Applications using the compiler can extend this class to manually configure the builder
*
* @author F43nd1r
* @since 4.9.1
*/

public interface IAcraApplication {
void configure(ConfigurationBuilder builder);
}
35 changes: 35 additions & 0 deletions src/main/java/org/acra/annotation/AcraDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2016
*
* 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 java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Used to mark a dialog for the compiler
*
* @author F43nd1r
* @since 4.9.1
*/

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@Inherited
public @interface AcraDialog {
}
4 changes: 2 additions & 2 deletions src/main/java/org/acra/builder/LastActivityManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import android.support.annotation.Nullable;

import org.acra.ACRA;
import org.acra.dialog.BaseCrashReportDialog;
import org.acra.dialog.ICrashReportDialog;

import java.lang.ref.WeakReference;

Expand All @@ -32,7 +32,7 @@ public LastActivityManager(@NonNull Application application) {
@Override
public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {
if (ACRA.DEV_LOGGING) ACRA.log.d(LOG_TAG, "onActivityCreated " + activity.getClass());
if (!(activity instanceof BaseCrashReportDialog)) {
if (!(activity instanceof ICrashReportDialog)) {
// Ignore CrashReportDialog because we want the last
// application Activity that was started so that we can explicitly kill it off.
lastActivityCreated = new WeakReference<Activity>(activity);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/acra/config/ACRAConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import org.acra.ReportingInteractionMode;
import org.acra.builder.ReportPrimer;
import org.acra.collections.ImmutableList;
import org.acra.dialog.BaseCrashReportDialog;
import org.acra.dialog.ICrashReportDialog;
import org.acra.file.Directory;
import org.acra.security.KeyStoreFactory;
import org.acra.sender.HttpSender.Method;
Expand Down Expand Up @@ -60,7 +60,7 @@ public final class ACRAConfiguration implements Serializable {
private final ImmutableList<String> logcatArguments;
private final String mailTo;
private final ReportingInteractionMode reportingInteractionMode;
private final Class<? extends BaseCrashReportDialog> reportDialogClass;
private final Class<? extends ICrashReportDialog> reportDialogClass;
private final Class<? extends ReportPrimer> reportPrimerClass;

@StringRes
Expand Down Expand Up @@ -383,7 +383,7 @@ public Directory applicationLogFileDir() {
}

@NonNull
public Class<? extends BaseCrashReportDialog> reportDialogClass() {
public Class<? extends ICrashReportDialog> reportDialogClass() {
return reportDialogClass;
}

Expand Down
16 changes: 12 additions & 4 deletions src/main/java/org/acra/config/ConfigurationBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.acra.config;

import android.app.Activity;
import android.app.Application;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
Expand All @@ -29,8 +30,8 @@
import org.acra.annotation.ReportsCrashes;
import org.acra.builder.NoOpReportPrimer;
import org.acra.builder.ReportPrimer;
import org.acra.dialog.BaseCrashReportDialog;
import org.acra.dialog.CrashReportDialog;
import org.acra.dialog.ICrashReportDialog;
import org.acra.file.Directory;
import org.acra.security.KeyStoreFactory;
import org.acra.security.NoKeyStoreFactory;
Expand Down Expand Up @@ -81,7 +82,7 @@ public final class ConfigurationBuilder {
private String[] logcatArguments;
private String mailTo;
private ReportingInteractionMode reportingInteractionMode;
private Class<? extends BaseCrashReportDialog> reportDialogClass;
private Class<? extends ICrashReportDialog> reportDialogClass;
private Class<? extends ReportPrimer> reportPrimerClass;

@StringRes private Integer resDialogPositiveButtonText;
Expand Down Expand Up @@ -121,6 +122,13 @@ public final class ConfigurationBuilder {
private String certificateType;
private Class<? extends RetryPolicy> retryPolicyClass;

/**
* Constructs a ConfigurationBuilder with default values.
*/
public ConfigurationBuilder(){
annotationType = null;
}


/**
* Constructs a ConfigurationBuilder that is prepopulated with any
Expand Down Expand Up @@ -444,7 +452,7 @@ public ConfigurationBuilder setResDialogNegativeButtonText(@StringRes int resId)
}

@NonNull
public ConfigurationBuilder setReportDialogClass(@NonNull Class<? extends BaseCrashReportDialog> reportDialogClass) {
public <T extends Activity & ICrashReportDialog> ConfigurationBuilder setReportDialogClass(@NonNull Class<T> reportDialogClass) {
this.reportDialogClass = reportDialogClass;
return this;
}
Expand Down Expand Up @@ -1164,7 +1172,7 @@ Directory applicationLogFileDir() {
}

@NonNull
Class<? extends BaseCrashReportDialog> reportDialogClass() {
Class<? extends ICrashReportDialog> reportDialogClass() {
if (reportDialogClass != null) {
return reportDialogClass;
}
Expand Down
117 changes: 27 additions & 90 deletions src/main/java/org/acra/dialog/BaseCrashReportDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,18 @@
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.widget.Toast;

import org.acra.ACRA;
import org.acra.ACRAConstants;
import org.acra.collector.CrashReportData;
import org.acra.config.ACRAConfiguration;
import org.acra.file.BulkReportDeleter;
import org.acra.file.CrashReportPersister;
import org.acra.sender.SenderServiceStarter;
import org.acra.util.ToastSender;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;

import static org.acra.ACRA.LOG_TAG;
import static org.acra.ReportField.USER_COMMENT;
import static org.acra.ReportField.USER_EMAIL;

/**
* Activity which implements the base functionality for a CrashReportDialog.
*
* <p>
* Activities which extend from this class can override init to create a custom view.
*
* <p>
* The methods sendCrash(comment, userEmail) and cancelReports() can be used to send or cancel
* sending of reports respectively.
*
* <p>
* This Activity will be instantiated with 3 (or 4) arguments:
* <ol>
* <li>{@link ACRAConstants#EXTRA_REPORT_FILE_NAME}</li>
Expand All @@ -38,103 +23,55 @@
* <li>{@link ACRAConstants#EXTRA_FORCE_CANCEL} (optional)</li>
* </ol>
*/
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class BaseCrashReportDialog extends Activity {

private File reportFile;
private ACRAConfiguration config;
private Throwable exception;
public abstract class BaseCrashReportDialog extends Activity implements ICrashReportDialog {
private final CrashReportDelegate delegate;

public BaseCrashReportDialog() {
delegate = new CrashReportDelegate(this);
}

/**
* NB if you were previously creating and showing your dialog in this method,
* you should move that code to {@link #init(Bundle)}.
*
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
*/
@Override
protected final void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


if (ACRA.DEV_LOGGING) {
ACRA.log.d(LOG_TAG, "CrashReportDialog extras=" + getIntent().getExtras());
}

final Serializable sConfig = getIntent().getSerializableExtra(ACRAConstants.EXTRA_REPORT_CONFIG);
final Serializable sReportFile = getIntent().getSerializableExtra(ACRAConstants.EXTRA_REPORT_FILE);
final Serializable sException = getIntent().getSerializableExtra(ACRAConstants.EXTRA_REPORT_EXCEPTION);
final boolean forceCancel = getIntent().getBooleanExtra(ACRAConstants.EXTRA_FORCE_CANCEL, false);

if (forceCancel) {
if (ACRA.DEV_LOGGING) ACRA.log.d(LOG_TAG, "Forced reports deletion.");
cancelReports();
finish();
} else if ((sConfig instanceof ACRAConfiguration) && (sReportFile instanceof File) && ((sException instanceof Throwable) || sException == null)) {
config = (ACRAConfiguration) sConfig;
reportFile = (File) sReportFile;
exception = (Throwable) sException;
if (delegate.loadFromIntent(getIntent())) {
init(savedInstanceState);
} else {
ACRA.log.w(LOG_TAG, "Illegal or incomplete call of BaseCrashReportDialog.");
finish();
}
}

/**
* Responsible for creating and showing the crash report dialog.
*
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
*/
protected void init(@Nullable Bundle savedInstanceState) {
}


/**
* Cancel any pending crash reports.
* {@inheritDoc}
*/
protected final void cancelReports() {
new BulkReportDeleter(getApplicationContext()).deleteReports(false, 0);
@Override
public void cancelReports() {
delegate.cancelReports();
}


/**
* Send crash report given user's comment and email address. If none should be empty strings
*
* @param comment Comment (may be null) provided by the user.
* @param userEmail Email address (may be null) provided by the client.
* {@inheritDoc}
*/
protected final void sendCrash(@Nullable String comment, @Nullable String userEmail) {
final CrashReportPersister persister = new CrashReportPersister();
try {
if (ACRA.DEV_LOGGING) ACRA.log.d(LOG_TAG, "Add user comment to " + reportFile);
final CrashReportData crashData = persister.load(reportFile);
crashData.put(USER_COMMENT, comment == null ? "" : comment);
crashData.put(USER_EMAIL, userEmail == null ? "" : userEmail);
persister.store(crashData, reportFile);
} catch (IOException e) {
ACRA.log.w(LOG_TAG, "User comment not added: ", e);
}

// Start the report sending task
final SenderServiceStarter starter = new SenderServiceStarter(getApplicationContext(), config);
starter.startService(false, true);

// Optional Toast to thank the user
final int toastId = config.resDialogOkToast();
if (toastId != 0) {
ToastSender.sendToast(getApplicationContext(), toastId, Toast.LENGTH_LONG);
}
@Override
public void sendCrash(@Nullable String comment, @Nullable String userEmail) {
delegate.sendCrash(comment, userEmail);
}

protected final ACRAConfiguration getConfig() {
return config;
@Override
public ACRAConfiguration getConfig() {
return delegate.getConfig();
}

protected final Throwable getException() {
return exception;
@Override
public Throwable getException() {
return delegate.getException();
}
}
Loading