RIP Flipper

pull/3321/head
Alex Baker 10 months ago
parent 7ed406fbbc
commit 6fe9b0b255

@ -194,9 +194,6 @@ dependencies {
implementation(libs.markwon.tables)
implementation(libs.markwon.tasklist)
debugImplementation(libs.facebook.flipper)
debugImplementation(libs.facebook.flipper.network)
debugImplementation(libs.facebook.soloader)
debugImplementation(libs.leakcanary)
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation(libs.kotlin.reflect)

@ -7,10 +7,6 @@
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:exported="true"
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"/>
</application>
</manifest>

@ -3,14 +3,6 @@ package org.tasks
import android.app.Application
import android.os.StrictMode
import android.os.StrictMode.VmPolicy
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.android.utils.FlipperUtils
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin
import com.facebook.flipper.plugins.inspector.DescriptorMapping
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin
import com.facebook.soloader.SoLoader
import com.todoroo.andlib.utility.AndroidUtilities.atLeastOreo
import com.todoroo.andlib.utility.AndroidUtilities.atLeastQ
import leakcanary.AppWatcher
@ -27,18 +19,9 @@ class BuildSetup @Inject constructor(
fun setup() {
Timber.plant(Timber.DebugTree())
Timber.plant(fileLogger)
SoLoader.init(context, false)
if (preferences.getBoolean(R.string.p_leakcanary, false)) {
AppWatcher.manualInstall(context)
}
if (preferences.getBoolean(R.string.p_flipper, false) && FlipperUtils.shouldEnableFlipper(context)) {
val client = AndroidFlipperClient.getInstance(context)
client.addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()))
client.addPlugin(DatabasesFlipperPlugin(context))
client.addPlugin(NetworkFlipperPlugin())
client.addPlugin(SharedPreferencesFlipperPlugin(context))
client.start()
}
if (preferences.getBoolean(R.string.p_strict_mode_thread, false)) {
val builder = StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog()
if (preferences.getBoolean(R.string.p_crash_main_queries, false)) {

@ -1,39 +0,0 @@
package org.tasks
import android.content.Context
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpResponse
import dagger.hilt.android.qualifiers.ApplicationContext
import okhttp3.OkHttpClient
import java.io.IOException
import javax.inject.Inject
class DebugNetworkInterceptor @Inject constructor(@param:ApplicationContext private val context: Context) {
fun apply(builder: OkHttpClient.Builder?) {
builder?.addNetworkInterceptor(FlipperOkhttpInterceptor(getNetworkPlugin(context)))
}
@Throws(IOException::class)
fun <T> execute(request: HttpRequest, responseClass: Class<T>): T? {
val interceptor = FlipperHttpInterceptor(getNetworkPlugin(context), responseClass)
request
.setInterceptor(interceptor)
.setResponseInterceptor(interceptor)
.execute()
return interceptor.response
}
@Throws(IOException::class)
fun <T> report(httpResponse: HttpResponse, responseClass: Class<T>, start: Long, finish: Long): T? {
val interceptor = FlipperHttpInterceptor(getNetworkPlugin(context), responseClass)
interceptor.report(httpResponse, start, finish)
return interceptor.response
}
private fun getNetworkPlugin(context: Context): NetworkFlipperPlugin {
return AndroidFlipperClient.getInstance(context).getPlugin(NetworkFlipperPlugin.ID)!!
}
}

@ -1,82 +0,0 @@
package org.tasks
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.facebook.flipper.plugins.network.NetworkReporter
import com.facebook.flipper.plugins.network.NetworkReporter.ResponseInfo
import com.google.api.client.http.*
import com.google.api.client.json.GenericJson
import org.tasks.data.UUIDHelper
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber
import java.io.ByteArrayOutputStream
import java.io.IOException
internal class FlipperHttpInterceptor<T>(private val plugin: NetworkFlipperPlugin, private val responseClass: Class<T>) : HttpExecuteInterceptor, HttpResponseInterceptor {
private val requestId = UUIDHelper.newUUID()
var response: T? = null
private set
override fun intercept(request: HttpRequest) {
plugin.reportRequest(toRequestInfo(request, currentTimeMillis()))
}
@Throws(IOException::class)
override fun interceptResponse(response: HttpResponse) {
plugin.reportResponse(toResponseInfo(response, currentTimeMillis()))
}
@Throws(IOException::class)
fun report(response: HttpResponse, start: Long, end: Long) {
plugin.reportRequest(toRequestInfo(response.request, start))
plugin.reportResponse(toResponseInfo(response, end))
}
private fun toRequestInfo(request: HttpRequest, timestamp: Long): NetworkReporter.RequestInfo {
val requestInfo = NetworkReporter.RequestInfo()
requestInfo.method = request.requestMethod
requestInfo.body = bodyToByteArray(request.content)
requestInfo.headers = getHeaders(request.headers)
requestInfo.requestId = requestId
requestInfo.timeStamp = timestamp
requestInfo.uri = request.url.toString()
return requestInfo
}
@Throws(IOException::class)
private fun toResponseInfo(response: HttpResponse, timestamp: Long): ResponseInfo {
val responseInfo = ResponseInfo()
responseInfo.timeStamp = timestamp
responseInfo.headers = getHeaders(response.headers)
responseInfo.requestId = requestId
responseInfo.statusCode = response.statusCode
responseInfo.statusReason = response.statusMessage
this.response = response.parseAs(responseClass)
if (this.response is GenericJson) {
try {
responseInfo.body = (this.response as GenericJson).toPrettyString().toByteArray()
} catch (e: IOException) {
Timber.e(e)
}
}
return responseInfo
}
private fun getHeaders(headers: HttpHeaders): List<NetworkReporter.Header> {
return headers.map { (name, value) -> NetworkReporter.Header(name, value.toString()) }
}
private fun bodyToByteArray(content: HttpContent?): ByteArray? {
if (content == null) {
return null
}
val output = ByteArrayOutputStream()
try {
content.writeTo(output)
} catch (e: IOException) {
Timber.e(e)
return null
}
return output.toByteArray()
}
}

@ -30,7 +30,6 @@ class Debug : InjectingPreferenceFragment() {
override suspend fun setupPreferences(savedInstanceState: Bundle?) {
for (pref in listOf(
R.string.p_leakcanary,
R.string.p_flipper,
R.string.p_strict_mode_vm,
R.string.p_strict_mode_thread,
R.string.p_crash_main_queries

@ -4,7 +4,6 @@
<string name="debug_strict_mode_thread">Strict mode - Thread</string>
<string name="debug_strict_mode_vm">Strict mode - VM</string>
<string name="debug_leakcanary">LeakCanary</string>
<string name="debug_flipper">Flipper</string>
<string name="debug_pro">Unlock pro</string>
<string name="debug_purchase">Purchase %s</string>
<string name="debug_consume">Consume %s</string>

@ -6,11 +6,6 @@
android:key="@string/p_leakcanary"
android:title="@string/debug_leakcanary" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="@string/p_flipper"
android:title="@string/debug_flipper"/>
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="@string/p_strict_mode_vm"

@ -6,9 +6,7 @@ import com.google.api.services.tasks.Tasks
import com.google.api.services.tasks.model.Task
import com.google.api.services.tasks.model.TaskList
import com.google.api.services.tasks.model.TaskLists
import org.tasks.DebugNetworkInterceptor
import org.tasks.googleapis.BaseInvoker
import org.tasks.preferences.Preferences
import java.io.IOException
/**
@ -19,9 +17,7 @@ import java.io.IOException
*/
class GtasksInvoker(
credentials: HttpCredentialsAdapter,
preferences: Preferences,
interceptor: DebugNetworkInterceptor
) : BaseInvoker(credentials, preferences, interceptor) {
) : BaseInvoker(credentials) {
private val service =
Tasks.Builder(NetHttpTransport(), GsonFactory(), credentials)
.setApplicationName(APP_NAME)

@ -10,19 +10,15 @@ import com.google.api.services.drive.model.File
import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter
import com.todoroo.astrid.gtasks.api.HttpNotFoundException
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.DebugNetworkInterceptor
import org.tasks.backup.BackupConstants
import org.tasks.files.FileHelper
import org.tasks.googleapis.BaseInvoker
import org.tasks.preferences.Preferences
import java.io.IOException
class DriveInvoker(
@param:ApplicationContext private val context: Context,
preferences: Preferences,
credentialsAdapter: HttpCredentialsAdapter,
interceptor: DebugNetworkInterceptor
) : BaseInvoker(credentialsAdapter, preferences, interceptor) {
) : BaseInvoker(credentialsAdapter) {
private val service =
Drive.Builder(NetHttpTransport(), GsonFactory(), credentialsAdapter)
.setApplicationName(APP_NAME)

@ -8,16 +8,11 @@ import com.todoroo.astrid.gtasks.api.HttpNotFoundException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.tasks.BuildConfig
import org.tasks.DebugNetworkInterceptor
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber
import java.io.IOException
abstract class BaseInvoker(
private val credentialsAdapter: HttpCredentialsAdapter,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor
) {
@Throws(IOException::class)
protected suspend fun <T> execute(request: AbstractGoogleJsonClientRequest<T>): T? = execute(request, false)
@ -28,15 +23,7 @@ abstract class BaseInvoker(
credentialsAdapter.checkToken()
Timber.d(caller)
val response: T? = try {
if (preferences.isFlipperEnabled) {
val start = currentTimeMillis()
val httpResponse = request.executeUnparsed()
interceptor.report(httpResponse, request.responseClass, start,
currentTimeMillis()
)
} else {
request.execute()
}
request.execute()
} catch (e: HttpResponseException) {
return@withContext if (e.statusCode == 401 && !retry) {
credentialsAdapter.invalidateToken()

@ -6,7 +6,6 @@ import com.google.api.services.tasks.TasksScopes
import com.todoroo.astrid.gtasks.api.GtasksInvoker
import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.DebugNetworkInterceptor
import org.tasks.R
import org.tasks.drive.DriveInvoker
import org.tasks.gtasks.GoogleAccountManager
@ -17,23 +16,18 @@ class InvokerFactory @Inject constructor(
@ApplicationContext private val context: Context,
private val googleAccountManager: GoogleAccountManager,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor
) {
fun getDriveInvoker() = DriveInvoker(
context,
preferences,
HttpCredentialsAdapter(
googleAccountManager,
preferences.getStringValue(R.string.p_google_drive_backup_account) ?: "",
DriveScopes.DRIVE_FILE
),
interceptor
)
fun getGtasksInvoker(account: String) = GtasksInvoker(
HttpCredentialsAdapter(googleAccountManager, account, TasksScopes.TASKS),
preferences,
interceptor
)
}

@ -23,11 +23,9 @@ import net.openid.appauth.AuthState
import okhttp3.OkHttpClient
import okhttp3.internal.tls.OkHostnameVerifier
import org.tasks.BuildConfig
import org.tasks.DebugNetworkInterceptor
import org.tasks.caldav.TasksCookieJar
import org.tasks.data.entity.CaldavAccount
import org.tasks.extensions.Context.cookiePersistor
import org.tasks.preferences.Preferences
import org.tasks.security.KeyStoreEncryption
import org.tasks.sync.microsoft.MicrosoftService
import org.tasks.sync.microsoft.requestTokenRefresh
@ -37,8 +35,6 @@ import javax.net.ssl.SSLContext
class HttpClientFactory @Inject constructor(
@ApplicationContext private val context: Context,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
private val encryption: KeyStoreEncryption,
) {
suspend fun newClient(foreground: Boolean) = newClient(
@ -85,9 +81,6 @@ class HttpClientFactory @Inject constructor(
block(builder)
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
return builder.build()
}

@ -12,26 +12,19 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient
import okhttp3.Request
import org.tasks.DebugNetworkInterceptor
import org.tasks.R
import org.tasks.data.entity.Place
import org.tasks.preferences.Preferences
import java.io.IOException
import javax.inject.Inject
class GeocoderMapbox @Inject constructor(
@ApplicationContext context: Context,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
) : Geocoder {
private val token = context.getString(R.string.mapbox_key)
override suspend fun reverseGeocode(mapPosition: MapPosition): Place? =
withContext(Dispatchers.IO) {
val builder = OkHttpClient().newBuilder()
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
val client = builder.build()
val url = "https://api.mapbox.com/geocoding/v5/mapbox.places/${mapPosition.longitude},${mapPosition.latitude}.json?access_token=$token"
val response = client.newCall(Request.Builder().get().url(url).build()).execute()

@ -11,18 +11,14 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient
import okhttp3.Request
import org.tasks.DebugNetworkInterceptor
import org.tasks.R
import org.tasks.data.entity.Place
import org.tasks.location.GeocoderMapbox.Companion.toPlace
import org.tasks.preferences.Preferences
import java.io.IOException
import javax.inject.Inject
class PlaceSearchMapbox @Inject constructor(
@ApplicationContext context: Context,
private val preferences: Preferences,
private val interceptor: DebugNetworkInterceptor,
) : PlaceSearch {
val token = context.getString(R.string.mapbox_key)
@ -35,9 +31,6 @@ class PlaceSearchMapbox @Inject constructor(
override suspend fun search(query: String, bias: MapPosition?): List<PlaceSearchResult> =
withContext(Dispatchers.IO) {
val builder = OkHttpClient().newBuilder()
if (preferences.isFlipperEnabled) {
interceptor.apply(builder)
}
val proximity = bias?.let {
"&proximity=${bias.longitude},${bias.latitude}"
}

@ -489,9 +489,6 @@ class Preferences @JvmOverloads constructor(
fun <T> getPrefs(c: Class<T>): Map<String, T> =
prefs.all.filter { (_, value) -> c.isInstance(value) } as Map<String, T>
val isFlipperEnabled: Boolean
get() = BuildConfig.DEBUG && getBoolean(R.string.p_flipper, false)
var isPositionHackEnabled: Boolean
get() = getLong(R.string.p_google_tasks_position_hack, 0) > currentTimeMillis() - ONE_WEEK
set(value) { setLong(R.string.p_google_tasks_position_hack, if (value) currentTimeMillis() else 0) }

@ -370,7 +370,6 @@
<string name="p_strict_mode_vm">strict_mode_vm</string>
<string name="p_strict_mode_thread">strict_mode_thread</string>
<string name="p_leakcanary">p_leakcanary</string>
<string name="p_flipper">p_flipper</string>
<string name="p_debug_pro">debug_pro</string>
<string name="p_crash_main_queries">debug_crash_main_queries</string>
<string name="p_sync_ongoing">sync_ongoing</string>

@ -1,12 +0,0 @@
package org.tasks
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpResponse
import okhttp3.OkHttpClient
import javax.inject.Inject
class DebugNetworkInterceptor @Inject constructor() {
fun apply(builder: OkHttpClient.Builder?) {}
fun <T> execute(httpRequest: HttpRequest?, responseClass: Class<T>?): T? = null
fun <T> report(httpResponse: HttpResponse?, responseClass: Class<T>?, start: Long, finish: Long): T? = null
}

@ -20,7 +20,6 @@ desugar_jdk_libs = "2.1.3"
etebase = "2.3.2"
firebase = "33.8.0"
firebase-crashlytics-gradle = "3.0.2"
flipper = "0.273.0"
google-oauth2 = "1.30.1"
google-api-drive = "v3-rev20250122-2.0.0"
google-api-tasks = "v1-rev20250105-2.0.0"
@ -58,7 +57,6 @@ recyclerview = "1.4.0"
rfc5545-datetime = "0.2.4"
room = "2.7.0-alpha13"
shortcut-badger = "1.1.22"
soloader = "0.12.1"
timber = "5.0.1"
swiperefreshlayout = "1.1.0"
work = "2.10.0"
@ -116,9 +114,6 @@ dmfs-opentasks-provider = { module = "com.github.tasks.opentasks:opentasks-provi
dmfs-recur = { module = "org.dmfs:lib-recur", version.ref = "lib-recur" }
dmfs-rfc5545-datetime = { module = "org.dmfs:rfc5545-datetime", version.ref = "rfc5545-datetime" }
etebase = { module = "com.etebase:client", version.ref = "etebase" }
facebook-flipper = { module = "com.facebook.flipper:flipper", version.ref = "flipper" }
facebook-flipper-network = { module = "com.facebook.flipper:flipper-network-plugin", version.ref = "flipper" }
facebook-soloader = { module = "com.facebook.soloader:soloader", version.ref = "soloader" }
firebase = { module = "com.google.firebase:firebase-bom", version.ref = "firebase" }
firebase-config-ktx = { module = "com.google.firebase:firebase-config-ktx" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" }

Loading…
Cancel
Save