/**
   * 初始化loader, 只可调用一次
   *
   * @param app
   */
  public static synchronized void initLoader(Application app, PluginManager manager) {

    if (!isLoaderInited) {
      LogUtil.d("插件框架初始化中...");

      isLoaderInited = true;
      sApplication = app;

      PluginInjector.injectBaseContext(sApplication);

      Object activityThread = PluginInjector.getActivityThread();
      PluginInjector.injectInstrumentation(activityThread);
      PluginInjector.injectHandlerCallback(activityThread);

      pluginManager = manager;
      changeListener = new PluginCallbackImpl();

      pluginManager.loadInstalledPlugins();
      changeListener.onPluginLoaderInited();

      if (Build.VERSION.SDK_INT >= 14) {

        sApplication.registerActivityLifecycleCallbacks(
            new Application.ActivityLifecycleCallbacks() {
              @Override
              public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

              @Override
              public void onActivityStarted(Activity activity) {}

              @Override
              public void onActivityResumed(Activity activity) {}

              @Override
              public void onActivityPaused(Activity activity) {}

              @Override
              public void onActivityStopped(Activity activity) {}

              @Override
              public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

              @Override
              public void onActivityDestroyed(Activity activity) {
                PluginStubBinding.unBindLaunchModeStubActivity(
                    activity.getClass().getName(), activity.getIntent());
              }
            });
      }
      LogUtil.d("插件框架初始化完成");
    }
  }
  public ThunderBoardPowerSaver(Context context, PreferenceManager preferenceManager) {

    if (android.os.Build.VERSION.SDK_INT < 18) {
      Timber.d("BackgroundPowerSaver requires API 18 or higher.");
      return;
    }

    if (context instanceof Application) {
      ((Application) context).registerActivityLifecycleCallbacks(this);
    } else {
      Timber.e("Context is not an application instance, so we cannot use the BackgroundPowerSaver");
    }

    this.preferenceManager = preferenceManager;
    this.beaconManager = BeaconManager.getInstanceForApplication(context);
  }
