/* * Twidere - Twitter client for Android * * Copyright (C) 2012-2015 Mariotaku Lee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package org.mariotaku.twidere.util.dagger import android.app.Application import android.content.Context import android.location.LocationManager import android.net.ConnectivityManager import android.os.Build import android.os.Looper import android.support.v4.net.ConnectivityManagerCompat import android.support.v4.text.BidiFormatter import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory import com.google.android.exoplayer2.extractor.ExtractorsFactory import com.google.android.exoplayer2.upstream.DataSource import com.squareup.otto.Bus import com.squareup.otto.ThreadEnforcer import com.twitter.Extractor import com.twitter.Validator import dagger.Module import dagger.Provides import edu.tsinghua.hotmobi.HotMobiLogger import okhttp3.Cache import okhttp3.ConnectionPool import okhttp3.Dns import okhttp3.OkHttpClient import org.mariotaku.kpreferences.KPreferences import org.mariotaku.mediaviewer.library.FileCache import org.mariotaku.mediaviewer.library.MediaDownloader import org.mariotaku.restfu.http.RestHttpClient import org.mariotaku.twidere.Constants import org.mariotaku.twidere.constant.SharedPreferenceConstants import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_CACHE_SIZE_LIMIT import org.mariotaku.twidere.constant.autoRefreshCompatibilityModeKey import org.mariotaku.twidere.model.DefaultFeatures import org.mariotaku.twidere.util.* import org.mariotaku.twidere.util.cache.DiskLRUFileCache import org.mariotaku.twidere.util.cache.JsonCache import org.mariotaku.twidere.util.media.TwidereMediaDownloader import org.mariotaku.twidere.util.net.TwidereDns import org.mariotaku.twidere.util.premium.ExtraFeaturesService import org.mariotaku.twidere.util.refresh.AutoRefreshController import org.mariotaku.twidere.util.refresh.JobSchedulerAutoRefreshController import org.mariotaku.twidere.util.refresh.LegacyAutoRefreshController import org.mariotaku.twidere.util.sync.JobSchedulerSyncController import org.mariotaku.twidere.util.sync.LegacySyncController import org.mariotaku.twidere.util.sync.SyncController import org.mariotaku.twidere.util.sync.SyncPreferences import java.io.File import javax.inject.Singleton /** * Created by mariotaku on 15/10/5. */ @Module class ApplicationModule(private val application: Application) { init { if (Thread.currentThread() !== Looper.getMainLooper().thread) { throw RuntimeException("Module must be created inside main thread") } } @Provides @Singleton fun keyboardShortcutsHandler(): KeyboardShortcutsHandler { return KeyboardShortcutsHandler(application) } @Provides @Singleton fun externalThemeManager(preferences: SharedPreferencesWrapper): ExternalThemeManager { return ExternalThemeManager(application, preferences) } @Provides @Singleton fun notificationManagerWrapper(): NotificationManagerWrapper { return NotificationManagerWrapper(application) } @Provides @Singleton fun sharedPreferences(): SharedPreferencesWrapper { return SharedPreferencesWrapper.getInstance(application, Constants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE, SharedPreferenceConstants::class.java) } @Provides @Singleton fun kPreferences(sharedPreferences: SharedPreferencesWrapper): KPreferences { return KPreferences(sharedPreferences) } @Provides @Singleton fun permissionsManager(): PermissionsManager { return PermissionsManager(application) } @Provides @Singleton fun userColorNameManager(): UserColorNameManager { return UserColorNameManager(application) } @Provides @Singleton fun multiSelectManager(): MultiSelectManager { return MultiSelectManager() } @Provides @Singleton fun restHttpClient(prefs: SharedPreferencesWrapper, dns: Dns, connectionPool: ConnectionPool, cache: Cache): RestHttpClient { val conf = HttpClientFactory.HttpClientConfiguration(prefs) return HttpClientFactory.createRestHttpClient(conf, dns, connectionPool, cache) } @Provides @Singleton fun connectionPool(): ConnectionPool { return ConnectionPool() } @Provides @Singleton fun bus(): Bus { return Bus(ThreadEnforcer.MAIN) } @Provides @Singleton fun asyncTaskManager(): AsyncTaskManager { return AsyncTaskManager() } @Provides @Singleton fun activityTracker(): ActivityTracker { return ActivityTracker() } @Provides @Singleton fun asyncTwitterWrapper(bus: Bus, preferences: SharedPreferencesWrapper, asyncTaskManager: AsyncTaskManager, notificationManagerWrapper: NotificationManagerWrapper): AsyncTwitterWrapper { return AsyncTwitterWrapper(application, bus, preferences, asyncTaskManager, notificationManagerWrapper) } @Provides @Singleton fun readStateManager(): ReadStateManager { return ReadStateManager(application) } @Provides @Singleton fun contentNotificationManager(activityTracker: ActivityTracker, userColorNameManager: UserColorNameManager, notificationManagerWrapper: NotificationManagerWrapper, preferences: SharedPreferencesWrapper): ContentNotificationManager { return ContentNotificationManager(application, activityTracker, userColorNameManager, notificationManagerWrapper, preferences) } @Provides @Singleton fun mediaLoaderWrapper(preferences: SharedPreferencesWrapper): MediaPreloader { val preloader = MediaPreloader(application) preloader.reloadOptions(preferences) val cm = application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager preloader.isNetworkMetered = ConnectivityManagerCompat.isActiveNetworkMetered(cm) return preloader } @Provides @Singleton fun dns(preferences: SharedPreferencesWrapper): Dns { return TwidereDns(application, preferences) } @Provides @Singleton fun mediaDownloader(preferences: SharedPreferencesWrapper, client: RestHttpClient): MediaDownloader { return TwidereMediaDownloader(application, preferences, client) } @Provides @Singleton fun validator(): Validator { return Validator() } @Provides @Singleton fun extractor(): Extractor { return Extractor() } @Provides @Singleton fun errorInfoStore(): ErrorInfoStore { return ErrorInfoStore(application) } @Provides fun provideBidiFormatter(): BidiFormatter { return BidiFormatter.getInstance() } @Provides @Singleton fun autoRefreshController(kPreferences: KPreferences): AutoRefreshController { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !kPreferences[autoRefreshCompatibilityModeKey]) { return JobSchedulerAutoRefreshController(application, kPreferences) } return LegacyAutoRefreshController(application, kPreferences) } @Provides @Singleton fun syncController(): SyncController { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return JobSchedulerSyncController(application) } return LegacySyncController(application) } @Provides @Singleton fun syncPreferences(): SyncPreferences { return SyncPreferences(application) } @Provides @Singleton fun taskCreator(kPreferences: KPreferences, bus: Bus): TaskServiceRunner { return TaskServiceRunner(application, kPreferences, bus) } @Provides @Singleton fun defaultFeatures(preferences: SharedPreferencesWrapper): DefaultFeatures { val features = DefaultFeatures() features.load(preferences) return features } @Provides @Singleton fun hotMobiLogger(): HotMobiLogger { return HotMobiLogger(application) } @Provides @Singleton fun extraFeaturesService(): ExtraFeaturesService { return ExtraFeaturesService.newInstance(application) } @Provides @Singleton fun etagCache(): ETagCache { return ETagCache(application) } @Provides fun locationManager(): LocationManager { return application.getSystemService(Context.LOCATION_SERVICE) as LocationManager } @Provides fun okHttpClient(preferences: SharedPreferencesWrapper, dns: Dns, connectionPool: ConnectionPool, cache: Cache): OkHttpClient { val conf = HttpClientFactory.HttpClientConfiguration(preferences) val builder = OkHttpClient.Builder() HttpClientFactory.initOkHttpClient(conf, builder, dns, connectionPool, cache) return builder.build() } @Provides @Singleton fun dataSourceFactory(preferences: SharedPreferencesWrapper, dns: Dns, connectionPool: ConnectionPool, cache: Cache): DataSource.Factory { val conf = HttpClientFactory.HttpClientConfiguration(preferences) val builder = OkHttpClient.Builder() HttpClientFactory.initOkHttpClient(conf, builder, dns, connectionPool, cache) val userAgent = UserAgentUtils.getDefaultUserAgentStringSafe(application) return OkHttpDataSourceFactory(builder.build(), userAgent, null) } @Provides @Singleton fun cache(preferences: SharedPreferencesWrapper): Cache { val cacheSizeMB = preferences.getInt(KEY_CACHE_SIZE_LIMIT, 300).coerceIn(100..500) // Convert to bytes return Cache(getCacheDir("network", cacheSizeMB * 1048576L), cacheSizeMB * 1048576L) } @Provides @Singleton fun extractorsFactory(): ExtractorsFactory { return DefaultExtractorsFactory() } @Provides @Singleton fun jsonCache(): JsonCache { return JsonCache(getCacheDir("json", 100 * 1048576L)) } @Provides @Singleton fun fileCache(): FileCache { return DiskLRUFileCache(getCacheDir("media", 100 * 1048576L)) } private fun getCacheDir(dirName: String, sizeInBytes: Long): File { return Utils.getExternalCacheDir(application, dirName, sizeInBytes) ?: Utils.getInternalCacheDir(application, dirName) } companion object { private var sApplicationModule: ApplicationModule? = null fun get(context: Context): ApplicationModule { if (sApplicationModule != null) return sApplicationModule!! val application = context.applicationContext as Application sApplicationModule = ApplicationModule(application) return sApplicationModule!! } } }