| Index: chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
|
| similarity index 52%
|
| copy from chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
|
| copy to chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
|
| index d2f34b0b768d407134d7271310b5bf26d5d134fc..fa32532021d758230765cbfa7a9f0d45f9e7520c 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
|
| @@ -1,126 +1,61 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| package org.chromium.chrome.browser;
|
|
|
| -import android.app.Activity;
|
| import android.app.Notification;
|
| -import android.content.Context;
|
| import android.content.Intent;
|
| -import android.content.SharedPreferences;
|
| import android.os.Handler;
|
| import android.os.Looper;
|
| -import android.os.SystemClock;
|
| -import android.util.Log;
|
|
|
| -import org.chromium.base.ActivityState;
|
| -import org.chromium.base.ApplicationStatus;
|
| -import org.chromium.base.CommandLineInitUtil;
|
| import org.chromium.base.ContextUtils;
|
| -import org.chromium.base.ThreadUtils;
|
| -import org.chromium.base.TraceEvent;
|
| -import org.chromium.base.annotations.CalledByNative;
|
| -import org.chromium.base.annotations.MainDex;
|
| -import org.chromium.base.annotations.SuppressFBWarnings;
|
| -import org.chromium.base.library_loader.ProcessInitException;
|
| import org.chromium.chrome.browser.banners.AppDetailsDelegate;
|
| import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
|
| import org.chromium.chrome.browser.datausage.ExternalDataUseObserver;
|
| -import org.chromium.chrome.browser.document.DocumentActivity;
|
| -import org.chromium.chrome.browser.document.IncognitoDocumentActivity;
|
| import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
|
| import org.chromium.chrome.browser.feedback.EmptyFeedbackReporter;
|
| import org.chromium.chrome.browser.feedback.FeedbackReporter;
|
| import org.chromium.chrome.browser.gsa.GSAHelper;
|
| import org.chromium.chrome.browser.help.HelpAndFeedback;
|
| import org.chromium.chrome.browser.historyreport.AppIndexingReporter;
|
| -import org.chromium.chrome.browser.init.InvalidStartupDialog;
|
| +import org.chromium.chrome.browser.init.ProcessInitializationHandler;
|
| import org.chromium.chrome.browser.instantapps.InstantAppsHandler;
|
| import org.chromium.chrome.browser.locale.LocaleManager;
|
| import org.chromium.chrome.browser.media.VideoPersister;
|
| -import org.chromium.chrome.browser.metrics.UmaUtils;
|
| import org.chromium.chrome.browser.metrics.VariationsSession;
|
| import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
|
| import org.chromium.chrome.browser.net.qualityprovider.ExternalEstimateProviderAndroid;
|
| import org.chromium.chrome.browser.omaha.RequestGenerator;
|
| -import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
|
| import org.chromium.chrome.browser.physicalweb.PhysicalWebBleClient;
|
| import org.chromium.chrome.browser.policy.PolicyAuditor;
|
| import org.chromium.chrome.browser.preferences.LocationSettings;
|
| -import org.chromium.chrome.browser.preferences.PreferencesLauncher;
|
| -import org.chromium.chrome.browser.preferences.autofill.AutofillAndPaymentsPreferences;
|
| -import org.chromium.chrome.browser.preferences.password.SavePasswordsPreferences;
|
| import org.chromium.chrome.browser.rlz.RevenueStats;
|
| import org.chromium.chrome.browser.services.AndroidEduOwnerCheckCallback;
|
| import org.chromium.chrome.browser.signin.GoogleActivityController;
|
| import org.chromium.chrome.browser.sync.GmsCoreSyncListener;
|
| import org.chromium.chrome.browser.tab.AuthenticatorNavigationInterceptor;
|
| import org.chromium.chrome.browser.tab.Tab;
|
| -import org.chromium.chrome.browser.tabmodel.document.ActivityDelegateImpl;
|
| -import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelSelector;
|
| -import org.chromium.chrome.browser.tabmodel.document.StorageDelegate;
|
| -import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
|
| import org.chromium.chrome.browser.webapps.ChromeShortcutManager;
|
| import org.chromium.chrome.browser.webapps.GooglePlayWebApkInstallDelegate;
|
| import org.chromium.components.signin.AccountManagerDelegate;
|
| import org.chromium.components.signin.SystemAccountManagerDelegate;
|
| -import org.chromium.content.app.ContentApplication;
|
| import org.chromium.policy.AppRestrictionsProvider;
|
| import org.chromium.policy.CombinedPolicyProvider;
|
|
|
| /**
|
| - * Basic application functionality that should be shared among all browser applications that use
|
| - * chrome layer.
|
| + * Base class for defining methods where different behavior is required by downstream targets.
|
| + * The correct version of {@link AppHooksImpl} will be determined at compile time via build rules.
|
| + * See http://crbug/560466.
|
| */
|
| -@MainDex
|
| -public class ChromeApplication extends ContentApplication {
|
| - public static final String COMMAND_LINE_FILE = "chrome-command-line";
|
| +public abstract class AppHooks {
|
| + private static AppHooksImpl sInstance;
|
|
|
| - private static final String TAG = "ChromiumApplication";
|
| - private static final String PREF_BOOT_TIMESTAMP =
|
| - "com.google.android.apps.chrome.ChromeMobileApplication.BOOT_TIMESTAMP";
|
| - private static final long BOOT_TIMESTAMP_MARGIN_MS = 1000;
|
| -
|
| - private static DocumentTabModelSelector sDocumentTabModelSelector;
|
| -
|
| - @Override
|
| - protected void attachBaseContext(Context base) {
|
| - super.attachBaseContext(base);
|
| - ContextUtils.initApplicationContext(this);
|
| - }
|
| -
|
| - /**
|
| - * This is called once per ChromeApplication instance, which get created per process
|
| - * (browser OR renderer). Don't stick anything in here that shouldn't be called multiple times
|
| - * during Chrome's lifetime.
|
| - */
|
| - @Override
|
| - public void onCreate() {
|
| - UmaUtils.recordMainEntryPointTime();
|
| - initCommandLine();
|
| - TraceEvent.maybeEnableEarlyTracing();
|
| - TraceEvent.begin("ChromeApplication.onCreate");
|
| -
|
| - super.onCreate();
|
| -
|
| - TraceEvent.end("ChromeApplication.onCreate");
|
| - }
|
| -
|
| - /**
|
| - * Returns a new instance of VariationsSession.
|
| - */
|
| - public VariationsSession createVariationsSession() {
|
| - return new VariationsSession();
|
| - }
|
| -
|
| - /**
|
| - * Return a {@link AuthenticatorNavigationInterceptor} for the given {@link Tab}.
|
| - * This can be null if there are no applicable interceptor to be built.
|
| - */
|
| - @SuppressWarnings("unused")
|
| - public AuthenticatorNavigationInterceptor createAuthenticatorNavigationInterceptor(Tab tab) {
|
| - return null;
|
| + public static AppHooks get() {
|
| + if (sInstance == null) {
|
| + sInstance = new AppHooksImpl();
|
| + }
|
| + return sInstance;
|
| }
|
|
|
| /**
|
| @@ -136,77 +71,56 @@ public class ChromeApplication extends ContentApplication {
|
| });
|
| }
|
|
|
| - @CalledByNative
|
| - protected void showAutofillSettings() {
|
| - PreferencesLauncher.launchSettingsPage(
|
| - this, AutofillAndPaymentsPreferences.class.getName());
|
| - }
|
| -
|
| - @CalledByNative
|
| - protected void showPasswordSettings() {
|
| - PreferencesLauncher.launchSettingsPage(this,
|
| - SavePasswordsPreferences.class.getName());
|
| - }
|
| -
|
| - @Override
|
| - public void initCommandLine() {
|
| - CommandLineInitUtil.initCommandLine(this, COMMAND_LINE_FILE);
|
| + /**
|
| + * Creates a new {@link AccountManagerDelegate}.
|
| + * @return the created {@link AccountManagerDelegate}.
|
| + */
|
| + public AccountManagerDelegate createAccountManagerDelegate() {
|
| + return new SystemAccountManagerDelegate(ContextUtils.getApplicationContext());
|
| }
|
|
|
| /**
|
| - * Shows an error dialog following a startup error, and then exits the application.
|
| - * @param e The exception reported by Chrome initialization.
|
| + * @return An instance of AppDetailsDelegate that can be queried about app information for the
|
| + * App Banner feature. Will be null if one is unavailable.
|
| */
|
| - public static void reportStartupErrorAndExit(final ProcessInitException e) {
|
| - Activity activity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| - if (ApplicationStatus.getStateForActivity(activity) == ActivityState.DESTROYED) {
|
| - return;
|
| - }
|
| - InvalidStartupDialog.show(activity, e.getErrorCode());
|
| + public AppDetailsDelegate createAppDetailsDelegate() {
|
| + return null;
|
| }
|
|
|
| /**
|
| - * Returns an instance of LocationSettings to be installed as a singleton.
|
| + * Creates a new {@link AppIndexingReporter}.
|
| + * @return the created {@link AppIndexingReporter}.
|
| */
|
| - public LocationSettings createLocationSettings() {
|
| - // Using an anonymous subclass as the constructor is protected.
|
| - // This is done to deter instantiation of LocationSettings elsewhere without using the
|
| - // getInstance() helper method.
|
| - return new LocationSettings(){};
|
| + public AppIndexingReporter createAppIndexingReporter() {
|
| + return new AppIndexingReporter();
|
| }
|
|
|
| /**
|
| - * Opens the UI to clear browsing data.
|
| - * @param tab The tab that triggered the request.
|
| + * Return a {@link AuthenticatorNavigationInterceptor} for the given {@link Tab}.
|
| + * This can be null if there are no applicable interceptor to be built.
|
| */
|
| - @CalledByNative
|
| - protected void openClearBrowsingData(Tab tab) {
|
| - Activity activity = tab.getWindowAndroid().getActivity().get();
|
| - if (activity == null) {
|
| - Log.e(TAG,
|
| - "Attempting to open clear browsing data for a tab without a valid activity");
|
| - return;
|
| - }
|
| + public AuthenticatorNavigationInterceptor createAuthenticatorNavigationInterceptor(Tab tab) {
|
| + return null;
|
| + }
|
|
|
| - Intent intent = PreferencesLauncher.createIntentForClearBrowsingDataPage(activity);
|
| - activity.startActivity(intent);
|
| + /** Returns the singleton instance of ChromeShortcutManager */
|
| + public ChromeShortcutManager createChromeShortcutManager() {
|
| + return new ChromeShortcutManager();
|
| }
|
|
|
| /**
|
| - * @return Whether parental controls are enabled. Returning true will disable
|
| - * incognito mode.
|
| + * @return An instance of {@link CustomTabsConnection}. Should not be called
|
| + * outside of {@link CustomTabsConnection#getInstance()}.
|
| */
|
| - @CalledByNative
|
| - protected boolean areParentalControlsEnabled() {
|
| - return PartnerBrowserCustomizations.isIncognitoDisabled();
|
| + public CustomTabsConnection createCustomTabsConnection() {
|
| + return new CustomTabsConnection(((ChromeApplication) ContextUtils.getApplicationContext()));
|
| }
|
|
|
| /**
|
| - * @return A provider of external estimates.
|
| - * @param nativePtr Pointer to the native ExternalEstimateProviderAndroid object.
|
| + * @return An instance of ExternalAuthUtils to be installed as a singleton.
|
| */
|
| - public ExternalEstimateProviderAndroid createExternalEstimateProviderAndroid(long nativePtr) {
|
| - return new ExternalEstimateProviderAndroid(nativePtr) {};
|
| + public ExternalAuthUtils createExternalAuthUtils() {
|
| + return new ExternalAuthUtils();
|
| }
|
|
|
| /**
|
| @@ -218,54 +132,13 @@ public class ChromeApplication extends ContentApplication {
|
| }
|
|
|
| /**
|
| - * @return The user agent string of Chrome.
|
| - */
|
| - public static String getBrowserUserAgent() {
|
| - return nativeGetBrowserUserAgent();
|
| - }
|
| -
|
| - /**
|
| - * The host activity should call this during its onPause() handler to ensure
|
| - * all state is saved when the app is suspended. Calling ChromiumApplication.onStop() does
|
| - * this for you.
|
| - */
|
| - public static void flushPersistentData() {
|
| - try {
|
| - TraceEvent.begin("ChromiumApplication.flushPersistentData");
|
| - nativeFlushPersistentData();
|
| - } finally {
|
| - TraceEvent.end("ChromiumApplication.flushPersistentData");
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Removes all session cookies (cookies with no expiration date) after device reboots.
|
| - * This function will incorrectly clear cookies when Daylight Savings Time changes the clock.
|
| - * Without a way to get a monotonically increasing system clock, the boot timestamp will be off
|
| - * by one hour. However, this should only happen at most once when the clock changes since the
|
| - * updated timestamp is immediately saved.
|
| + * @return A provider of external estimates.
|
| + * @param nativePtr Pointer to the native ExternalEstimateProviderAndroid object.
|
| */
|
| - public static void removeSessionCookies() {
|
| - long lastKnownBootTimestamp =
|
| - ContextUtils.getAppSharedPreferences().getLong(PREF_BOOT_TIMESTAMP, 0);
|
| - long bootTimestamp = System.currentTimeMillis() - SystemClock.uptimeMillis();
|
| - long difference = bootTimestamp - lastKnownBootTimestamp;
|
| -
|
| - // Allow some leeway to account for fractions of milliseconds.
|
| - if (Math.abs(difference) > BOOT_TIMESTAMP_MARGIN_MS) {
|
| - nativeRemoveSessionCookies();
|
| -
|
| - SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
|
| - SharedPreferences.Editor editor = prefs.edit();
|
| - editor.putLong(PREF_BOOT_TIMESTAMP, bootTimestamp);
|
| - editor.apply();
|
| - }
|
| + public ExternalEstimateProviderAndroid createExternalEstimateProviderAndroid(long nativePtr) {
|
| + return new ExternalEstimateProviderAndroid(nativePtr) {};
|
| }
|
|
|
| - private static native void nativeRemoveSessionCookies();
|
| - private static native String nativeGetBrowserUserAgent();
|
| - private static native void nativeFlushPersistentData();
|
| -
|
| /**
|
| * @return An instance of {@link FeedbackReporter} to report feedback.
|
| */
|
| @@ -274,32 +147,33 @@ public class ChromeApplication extends ContentApplication {
|
| }
|
|
|
| /**
|
| - * @return An instance of ExternalAuthUtils to be installed as a singleton.
|
| + * @return An instance of GmsCoreSyncListener to notify GmsCore of sync encryption key changes.
|
| + * Will be null if one is unavailable.
|
| */
|
| - public ExternalAuthUtils createExternalAuthUtils() {
|
| - return new ExternalAuthUtils();
|
| + public GmsCoreSyncListener createGmsCoreSyncListener() {
|
| + return null;
|
| }
|
|
|
| /**
|
| - * Returns a new instance of HelpAndFeedback.
|
| + * @return An instance of GoogleActivityController.
|
| */
|
| - public HelpAndFeedback createHelpAndFeedback() {
|
| - return new HelpAndFeedback();
|
| + public GoogleActivityController createGoogleActivityController() {
|
| + return new GoogleActivityController();
|
| }
|
|
|
| /**
|
| - * @return An instance of {@link CustomTabsConnection}. Should not be called
|
| - * outside of {@link CustomTabsConnection#getInstance()}.
|
| + * @return An instance of {@link GSAHelper} that handles the start point of chrome's integration
|
| + * with GSA.
|
| */
|
| - public CustomTabsConnection createCustomTabsConnection() {
|
| - return new CustomTabsConnection(this);
|
| + public GSAHelper createGsaHelper() {
|
| + return new GSAHelper();
|
| }
|
|
|
| /**
|
| - * @return A new {@link PhysicalWebBleClient} instance.
|
| + * Returns a new instance of HelpAndFeedback.
|
| */
|
| - public PhysicalWebBleClient createPhysicalWebBleClient() {
|
| - return new PhysicalWebBleClient();
|
| + public HelpAndFeedback createHelpAndFeedback() {
|
| + return new HelpAndFeedback();
|
| }
|
|
|
| public InstantAppsHandler createInstantAppsHandler() {
|
| @@ -307,37 +181,20 @@ public class ChromeApplication extends ContentApplication {
|
| }
|
|
|
| /**
|
| - * @return An instance of {@link GSAHelper} that handles the start point of chrome's integration
|
| - * with GSA.
|
| - */
|
| - public GSAHelper createGsaHelper() {
|
| - return new GSAHelper();
|
| - }
|
| -
|
| - /**
|
| * @return An instance of {@link LocaleManager} that handles customized locale related logic.
|
| */
|
| public LocaleManager createLocaleManager() {
|
| return new LocaleManager();
|
| }
|
|
|
| - /**
|
| - * Registers various policy providers with the policy manager.
|
| - * Providers are registered in increasing order of precedence so overrides should call this
|
| - * method in the end for this method to maintain the highest precedence.
|
| - * @param combinedProvider The {@link CombinedPolicyProvider} to register the providers with.
|
| - */
|
| - public void registerPolicyProviders(CombinedPolicyProvider combinedProvider) {
|
| - combinedProvider.registerProvider(new AppRestrictionsProvider(getApplicationContext()));
|
| - }
|
| -
|
| /**
|
| - * @return An instance of PolicyAuditor that notifies the policy system of the user's activity.
|
| - * Only applicable when the user has a policy active, that is tracking the activity.
|
| + * Returns an instance of LocationSettings to be installed as a singleton.
|
| */
|
| - public PolicyAuditor getPolicyAuditor() {
|
| - // This class has a protected constructor to prevent accidental instantiation.
|
| - return new PolicyAuditor() {};
|
| + public LocationSettings createLocationSettings() {
|
| + // Using an anonymous subclass as the constructor is protected.
|
| + // This is done to deter instantiation of LocationSettings elsewhere without using the
|
| + // getInstance() helper method.
|
| + return new LocationSettings() {};
|
| }
|
|
|
| /**
|
| @@ -348,13 +205,6 @@ public class ChromeApplication extends ContentApplication {
|
| }
|
|
|
| /**
|
| - * @return An instance of VideoPersister to be installed as a singleton.
|
| - */
|
| - public VideoPersister createVideoPersister() {
|
| - return new VideoPersister();
|
| - }
|
| -
|
| - /**
|
| * @return An instance of RequestGenerator to be used for Omaha XML creation. Will be null if
|
| * a generator is unavailable.
|
| */
|
| @@ -363,77 +213,57 @@ public class ChromeApplication extends ContentApplication {
|
| }
|
|
|
| /**
|
| - * @return An instance of GmsCoreSyncListener to notify GmsCore of sync encryption key changes.
|
| - * Will be null if one is unavailable.
|
| + * @return A new {@link PhysicalWebBleClient} instance.
|
| */
|
| - public GmsCoreSyncListener createGmsCoreSyncListener() {
|
| - return null;
|
| + public PhysicalWebBleClient createPhysicalWebBleClient() {
|
| + return new PhysicalWebBleClient();
|
| }
|
|
|
| /**
|
| - * @return An instance of GoogleActivityController.
|
| - */
|
| - public GoogleActivityController createGoogleActivityController() {
|
| - return new GoogleActivityController();
|
| + * @return a new {@link ProcessInitializationHandler} instance.
|
| + */
|
| + public ProcessInitializationHandler createProcessInitializationHandler() {
|
| + return new ProcessInitializationHandler();
|
| }
|
|
|
| /**
|
| - * @return An instance of AppDetailsDelegate that can be queried about app information for the
|
| - * App Banner feature. Will be null if one is unavailable.
|
| + * @return An instance of RevenueStats to be installed as a singleton.
|
| */
|
| - public AppDetailsDelegate createAppDetailsDelegate() {
|
| - return null;
|
| - }
|
| -
|
| - /** Returns the singleton instance of GooglePlayWebApkInstallDelegate. */
|
| - public GooglePlayWebApkInstallDelegate getGooglePlayWebApkInstallDelegate() {
|
| - return null;
|
| - }
|
| -
|
| - /** Returns the singleton instance of ChromeShortcutManager */
|
| - public ChromeShortcutManager createChromeShortcutManager() {
|
| - return new ChromeShortcutManager();
|
| + public RevenueStats createRevenueStatsInstance() {
|
| + return new RevenueStats();
|
| }
|
|
|
| /**
|
| - * Returns the singleton instance of the DocumentTabModelSelector.
|
| - * TODO(dfalcantara): Find a better place for this once we differentiate between activity and
|
| - * application-level TabModelSelectors.
|
| - * @return The DocumentTabModelSelector for the application.
|
| + * Returns a new instance of VariationsSession.
|
| */
|
| - @SuppressFBWarnings("LI_LAZY_INIT_STATIC")
|
| - public static DocumentTabModelSelector getDocumentTabModelSelector() {
|
| - ThreadUtils.assertOnUiThread();
|
| - if (sDocumentTabModelSelector == null) {
|
| - ActivityDelegateImpl activityDelegate = new ActivityDelegateImpl(
|
| - DocumentActivity.class, IncognitoDocumentActivity.class);
|
| - sDocumentTabModelSelector = new DocumentTabModelSelector(activityDelegate,
|
| - new StorageDelegate(), new TabDelegate(false), new TabDelegate(true));
|
| - }
|
| - return sDocumentTabModelSelector;
|
| + public VariationsSession createVariationsSession() {
|
| + return new VariationsSession();
|
| }
|
|
|
| /**
|
| - * @return An instance of RevenueStats to be installed as a singleton.
|
| + * @return An instance of VideoPersister to be installed as a singleton.
|
| */
|
| - public RevenueStats createRevenueStatsInstance() {
|
| - return new RevenueStats();
|
| + public VideoPersister createVideoPersister() {
|
| + return new VideoPersister();
|
| }
|
|
|
| - /**
|
| - * Creates a new {@link AccountManagerDelegate}.
|
| - * @return the created {@link AccountManagerDelegate}.
|
| - */
|
| - public AccountManagerDelegate createAccountManagerDelegate() {
|
| - return new SystemAccountManagerDelegate(this);
|
| + /** Returns the singleton instance of GooglePlayWebApkInstallDelegate. */
|
| + public GooglePlayWebApkInstallDelegate getGooglePlayWebApkInstallDelegate() {
|
| + return null;
|
| }
|
|
|
| /**
|
| - * Creates a new {@link AppIndexingReporter}.
|
| - * @return the created {@link AppIndexingReporter}.
|
| + * @return An instance of PolicyAuditor that notifies the policy system of the user's activity.
|
| + * Only applicable when the user has a policy active, that is tracking the activity.
|
| */
|
| - public AppIndexingReporter createAppIndexingReporter() {
|
| - return new AppIndexingReporter();
|
| + public PolicyAuditor getPolicyAuditor() {
|
| + // This class has a protected constructor to prevent accidental instantiation.
|
| + return new PolicyAuditor() {};
|
| + }
|
| +
|
| + public void registerPolicyProviders(CombinedPolicyProvider combinedProvider) {
|
| + combinedProvider.registerProvider(
|
| + new AppRestrictionsProvider(ContextUtils.getApplicationContext()));
|
| }
|
|
|
| /**
|
| @@ -450,6 +280,6 @@ public class ChromeApplication extends ContentApplication {
|
| Intent intent, int notificationId, Notification notification) {
|
| // TODO(dtrainor): Eventually make sure the service gets put into the foreground with
|
| // {@link android.app.Service#startForeground(int, Notification)}.
|
| - startService(intent);
|
| + ContextUtils.getApplicationContext().startService(intent);
|
| }
|
| -}
|
| +}
|
|
|