Пример #3
0
  /**
   * Fix for https://code.google.com/p/android/issues/detail?id=171190 .
   *
   * <p>When a view that has focus gets detached, we wait for the main thread to be idle and then
   * check if the InputMethodManager is leaking a view. If yes, we tell it that the decor view got
   * focus, which is what happens if you press home and come back from recent apps. This replaces
   * the reference to the detached view with a reference to the decor view.
   *
   * <p>Should be called from {@link Activity#onCreate(android.os.Bundle)} )}.
   */
  @TargetApi(Build.VERSION_CODES.KITKAT)
  public static void fixFocusedViewLeak(Application application) {

    // Don't know about other versions yet.
    if (SDK_INT < 19 || SDK_INT > 23) {
      return;
    }

    final InputMethodManager inputMethodManager =
        (InputMethodManager) application.getSystemService(INPUT_METHOD_SERVICE);

    final Field mServedViewField;
    final Field mHField;
    final Method finishInputLockedMethod;
    final Method focusInMethod;
    try {
      mServedViewField = InputMethodManager.class.getDeclaredField("mServedView");
      mServedViewField.setAccessible(true);
      mHField = InputMethodManager.class.getDeclaredField("mServedView");
      mHField.setAccessible(true);
      finishInputLockedMethod = InputMethodManager.class.getDeclaredMethod("finishInputLocked");
      finishInputLockedMethod.setAccessible(true);
      focusInMethod = InputMethodManager.class.getDeclaredMethod("focusIn", View.class);
      focusInMethod.setAccessible(true);
    } catch (NoSuchMethodException | NoSuchFieldException unexpected) {
      Log.e("IMMLeaks", "Unexpected reflection exception", unexpected);
      return;
    }

    application.registerActivityLifecycleCallbacks(
        new LifecycleCallbacksAdapter() {
          @Override
          public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            ReferenceCleaner cleaner =
                new ReferenceCleaner(
                    inputMethodManager, mHField, mServedViewField, finishInputLockedMethod);
            View rootView = activity.getWindow().getDecorView().getRootView();
            ViewTreeObserver viewTreeObserver = rootView.getViewTreeObserver();
            viewTreeObserver.addOnGlobalFocusChangeListener(cleaner);
          }
        });
  }
  public static void startTracking(Application application, final String appId) {
    if (!tracking.compareAndSet(false, true)) {
      return;
    }

    ActivityLifecycleTracker.appId = appId;

    application.registerActivityLifecycleCallbacks(
        new Application.ActivityLifecycleCallbacks() {
          @Override
          public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
            AppEventUtility.assertIsMainThread();
            ActivityLifecycleTracker.onActivityCreated(activity);
          }

          @Override
          public void onActivityStarted(Activity activity) {}

          @Override
          public void onActivityResumed(final Activity activity) {
            AppEventUtility.assertIsMainThread();
            ActivityLifecycleTracker.onActivityResumed(activity);
          }

          @Override
          public void onActivityPaused(final Activity activity) {
            AppEventUtility.assertIsMainThread();
            ActivityLifecycleTracker.onActivityPaused(activity);
          }

          @Override
          public void onActivityStopped(Activity activity) {
            AppEventsLogger.onContextStop();
          }

          @Override
          public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

          @Override
          public void onActivityDestroyed(Activity activity) {}
        });
  }
  public LifeCycleSupport(Context context) {
    applicationBaseContext = context;
    mRequestManager = new RequestManager();

    lifeCycle =
        new Application.ActivityLifecycleCallbacks() {

          @Override
          public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

          @Override
          public void onActivityStarted(Activity activity) {}

          @Override
          public void onActivityResumed(Activity activity) {
            mRequestManager.resumeLoad();
          }

          @Override
          public void onActivityPaused(Activity activity) {}

          @Override
          public void onActivityStopped(Activity activity) {
            mRequestManager.unsubscribeAll();
          }

          @Override
          public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

          @Override
          public void onActivityDestroyed(Activity activity) {
            mRequestManager.onDestroy();
          }
        };
    ((Application) applicationBaseContext).registerActivityLifecycleCallbacks(lifeCycle);
  }
  /**
   * 初始化loader, 只可调用一次
   *
   * @param app
   */
  public static synchronized void initLoader(Application app, PluginManager manager) {

    if (!isLoaderInited) {
      LogUtil.d("插件框架初始化中...");

      isLoaderInited = true;
      sApplication = app;
      pluginManager = manager;
      changeListener = new PluginCallbackImpl();

      AndroidAppIActivityManager.installProxy();
      AndroidAppINotificationManager.installProxy();
      AndroidAppIPackageManager.installProxy(sApplication.getPackageManager());
      AndroidWidgetToast.installProxy();
      // 不可在主进程中同步安装,因为此时ActivityThread还没有准备好, 会导致空指针。
      new Handler()
          .postDelayed(
              new Runnable() {
                @Override
                public void run() {
                  AndroidWebkitWebViewFactoryProvider.installProxy();
                }
              },
              50);

      PluginInjector.injectInstrumentation();
      PluginInjector.injectHandlerCallback();
      PluginInjector.injectBaseContext(sApplication);

      pluginManager.loadInstalledPlugins();
      Iterator<PluginDescriptor> itr = getPlugins().iterator();
      while (itr.hasNext()) {
        PluginDescriptor plugin = itr.next();
        LocalServiceManager.registerService(plugin);
      }
      changeListener.onPluginLoaderInited();

      if (Build.VERSION.SDK_INT >= 14) {
        sApplication.registerActivityLifecycleCallbacks(
            new Application.ActivityLifecycleCallbacks() {
              @Override
              public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

              @Override
              public void onActivityStarted(Activity activity) {}

              @Override
              public void onActivityResumed(Activity activity) {}

              @Override
              public void onActivityPaused(Activity activity) {}

              @Override
              public void onActivityStopped(Activity activity) {}

              @Override
              public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

              @Override
              public void onActivityDestroyed(Activity activity) {
                PluginStubBinding.unBindLaunchModeStubActivity(
                    activity.getClass().getName(), activity.getIntent());
              }
            });
      }
      LogUtil.d("插件框架初始化完成");
    }
  }
Пример #7
0
 @Override
 public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
   super.registerActivityLifecycleCallbacks(callback);
 }
Пример #8
0
 public ActivityErrorHandler(Application application) {
   application.registerActivityLifecycleCallbacks(this);
 }
