Search in sources :

Example 1 with RestrictTo

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);
    }
}
Also used : Bundle(android.os.Bundle) DefaultErrorActivity(cat.ereza.customactivityoncrash.activity.DefaultErrorActivity) Activity(android.app.Activity) Intent(android.content.Intent) Date(java.util.Date) SuppressLint(android.annotation.SuppressLint) StringWriter(java.io.StringWriter) SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) WeakReference(java.lang.ref.WeakReference) Application(android.app.Application) SimpleDateFormat(java.text.SimpleDateFormat) PrintWriter(java.io.PrintWriter) RestrictTo(androidx.annotation.RestrictTo)

Example 2 with RestrictTo

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;
}
Also used : Typeface(android.graphics.Typeface) RestrictTo(androidx.annotation.RestrictTo) Nullable(androidx.annotation.Nullable)

Example 3 with RestrictTo

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;
}
Also used : CompositionLayer(com.airbnb.lottie.model.layer.CompositionLayer) RestrictTo(androidx.annotation.RestrictTo)

Example 4 with RestrictTo

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);
    }
}
Also used : Bundle(android.os.Bundle) Activity(android.app.Activity) Intent(android.content.Intent) Date(java.util.Date) SuppressLint(android.annotation.SuppressLint) StringWriter(java.io.StringWriter) SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) WeakReference(java.lang.ref.WeakReference) Application(android.app.Application) SimpleDateFormat(java.text.SimpleDateFormat) PrintWriter(java.io.PrintWriter) RestrictTo(androidx.annotation.RestrictTo)

Example 5 with RestrictTo

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;
}
Also used : FontFamilyFilesResourceEntry(androidx.core.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry) Typeface(android.graphics.Typeface) ProviderResourceEntry(androidx.core.content.res.FontResourcesParserCompat.ProviderResourceEntry) RestrictTo(androidx.annotation.RestrictTo) Nullable(androidx.annotation.Nullable)

Aggregations

RestrictTo (androidx.annotation.RestrictTo)6 SuppressLint (android.annotation.SuppressLint)3 Activity (android.app.Activity)2 Application (android.app.Application)2 Intent (android.content.Intent)2 Typeface (android.graphics.Typeface)2 Bundle (android.os.Bundle)2 Nullable (androidx.annotation.Nullable)2 PrintWriter (java.io.PrintWriter)2 StringWriter (java.io.StringWriter)2 WeakReference (java.lang.ref.WeakReference)2 DateFormat (java.text.DateFormat)2 SimpleDateFormat (java.text.SimpleDateFormat)2 Date (java.util.Date)2 NonNull (androidx.annotation.NonNull)1 FontFamilyFilesResourceEntry (androidx.core.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry)1 ProviderResourceEntry (androidx.core.content.res.FontResourcesParserCompat.ProviderResourceEntry)1 DefaultErrorActivity (cat.ereza.customactivityoncrash.activity.DefaultErrorActivity)1 CompositionLayer (com.airbnb.lottie.model.layer.CompositionLayer)1 User (com.firebase.ui.auth.data.model.User)1