use of androidx.annotation.RestrictTo in project CustomActivityOnCrash by Ereza.
the class CustomActivityOnCrash method install.
/**
* Installs CustomActivityOnCrash on the application using the default error activity.
*
* @param context Context to use for obtaining the ApplicationContext. Must not be null.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
public static void install(@Nullable final Context context) {
try {
if (context == null) {
Log.e(TAG, "Install failed: context is null!");
} else {
// INSTALL!
final Thread.UncaughtExceptionHandler oldHandler = Thread.getDefaultUncaughtExceptionHandler();
if (oldHandler != null && oldHandler.getClass().getName().startsWith(CAOC_HANDLER_PACKAGE_NAME)) {
Log.e(TAG, "CustomActivityOnCrash was already installed, doing nothing!");
} else {
if (oldHandler != null && !oldHandler.getClass().getName().startsWith(DEFAULT_HANDLER_PACKAGE_NAME)) {
Log.e(TAG, "IMPORTANT WARNING! You already have an UncaughtExceptionHandler, are you sure this is correct? If you use a custom UncaughtExceptionHandler, you must initialize it AFTER CustomActivityOnCrash! Installing anyway, but your original handler will not be called.");
}
application = (Application) context.getApplicationContext();
// We define a default exception handler that does what we want so it can be called from Crashlytics/ACRA
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(@NonNull Thread thread, @NonNull final Throwable throwable) {
if (config.isEnabled()) {
Log.e(TAG, "App has crashed, executing CustomActivityOnCrash's UncaughtExceptionHandler", throwable);
if (hasCrashedInTheLastSeconds(application)) {
Log.e(TAG, "App already crashed recently, not starting custom error activity because we could enter a restart loop. Are you sure that your app does not crash directly on init?", throwable);
if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
return;
}
} else {
setLastCrashTimestamp(application, new Date().getTime());
Class<? extends Activity> errorActivityClass = config.getErrorActivityClass();
if (errorActivityClass == null) {
errorActivityClass = guessErrorActivityClass(application);
}
if (isStackTraceLikelyConflictive(throwable, errorActivityClass)) {
Log.e(TAG, "Your application class or your error activity have crashed, the custom activity will not be launched!");
if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
return;
}
} else if (config.getBackgroundMode() == CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM || !isInBackground || (lastActivityCreatedTimestamp >= new Date().getTime() - TIME_TO_CONSIDER_FOREGROUND_MS)) {
final Intent intent = new Intent(application, errorActivityClass);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
String stackTraceString = sw.toString();
// And: http://stackoverflow.com/questions/11451393/what-to-do-on-transactiontoolargeexception#comment46697371_12809171
if (stackTraceString.length() > MAX_STACK_TRACE_SIZE) {
String disclaimer = " [stack trace too large]";
stackTraceString = stackTraceString.substring(0, MAX_STACK_TRACE_SIZE - disclaimer.length()) + disclaimer;
}
intent.putExtra(EXTRA_STACK_TRACE, stackTraceString);
if (config.isTrackActivities()) {
StringBuilder activityLogStringBuilder = new StringBuilder();
while (!activityLog.isEmpty()) {
activityLogStringBuilder.append(activityLog.poll());
}
intent.putExtra(EXTRA_ACTIVITY_LOG, activityLogStringBuilder.toString());
}
if (config.isShowRestartButton() && config.getRestartActivityClass() == null) {
// We can set the restartActivityClass because the app will terminate right now,
// and when relaunched, will be null again by default.
config.setRestartActivityClass(guessRestartActivityClass(application));
}
intent.putExtra(EXTRA_CONFIG, config);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
if (config.getEventListener() != null) {
config.getEventListener().onLaunchErrorActivity();
}
application.startActivity(intent);
} else if (config.getBackgroundMode() == CaocConfig.BACKGROUND_MODE_CRASH) {
if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
return;
}
// If it is null (should not be), we let it continue and kill the process or it will be stuck
}
// Else (BACKGROUND_MODE_SILENT): do nothing and let the following code kill the process
}
final Activity lastActivity = lastActivityCreated.get();
if (lastActivity != null) {
// We finish the activity, this solves a bug which causes infinite recursion.
// See: https://github.com/ACRA/acra/issues/42
lastActivity.finish();
lastActivityCreated.clear();
}
killCurrentProcess();
} else if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
}
}
});
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
int currentlyStartedActivities = 0;
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
@Override
public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {
if (activity.getClass() != config.getErrorActivityClass()) {
// Copied from ACRA:
// Ignore activityClass because we want the last
// application Activity that was started so that we can
// explicitly kill it off.
lastActivityCreated = new WeakReference<>(activity);
lastActivityCreatedTimestamp = new Date().getTime();
}
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " created\n");
}
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
currentlyStartedActivities++;
isInBackground = (currentlyStartedActivities == 0);
// Do nothing
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " resumed\n");
}
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " paused\n");
}
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
// Do nothing
currentlyStartedActivities--;
isInBackground = (currentlyStartedActivities == 0);
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
// Do nothing
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " destroyed\n");
}
}
});
}
Log.i(TAG, "CustomActivityOnCrash has been installed.");
}
} catch (Throwable t) {
Log.e(TAG, "An unknown error occurred while installing CustomActivityOnCrash, it may not have been properly initialized. Please report this as a bug if needed.", t);
}
}
use of androidx.annotation.RestrictTo in project Carbon by ZieIony.
the class TypefaceCompat method createFromResourcesFontFile.
/**
* Used by Resources to load a font resource of type font file.
*
* @hide
*/
@Nullable
@RestrictTo(LIBRARY_GROUP_PREFIX)
public static Typeface createFromResourcesFontFile(@NonNull Context context, @NonNull Resources resources, int id, String path, boolean italic, int weight) {
Typeface typeface = sTypefaceCompatImpl.createFromResourcesFontFile(context, resources, id, path, 0);
if (typeface != null) {
final String resourceUid = createResourceUid(resources, id, italic, weight);
sTypefaceCache.put(resourceUid, typeface);
}
return typeface;
}
use of androidx.annotation.RestrictTo in project lottie-android by airbnb.
the class LottieDrawable method draw.
/**
* To be used by lottie-compose only.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void draw(Canvas canvas, Matrix matrix) {
CompositionLayer compositionLayer = this.compositionLayer;
LottieComposition composition = this.composition;
if (compositionLayer == null || composition == null) {
return;
}
if (useSoftwareRendering) {
canvas.save();
canvas.concat(matrix);
renderAndDrawAsBitmap(canvas, compositionLayer);
canvas.restore();
} else {
compositionLayer.draw(canvas, matrix, alpha);
}
isDirty = false;
}
use of androidx.annotation.RestrictTo in project RxTools by vondear.
the class TCrashTool method install.
/**
* Installs CustomActivityOnCrash on the application using the default error activity.
*
* @param context Context to use for obtaining the ApplicationContext. Must not be null.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
public static void install(@Nullable final Context context) {
try {
if (context == null) {
TLog.e(TAG, "Install failed: context is null!");
} else {
// INSTALL!
final Thread.UncaughtExceptionHandler oldHandler = Thread.getDefaultUncaughtExceptionHandler();
if (oldHandler != null && oldHandler.getClass().getName().startsWith(TAM_HANDLER_PACKAGE_NAME)) {
TLog.e(TAG, "TCrashTool was already installed, doing nothing!");
} else {
if (oldHandler != null && !oldHandler.getClass().getName().startsWith(DEFAULT_HANDLER_PACKAGE_NAME)) {
TLog.e(TAG, "IMPORTANT WARNING! You already have an UncaughtExceptionHandler, are you sure this is correct? If you use a custom UncaughtExceptionHandler, you must initialize it AFTER TCrashTool! Installing anyway, but your original handler will not be called.");
}
application = (Application) context.getApplicationContext();
// We define a default exception handler that does what we want so it can be called from Crashlytics/ACRA
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
if (config.isEnabled()) {
TLog.e(TAG, "App has crashed, executing TCrashTool's UncaughtExceptionHandler", throwable);
if (hasCrashedInTheLastSeconds(application)) {
TLog.e(TAG, "App already crashed recently, not starting custom error activity because we could enter a restart loop. Are you sure that your app does not crash directly on init?", throwable);
if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
return;
}
} else {
setLastCrashTimestamp(application, new Date().getTime());
Class<? extends Activity> errorActivityClass = config.getErrorActivityClass();
if (errorActivityClass == null) {
errorActivityClass = guessErrorActivityClass(application);
}
if (isStackTraceLikelyConflictive(throwable, errorActivityClass)) {
TLog.e(TAG, "Your application class or your error activity have crashed, the custom activity will not be launched!");
if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
return;
}
} else if (config.getBackgroundMode() == TCrashProfile.BACKGROUND_MODE_SHOW_CUSTOM || !isInBackground || (lastActivityCreatedTimestamp >= new Date().getTime() - TIME_TO_CONSIDER_FOREGROUND_MS)) {
final Intent intent = new Intent(application, errorActivityClass);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
String stackTraceString = sw.toString();
// And: http://stackoverflow.com/questions/11451393/what-to-do-on-transactiontoolargeexception#comment46697371_12809171
if (stackTraceString.length() > MAX_STACK_TRACE_SIZE) {
String disclaimer = " [stack trace too large]";
stackTraceString = stackTraceString.substring(0, MAX_STACK_TRACE_SIZE - disclaimer.length()) + disclaimer;
}
intent.putExtra(EXTRA_STACK_TRACE, stackTraceString);
if (config.isTrackActivities()) {
StringBuilder activityLogStringBuilder = new StringBuilder();
while (!activityLog.isEmpty()) {
activityLogStringBuilder.append(activityLog.poll());
}
intent.putExtra(EXTRA_ACTIVITY_LOG, activityLogStringBuilder.toString());
}
if (config.isShowRestartButton() && config.getRestartActivityClass() == null) {
// We can set the restartActivityClass because the app will terminate right now,
// and when relaunched, will be null again by default.
config.setRestartActivityClass(guessRestartActivityClass(application));
}
intent.putExtra(EXTRA_CONFIG, config);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
if (config.getEventListener() != null) {
config.getEventListener().onLaunchErrorActivity();
}
application.startActivity(intent);
} else if (config.getBackgroundMode() == TCrashProfile.BACKGROUND_MODE_CRASH) {
if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
return;
}
// If it is null (should not be), we let it continue and kill the process or it will be stuck
}
// Else (BACKGROUND_MODE_SILENT): do nothing and let the following code kill the process
}
final Activity lastActivity = lastActivityCreated.get();
if (lastActivity != null) {
// We finish the activity, this solves a bug which causes infinite recursion.
// See: https://github.com/ACRA/acra/issues/42
lastActivity.finish();
lastActivityCreated.clear();
}
killCurrentProcess();
} else if (oldHandler != null) {
oldHandler.uncaughtException(thread, throwable);
}
});
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
int currentlyStartedActivities = 0;
@Override
public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {
if (activity.getClass() != config.getErrorActivityClass()) {
// Copied from ACRA:
// Ignore activityClass because we want the last
// application Activity that was started so that we can
// explicitly kill it off.
lastActivityCreated = new WeakReference<>(activity);
lastActivityCreatedTimestamp = new Date().getTime();
}
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " created\n");
}
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
currentlyStartedActivities++;
isInBackground = (currentlyStartedActivities == 0);
// Do nothing
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " resumed\n");
}
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " paused\n");
}
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
// Do nothing
currentlyStartedActivities--;
isInBackground = (currentlyStartedActivities == 0);
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
// Do nothing
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
if (config.isTrackActivities()) {
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " destroyed\n");
}
}
});
}
TLog.i(TAG, "TCrashTool has been installed.");
}
} catch (Throwable t) {
TLog.e(TAG, "An unknown error occurred while installing TCrashTool, it may not have been properly initialized. Please report this as a bug if needed.", t);
}
}
use of androidx.annotation.RestrictTo in project Carbon by ZieIony.
the class TypefaceCompat method createFromResourcesFamilyXml.
/**
* Create Typeface from XML resource which root node is font-family.
*
* @return null if failed to create.
* @hide
*/
@Nullable
@RestrictTo(LIBRARY_GROUP_PREFIX)
public static Typeface createFromResourcesFamilyXml(@NonNull Context context, @NonNull FamilyResourceEntry entry, @NonNull Resources resources, int id, int style, int weight, @Nullable ResourcesCompat.FontCallback fontCallback, @Nullable Handler handler, boolean isRequestFromLayoutInflator) {
Typeface typeface;
if (entry instanceof ProviderResourceEntry) {
ProviderResourceEntry providerEntry = (ProviderResourceEntry) entry;
final boolean isBlocking = isRequestFromLayoutInflator ? providerEntry.getFetchStrategy() == FontResourcesParserCompat.FETCH_STRATEGY_BLOCKING : fontCallback == null;
final int timeout = isRequestFromLayoutInflator ? providerEntry.getTimeout() : FontResourcesParserCompat.INFINITE_TIMEOUT_VALUE;
typeface = FontsContractCompat.getFontSync(context, providerEntry.getRequest(), fontCallback, handler, isBlocking, timeout, style);
} else {
typeface = sTypefaceCompatImpl.createFromFontFamilyFilesResourceEntry(context, (FontFamilyFilesResourceEntry) entry, resources, (style & Typeface.ITALIC) != 0, weight);
if (fontCallback != null) {
if (typeface != null) {
fontCallback.callbackSuccessAsync(typeface, handler);
} else {
fontCallback.callbackFailAsync(FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR, handler);
}
}
}
if (typeface != null) {
sTypefaceCache.put(createResourceUid(resources, id, (style & Typeface.ITALIC) != 0, weight), typeface);
}
return typeface;
}
Aggregations