Пример #9
0
 public ForegroundDetector(Application application) {
   Instance = this;
   application.registerActivityLifecycleCallbacks(this);
 }
  /**
   * Installs CustomActivityOnCrash on the application using the default error activity.
   *
   * @param context Context to use for obtaining the ApplicationContext. Must not be null.
   */
  public static void install(Context context) {
    try {
      if (context == null) {
        Log.e(TAG, "Install failed: context is null!");
      } else {
        if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
          Log.w(
              TAG,
              "CustomActivityOnCrash will be installed, but may not be reliable in API lower than 14");
        }

        // INSTALL!
        final Thread.UncaughtExceptionHandler oldHandler =
            Thread.getDefaultUncaughtExceptionHandler();

        if (oldHandler != null
            && oldHandler.getClass().getName().startsWith(CAOC_HANDLER_PACKAGE_NAME)) {
          Log.e(TAG, "You have already installed CustomActivityOnCrash, 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 ACRA, Crashlytics or similar libraries, you must initialize them 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(Thread thread, final Throwable throwable) {
                  Log.e(
                      TAG,
                      "App has crashed, executing CustomActivityOnCrash's UncaughtExceptionHandler",
                      throwable);

                  if (hasCrashedInTheLastSeconds(application)) {
                    Log.e(
                        TAG,
                        "App already crashed in the last 2 seconds, 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());

                    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 (launchErrorActivityWhenInBackground || !isInBackground) {

                      final Intent intent = new Intent(application, errorActivityClass);
                      StringWriter sw = new StringWriter();
                      PrintWriter pw = new PrintWriter(sw);
                      throwable.printStackTrace(pw);
                      String stackTraceString = sw.toString();

                      // Reduce data to 128KB so we don't get a TransactionTooLargeException when
                      // sending the intent.
                      // The limit is 1MB on Android but some devices seem to have it lower.
                      // See:
                      // http://developer.android.com/reference/android/os/TransactionTooLargeException.html
                      // 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;
                      }

                      if (enableAppRestart && restartActivityClass == null) {
                        // We can set the restartActivityClass because the app will terminate right
                        // now,
                        // and when relaunched, will be null again by default.
                        restartActivityClass = guessRestartActivityClass(application);
                      } else if (!enableAppRestart) {
                        // In case someone sets the activity and then decides to not restart
                        restartActivityClass = null;
                      }

                      intent.putExtra(EXTRA_STACK_TRACE, stackTraceString);
                      intent.putExtra(EXTRA_RESTART_ACTIVITY_CLASS, restartActivityClass);
                      intent.putExtra(EXTRA_SHOW_ERROR_DETAILS, showErrorDetails);
                      intent.putExtra(EXTRA_EVENT_LISTENER, eventListener);
                      intent.putExtra(EXTRA_IMAGE_DRAWABLE_ID, defaultErrorActivityDrawableId);
                      intent.setFlags(
                          Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                      if (eventListener != null) {
                        eventListener.onLaunchErrorActivity();
                      }
                      application.startActivity(intent);
                    }
                  }
                  final Activity lastActivity = lastActivityCreated.get();
                  if (lastActivity != null) {
                    // We finish the activity, this solves a bug which causes infinite recursion.
                    // This is unsolvable in API<14, so beware!
                    // See: https://github.com/ACRA/acra/issues/42
                    lastActivity.finish();
                    lastActivityCreated.clear();
                  }
                  killCurrentProcess();
                }
              });
          if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            application.registerActivityLifecycleCallbacks(
                new Application.ActivityLifecycleCallbacks() {
                  int currentlyStartedActivities = 0;

                  @Override
                  public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                    if (activity.getClass() != errorActivityClass) {
                      // 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);
                    }
                  }

                  @Override
                  public void onActivityStarted(Activity activity) {
                    currentlyStartedActivities++;
                    isInBackground = (currentlyStartedActivities == 0);
                    // Do nothing
                  }

                  @Override
                  public void onActivityResumed(Activity activity) {
                    // Do nothing
                  }

                  @Override
                  public void onActivityPaused(Activity activity) {
                    // Do nothing
                  }

                  @Override
                  public void onActivityStopped(Activity activity) {
                    // Do nothing
                    currentlyStartedActivities--;
                    isInBackground = (currentlyStartedActivities == 0);
                  }

                  @Override
                  public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                    // Do nothing
                  }

                  @Override
                  public void onActivityDestroyed(Activity activity) {
                    // Do nothing
                  }
                });
          }

          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);
    }
  }