GithubHelp home page GithubHelp logo

chuckerteam / chucker Goto Github PK

View Code? Open in Web Editor NEW
3.8K 3.8K 334.0 36.83 MB

๐Ÿ”Ž An HTTP inspector for Android & OkHTTP (like Charles but on device)

License: Apache License 2.0

Kotlin 99.66% Shell 0.34%
android android-library android-sdk hacktoberfest http-requests interceptor kotlin kotlin-library library network-analysis network-monitoring okhttp okhttp-client okhttp-interceptor okhttp3 okhttp3-integration okhttp3-util okhttpclient okhttputils proxy

chucker's Introduction

Chucker

Maven Central Pre Merge Checks License PRs Welcome Join the chat at https://kotlinlang.slack.com Android Weekly

A fork of Chuck

chucker icon

Chucker simplifies the inspection of HTTP(S) requests/responses fired by your Android App. Chucker works as an OkHttp Interceptor persisting all those events inside your application, and providing a UI for inspecting and sharing their content.

Apps using Chucker will display a notification showing a summary of ongoing HTTP activity. Tapping on the notification launches the full Chucker UI. Apps can optionally suppress the notification, and launch the Chucker UI directly from within their own interface.

chucker http sample

Getting Started ๐Ÿ‘ฃ

Chucker is distributed through Maven Central. To use it you need to add the following Gradle dependency to the build.gradle file of your android app module (NOT the root file).

Please note that you should add both the library and the library-no-op variant to isolate Chucker from release builds as follows:

dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:4.0.0"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:4.0.0"
}

To start using Chucker, just plug in a new ChuckerInterceptor to your OkHttp Client Builder:

val client = OkHttpClient.Builder()
                .addInterceptor(ChuckerInterceptor(context))
                .build()

That's it! ๐ŸŽ‰ Chucker will now record all HTTP interactions made by your OkHttp client.

Historically, Chucker was distributed through JitPack. You can find older version of Chucker here: JitPack.

Features ๐Ÿงฐ

Don't forget to check the changelog to have a look at all the changes in the latest version of Chucker.

  • Compatible with OkHTTP 4
  • API >= 21 compatible
  • Easy to integrate (just 2 gradle implementation lines).
  • Works out of the box, no customization needed.
  • Empty release artifact ๐Ÿงผ (no traces of Chucker in your final APK).
  • Support for body text search with highlighting ๐Ÿ•ต๏ธโ€โ™‚๏ธ
  • Support for showing images in HTTP Responses ๐Ÿ–ผ
  • Support for custom decoding of HTTP bodies

Multi-Window ๐Ÿšช

The main Chucker activity is launched in its own task, allowing it to be displayed alongside the host app UI using Android 7.x multi-window support.

Multi-Window

Configure ๐ŸŽจ

You can customize chucker providing an instance of a ChuckerCollector:

// Create the Collector
val chuckerCollector = ChuckerCollector(
        context = this,
        // Toggles visibility of the notification
        showNotification = true,
        // Allows to customize the retention period of collected data
        retentionPeriod = RetentionManager.Period.ONE_HOUR
)

// Create the Interceptor
val chuckerInterceptor = ChuckerInterceptor.Builder(context)
        // The previously created Collector
        .collector(chuckerCollector)
        // The max body content length in bytes, after this responses will be truncated.
        .maxContentLength(250_000L)
        // List of headers to replace with ** in the Chucker UI
        .redactHeaders("Auth-Token", "Bearer")
        // Read the whole response body even when the client does not consume the response completely.
        // This is useful in case of parsing errors or when the response body
        // is closed before being read like in Retrofit with Void and Unit types.
        .alwaysReadResponseBody(true)
        // Use decoder when processing request and response bodies. When multiple decoders are installed they
        // are applied in an order they were added.
        .addBodyDecoder(decoder)
        // Controls Android shortcut creation.
        .createShortcut(true)
        .build()

// Don't forget to plug the ChuckerInterceptor inside the OkHttpClient
val client = OkHttpClient.Builder()
        .addInterceptor(chuckerInterceptor)
        .build()

Redact-Header ๐Ÿ‘ฎโ€โ™‚๏ธ

Warning The data generated and stored when using Chucker may contain sensitive information such as Authorization or Cookie headers, and the contents of request and response bodies.

It is intended for use during development, and not in release builds or other production deployments.

You can redact headers that contain sensitive information by calling redactHeader(String) on the ChuckerInterceptor.

interceptor.redactHeader("Auth-Token", "User-Session");

Decode-Body ๐Ÿ“–

Chucker by default handles only plain text, Gzip compressed or Brotli compressed. If you use a binary format like, for example, Protobuf or Thrift it won't be automatically handled by Chucker. You can, however, install a custom decoder that is capable of reading data from different encodings.

object ProtoDecoder : BodyDecoder {
    fun decodeRequest(request: Request, body: ByteString): String? = if (request.isExpectedProtoRequest) {
        decodeProtoBody(body)
    } else {
        null
    }

    fun decodeResponse(request: Response, body: ByteString): String? = if (request.isExpectedProtoResponse) {
        decodeProtoBody(body)
    } else {
        null
    }
}
interceptorBuilder.addBodyDecoder(ProtoDecoder).build()

Notification Permission ๐Ÿ””

Starting with Android 13, your apps needs to request the android.permission.POST_NOTIFICATIONS permission to the user in order to show notifications. As Chucker also shows notifications to show network activity you need to handle permission request depending on your app features. Without this permission Chucker will track network activity, but there will be no notifications on devices with Android 13 and newer.

There are 2 possible cases:

  1. If your app is already sending notifications, you don't need to do anything as Chucker will show a notification as soon as the android.permission.POST_NOTIFICATIONS permission is granted to your app.
  2. If your app does not send notifications you would need to open Chucker directly (can be done via shortcut, which is added to your app by default when Chucker is added) and click Allow in the dialog with permission request. In case you don't allow this permission or dismiss that dialog by mistake, on every Chucker launch there will be a snackbar with a button to open your app settings where you can change permissions settings. Note, you need to grant android.permission.POST_NOTIFICATIONS to your app in Settings as there will be no separate app in Apps list in Settings.

Migrating ๐Ÿš—

If you're migrating from Chuck to Chucker, please refer to this migration guide.

If you're migrating from Chucker v2.0 to v3.0, please expect multiple breaking changes. You can find documentation on how to update your code on this other migration guide.

Snapshots ๐Ÿ“ฆ

Development of Chucker happens in the main branch. Every push to main will trigger a publishing of a SNAPSHOT artifact for the upcoming version. You can get those snapshots artifacts directly from Sonatype with:

repositories {
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:4.1.0-SNAPSHOT"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:4.1.0-SNAPSHOT"
}

Moreover, you can still use JitPack as it builds every branch. So the top of main is available here:

repositories {
    maven { url "https://jitpack.io" }
}
dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:main-SNAPSHOT"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:main-SNAPSHOT"
}

โš ๏ธ Please note that the latest snapshot might be unstable. Use it at your own risk โš ๏ธ

If you're looking for the latest stable version, you can always find it in Releases section.

FAQ โ“

  • Why are some of my request headers (e.g. Content-Encoding or Accept-Encoding) missing?
  • Why are retries and redirects not being captured discretely?
  • Why are my encoded request/response bodies not appearing as plain text?

Please refer to this section of the OkHttp documentation. You can choose to use Chucker as either an application or network interceptor, depending on your requirements.

  • Why Android < 21 is no longer supported?

In order to keep up with the changes in OkHttp we decided to bump its version in 4.x release. Chucker 3.5.x supports Android 16+ but its active development stopped and only bug fixes and minor improvements will land on 3.x branch till March 2021.

Sponsors ๐Ÿ’ธ

Chucker is maintained and improved during nights, weekends and whenever team has free time. If you use Chucker in your project, please consider sponsoring us. This will help us buy a domain for a website we will have soon and also spend some money on charity. Additionally, sponsorship will also help us understand better how valuable Chucker is for people's everyday work.

You can sponsor us by clicking Sponsor button.

Contributing ๐Ÿค

We're offering support for Chucker on the #chucker channel on kotlinlang.slack.com. Come and join the conversation over there.

We're looking for contributors! Don't be shy. ๐Ÿ˜ Feel free to open issues/pull requests to help us improve this project.

  • When reporting a new Issue, make sure to attach Screenshots, Videos or GIFs of the problem you are reporting.
  • When submitting a new PR, make sure tests are all green. Write new tests if necessary.

Short TODO List for new contributors:

Building ๐Ÿ› 

In order to start working on Chucker, you need to fork the project and open it in Android Studio/IntelliJ IDEA.

Before committing we suggest you install the pre-commit hooks with the following command:

./gradlew installGitHook

This will make sure your code is validated against KtLint and Detekt before every commit. The command will run automatically before the clean task, so you should have the pre-commit hook installed by then.

Before submitting a PR please run:

./gradlew build

This will build the library and will run all the verification tasks (ktlint, detekt, lint, unit tests) locally. This will make sure your CI checks will pass.

Acknowledgments ๐ŸŒธ

Maintainers

Chucker is currently developed and maintained by the ChuckerTeam. When submitting a new PR, please ping one of:

Thanks

Big thanks to our contributors โค๏ธ

Libraries

Chucker uses the following open source libraries:

  • OkHttp - Copyright Square, Inc.
  • Gson - Copyright Google Inc.
  • Room - Copyright Google Inc.

License ๐Ÿ“„

    Copyright (C) 2018-2021 Chucker Team.
    Copyright (C) 2017 Jeff Gilfelt.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

chucker's People

Contributors

4shutosh avatar abhishek4uh avatar adammasyk avatar adb-shell avatar alorma avatar arjansm avatar bluestormdna avatar cortinico avatar dependabot[bot] avatar eschlenz avatar goooler avatar handstandsam avatar hitanshu-dhawan avatar jaynewstrom avatar jgilfelt avatar jonathan-caryl avatar kmayoral avatar koral-- avatar misikora avatar olivierperez avatar paulwoitaschek avatar peter-tackage avatar psh avatar rakshit444 avatar redwarp avatar simonmarquis avatar technoir42 avatar uoooo avatar vbuberen avatar yoavst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chucker's Issues

Optional JSON formatting support

Pretty sure Chuck did formatted JSON output but Chucker appears to be a compact format sans any white space / line feeds. Makes the output much harder to read.

Would love to have the option to show RESPONSE area pretty printed. Seems maybe it is pretty printed for small payloads and not for larger ones (could be the way our server sends it as well).

App crashing when trying to open request details

Describe the bug
I'm able to see the list of made requests, when I try to open the request details to see respons / headers etc.. Chucker will creash.

Crash Log

2019-09-29 13:20:14.457 30344-30344/com.myspringring E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myspringring, PID: 30344
    java.lang.RuntimeException: Unable to resume activity {com.myspringring/com.chuckerteam.chucker.api.internal.ui.transaction.TransactionActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window android.app.Activity.getWindow()' on a null object reference
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3429)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3469)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window android.app.Activity.getWindow()' on a null object reference
        at androidx.core.app.ComponentActivity.dispatchKeyShortcutEvent(ComponentActivity.java:85)
        at androidx.lifecycle.LiveData.observe(LiveData.java:172)
        at com.chuckerteam.chucker.api.internal.ui.transaction.TransactionActivity.onResume(TransactionActivity.java:89)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
        at android.app.Activity.performResume(Activity.java:6783)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3406)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3469)ย 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)ย 
        at android.app.ActivityThread.-wrap12(ActivityThread.java)ย 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)ย 
        at android.os.Handler.dispatchMessage(Handler.java:102)ย 
        at android.os.Looper.loop(Looper.java:154)ย 
        at android.app.ActivityThread.main(ActivityThread.java:6119)ย 
        at java.lang.reflect.Method.invoke(Native Method)ย 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)ย 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

The following code is where I initialize Chucker

public static Retrofit getRetrofit(final Context context) {

        String baseURL = getAPIBaseUrl();
        Retrofit.Builder retrofitBuilder;
        OkHttpClient.Builder builder = null;

        // Define the interceptor, add authentication headers
        Interceptor interceptor = new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {

                // TODO improve this
                if (!GlobalUtils.checkForInternetConnection(context, TAG)) {
                        //logThis(TAG, "No Internet Connection", null);
                    throw new NoConnectivityException(context);
                }

                Request newRequest = chain.request().newBuilder()
                        /**
                        Headers
                        **/
                return chain.proceed(newRequest);
            }
        };

        // Add the interceptor to OkHttpClient
        builder = new OkHttpClient.Builder();
        builder.connectTimeout((int) Global.getFirebaseRemoteConfigValue(context, Integer.class, Firebase.API_TIMEOUT_SHORT.toString(), 0), TimeUnit.SECONDS); // connect timeout
        builder.readTimeout((int) Global.getFirebaseRemoteConfigValue(context, Integer.class, Firebase.API_TIMEOUT_LONG.toString(), 0), TimeUnit.SECONDS); // write timeout
        builder.writeTimeout((int) Global.getFirebaseRemoteConfigValue(context, Integer.class, Firebase.API_TIMEOUT_LONG.toString(), 0), TimeUnit.SECONDS); // read timeout
        builder.interceptors().add(interceptor);

        // Add chuck interceptor
        builder.addInterceptor(new ChuckerInterceptor(context));

        if (isDebug()) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
        }

        // Set the custom client when building adapter
        retrofitBuilder = new Retrofit.Builder()
                .baseUrl(baseURL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(builder.build());

        return retrofitBuilder.build();
    }

More than one file was found with OS independent path 'META-INF/library_release.kotlin_module'

Hi, when I add the library to the app/build.gradle file:

debugImplementation "com.github.ChuckerTeam.Chucker:library:3.0.1"
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1"

I get the following build error:

Execution failed for task ':app:mergeDebugJavaResource'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > More than one file was found with OS independent path 'META-INF/library_release.kotlin_module'

Indeed, I have 2 libraries with this file, one of them is chucker:

Captura de Pantalla 2019-10-10 a les 12 58 32

There is a way to fix this with packagingOptions:

packagingOptions {
    exclude 'META-INF/library_release.kotlin_module'
}

However it seems that the root cause can be solved on the library, which is better because it avoids having everyone to add the exclude fix:

Takhion/android-extras-delegates#1
kosi-libs/Kodein#138

Would be nice if this was fixed at the library :)

Chucker is crashing opening responses with big bodies

Describe the bug

I do have an app that is calling an endpoint that returns a JSON Body of nearly 700kb.
Chucker is blocking the UI thread trying to parse the body and is causing an ANR/Crash if trying to inspect the response body.

To Reproduce

  1. Use Chucker to call an endpoint with a big response
  2. Click on the Chucker Push notification
  3. Open the HTTP Request from the list
  4. Click on the "Response" tab

Expected behavior
The tab should open immediately

Actual behavior
The Chucker UI is completely frozen and eventually crashes

Smartphone

  • Emulator - Nexus 5X
  • OS: API27
  • Lib version: 3.0.0-alpha1

Configure notification priority

Hi, I would love to have a way to set Chuck's notification priority to NotificationCompat.PRIORITY_MIN (https://stackoverflow.com/a/16999675) so that Android can hide it from the status bar (it gets pretty annoying otherwise, for someone using a debug app all day :)).

Let me know if this sounds good. I can take a shot at this, this weekend.

"Share as text" > Slack does not work

Trying to share these responses through the Slack android app fails because it pastes into the "Title" field in slack.

If you open up chrome, select any text, and share through slack, you can see that the "Title" field does not even show up in Slack and instead it pastes the output into the message field, so it seems like this isn't something necessarily wrong with the Slack app as other apps can share correctly into it.

Edit: Occurs in latest stable and beta

Chucker doesn't show explicit nulls

Chucker omits null values when they are set explicitly.

Here is my retrofit service:

interface MyService {
    //JSON:
    //    {
    //        "person": "Hi Chucker"
    //    }
    @GET("5d4d9ebf3300003e3a33792e?mocky-delay=1000ms")
    fun getPersonValid(): Call<Person>

    //JSON:
    //    {
    //
    //    }
    @GET("5d4d9f4f330000254b337934?mocky-delay=1000ms")
    fun getPersonMissing(): Call<Person>

    //JSON:
    //    {
    //        "person": null
    //    }
    @GET("5d4da01d3300004b4433793d?mocky-delay=1000ms")
    fun getPersonExplicitNull(): Call<Person>
}

I would expect the json in chucker to match the JSON outlined in the comments. But when a person is sent back from the server that is explicitly null, it just shows an {} which is misleading.

Chucker Push Notification is wrongly reporting the first HTTP request twice

Describe the bug
Looks like the first HttpTransaction of a session is reported twice on the Push Notification (only). Opening Chucker shows the correct number of transactions.

To Reproduce
Steps to reproduce the behavior:

  1. Edit MainActivity.kt to make sure only one request is fired
  2. Trigger the network request
  3. Open the push notification
  4. Verify that the same network request is reported twice

Expected behavior
Network request should be reported only once in the push notification

Screenshots
May-16-2019 12-26-14

Smartphone

  • Lib version: develop-SNAPSHOT

IllegalStateException: You can't access the transaction repository if you don't initialize it!

Describe the bug

    java.lang.IllegalStateException: You can't access the transaction repository if you don't initialize it!
        at com.chuckerteam.chucker.api.internal.data.repository.RepositoryProvider.transaction(RepositoryProvider.kt:16)
        at com.chuckerteam.chucker.api.internal.ui.transaction.TransactionListFragment.getDataSource(TransactionListFragment.java:136)
        at com.chuckerteam.chucker.api.internal.ui.transaction.TransactionListFragment.onAttach(TransactionListFragment.java:81)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1404)
        at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1195)
        at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1078)
        at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:117)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2408)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
        at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2243)
        at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:654)
        at androidx.fragment.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:146)

To Reproduce

  1. Invoke context.startActivity(Chucker.getLaunchIntent(context, Chucker.SCREEN_HTTP)) where context is valid activity Context.
    There is no HTTP(S) traffic logged before the invocation.

Sample project:
https://github.com/DroidsOnRoids/FoQA
Use Chucker Hyperion menu option to reproduce this issue.

Expected behavior
There should be no crash.

Smartphone

  • Device: does not matter but e.g. emulator
  • OS: does not matter but e.g. 5.0
  • Lib version: 3.0.0-alpha2

Provide an option to remove "errors" tab

I use a few other crash reporters and crash viewers built into my application. The fact that Chucker added this onto Chuck is nice, but I want to get rid of it so my team doesn't get confused about whether or not we should be using it vs our other error reporters. During Chucker setup, it'd be nice to just opt-out of having the error feature showing/working.

crash when try to visit a request record detail

Describe the bug
A clear and concise description of what the bug is.

To Reproduce

  1. upload an image with okhttp
  2. launch chucker from notification
  3. crash when click request record which I just upload

Smartphone

  • Device: [xiaomi mix 2s]
  • OS: [8.0.0]
  • Lib version: [e.g. 2.0.3]

Additional context
05-19 00:16:05.934 24324 24324 E AndroidRuntime: FATAL EXCEPTION: main
05-19 00:16:05.934 24324 24324 E AndroidRuntime: Process: com.android.expro, PID: 24324
05-19 00:16:05.934 24324 24324 E AndroidRuntime: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.database.AbstractCursor.checkPosition(AbstractCursor.java:466)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.database.AbstractWindowedCursor.isNull(AbstractWindowedCursor.java:92)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.database.CursorWrapper.isNull(CursorWrapper.java:182)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.database.CursorWrapper.isNull(CursorWrapper.java:182)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at nl.qbusict.cupboard.PreferredColumnOrderCursorWrapper.isNull(PreferredColumnOrderCursorWrapper.java:147)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at nl.qbusict.cupboard.convert.ReflectiveEntityConverter.fromCursor(ReflectiveEntityConverter.java:172)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at nl.qbusict.cupboard.QueryResultIterable$QueryResultIterator.next(QueryResultIterable.java:135)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at nl.qbusict.cupboard.QueryResultIterable.get(QueryResultIterable.java:67)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at nl.qbusict.cupboard.CursorCompartment.get(CursorCompartment.java:67)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at com.readystatesoftware.chuck.internal.ui.transaction.TransactionActivity.onLoadFinished(TransactionActivity.java:131)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at com.readystatesoftware.chuck.internal.ui.transaction.TransactionActivity.onLoadFinished(TransactionActivity.java:54)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.app.LoaderManagerImpl$LoaderObserver.onChanged(LoaderManagerImpl.java:250)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.arch.lifecycle.LiveData.considerNotify(LiveData.java:109)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.arch.lifecycle.LiveData.dispatchingValue(LiveData.java:126)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.arch.lifecycle.LiveData.setValue(LiveData.java:282)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.arch.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.app.LoaderManagerImpl$LoaderInfo.setValue(LoaderManagerImpl.java:189)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManagerImpl.java:174)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.Loader.deliverResult(Loader.java:132)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:109)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:41)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:258)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:83)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:490)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:507)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:105)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.os.Looper.loop(Looper.java:176)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6701)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:249)
05-19 00:16:05.934 24324 24324 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)

Multipart upload fail when using on Fast Android Networking

I used ChuckInterceptor on FAN and can't upload file via multipart.

    val okHttpClient = OkHttpClient().newBuilder()
            .connectTimeout(120, TimeUnit.SECONDS)
            .readTimeout(120, TimeUnit.SECONDS)
            .addInterceptor(ChuckerInterceptor(this))
            .writeTimeout(120, TimeUnit.SECONDS)
            .build()

    AndroidNetworking.initialize(applicationContext, okHttpClient)

Remove Interceptor is worked fine.

Better RTL support

Is your feature request related to a problem? Please describe.
It would be nicer if Chucker could have a better support for RTL devices.

Describe the solution you'd like
ViewPager works the opposite way on RTL layout and some texts are overlapping each other.

Describe alternatives you've considered
Better RTL support.

Additional context
Screenshot_1568793405
Screenshot_1568793426

Do you want to develop this feature yourself?
No unfortunately.

Chucker crash opening responses

Describe the bug
When opening Chucker in device and clicking to see the description of an Http Request, it crashes

To Reproduce
Steps to reproduce the behavior:

  1. Go to Chucker
  2. Click on an HttpRequest
  3. Appli crashes :
    java.lang.IncompatibleClassChangeError: Class 'com.chuckerteam.chucker.api.internal.ui.transaction.TransactionActivity' does not implement interface 'androidx.lifecycle.LifecycleOwner' in call to 'androidx.lifecycle.Lifecycle androidx.lifecycle.LifecycleOwner.getLifecycle()' (declaration of 'androidx.lifecycle.LiveData' appears in /data/app/xxx.debug-re4vlTGo19DGjF2gM0nfUw==/split_lib_dependencies_apk.apk)
    at androidx.lifecycle.LiveData.observe(LiveData.java:172)
    at com.chuckerteam.chucker.api.internal.ui.transaction.TransactionActivity.onResume(TransactionActivity.java:88)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1355)
    at android.app.Activity.performResume(Activity.java:7117)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862)
    at android.app.ActivityThread.-wrap11(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Smartphone

  • Device: Nexus 5X
  • OS: Android 9
  • Lib version: 3.0.0-alpha1

what if logic in intercept() throws an exception?

it's actually a question than a bug.

intercept() method does not have try/catch for logics other than network request itself.

if your logic throws some exception, the network request/response would fail to be passed to their downstream operators.

am i understanding correctly?

Crash when opening from notification after app is closed

Describe the bug
When tapping the clear / notification item to clear / open the chucker activity, it crashses instead.

To Reproduce
Steps to reproduce the behavior:

  1. Do anything to show the chucker notification
  2. Kill the app, chucker notification still persists
  3. Tap clear button / the notification itself
  4. Crashes

Smartphone

  • OS: 8.0.0
  • Lib version: 3.0.0-alpha2

java.lang.IllegalStateException: You can't access the transaction repository if you don't initialize it! at com.chuckerteam.chucker.api.internal.data.repository.RepositoryProvider.transaction(RepositoryProvider.kt:16) at com.chuckerteam.chucker.api.internal.support.ClearTransactionsService.onHandleIntent(ClearTransactionsService.java:25) at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:68) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:169) at android.os.HandlerThread.run(HandlerThread.java:65)


java.lang.IllegalStateException: You can't access the transaction repository if you don't initialize it! at com.chuckerteam.chucker.api.internal.data.repository.RepositoryProvider.transaction(RepositoryProvider.kt:16) at com.chuckerteam.chucker.api.internal.ui.transaction.TransactionListFragment.getDataSource(TransactionListFragment.java:136) at com.chuckerteam.chucker.api.internal.ui.transaction.TransactionListFragment.onAttach(TransactionListFragment.java:81) at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1404) at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1195)

Crash when chucker is used with proguard enabled.

Chucker is crashing with these crash logs when clicked on the notification. It is working fine in the debug build when proguard is not enabled but crashing when the proguard is enabled.

2019-11-26 17:39:06.222 18381-18381/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.gojek.driver.bike.staging, PID: 18381
android.view.InflateException: Binary XML file line #17: Binary XML file line #17: Error inflating class
Caused by: android.view.InflateException: Binary XML file line #17: Error inflating class
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:647)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at dark.ฦ—ลฟ.onCreateView(:65)
at dark.ฮนสŸ.performCreateView(:2439)
at dark.ะ†ษน.หŠ(:1460)
at dark.ะ†ษน.เฅฑเฅฑ(:1784)
at dark.ะ†ษน.เฅฑ(:1852)
at dark.ฯ™.เฅฑเฅฑ(:802)
at dark.ะ†ษน.ห‹(:2625)
at dark.ะ†ษน.หŠ(:2411)
at dark.ะ†ษน.ห‹(:2366)
at dark.ะ†ษน.ห(:2243)
at dark.ฯ™.สผ(:654)
at dark.ั–ษน.finishUpdate(:146)
at dark.ษจำ.หŠ(:1244)
at dark.ษจำ.ห(:1092)
at dark.ษจำ.onMeasure(:1622)
at android.view.View.measure(View.java:23355)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
at android.view.View.measure(View.java:23355)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at dark.ษฉฤฑ.onMeasure(:143)
at android.view.View.measure(View.java:23355)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
at android.view.View.measure(View.java:23355)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:23355)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
at android.view.View.measure(View.java:23355)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:717)
at android.view.View.measure(View.java:23355)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2919)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1749)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2042)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1637)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7797)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1172)
at android.view.Choreographer.doCallbacks(Choreographer.java:984)
at android.view.Choreographer.doFrame(Choreographer.java:809)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1158)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-11-26 17:39:06.222 18381-18381/? E/AndroidRuntime: Caused by: java.lang.IllegalStateException: Binary XML file line #17: Unable to find LayoutManager dark.LinearLayoutManager
at dark.ฮนษ.หŠ(:810)
at dark.ฮนษ.(:713)
at dark.ฮนษ.(:647)
... 65 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "dark.LinearLayoutManager" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.gojek.driver.bike.staging-QEokmeEQhz6U6wW5zueoIg==/base.apk"],nativeLibraryDirectories=[/data/app/com.gojek.driver.bike.staging-QEokmeEQhz6U6wW5zueoIg==/lib/arm64, /data/app/com.gojek.driver.bike.staging-QEokmeEQhz6U6wW5zueoIg==/base.apk!/lib/arm64-v8a, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at dark.ฮนษ.หŠ(:791)
... 67 more

Update to androidx?

I notice that you have an 'updated-deps' branch out there, and there's a general move toward modernizing the codebase with Kotlin. How do you feel about moving over to using Android Jetpack androidx for AppCompatActivity, Fragments, etc?

Do you want to develop this feature yourself?
Happy to, yes.

Crash after migrating from Chuck

Describe the bug
Update dependency from Chuck to Chucker, the database is not updated. So the RecordedThrowable table is not created, the lib crash when trying to read/write in it.

Expected behavior
Update the database and its table when migrating to Chucker.

Provide a way to query / get logs

Is your feature request related to a problem? Please describe.
In Chuck the only way to get a log of the requests was through reflection for the Db open helper.
It would be very useful to add a way to obtain the records to export a trace

Describe the solution you'd like
Add to Chucker a method to query the logs and get a list of http or error logs.

Null pointer dereference in MainActivity.getApplicationName()

Describe the bug
The following NPE is thrown:

     Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String java.lang.CharSequence.toString()' on a null object reference
        at com.chuckerteam.chucker.api.internal.ui.MainActivity.getApplicationName(MainActivity.java:90)
        at com.chuckerteam.chucker.api.internal.ui.MainActivity.onCreate(MainActivity.java:46)
        at android.app.Activity.performCreate(Activity.java:7802)

Affected line:

return stringId == 0 ? applicationInfo.nonLocalizedLabel.toString() : getString(stringId);

invokes toString() on ApplicationInfo.nonLocalizedLabel which may me null.
Official documentation on https://developer.android.com/reference/android/content/pm/PackageItemInfo.html#nonLocalizedLabel says

The string provided in the AndroidManifest file, if any.

If there is no such string in manifest then value is null.

To Reproduce

  1. Invoke context.startActivity(Chucker.getLaunchIntent(context, Chucker.SCREEN_HTTP)) where context is valid activity Context.

Sample project:
https://github.com/DroidsOnRoids/FoQA
Use Chucker Hyperion menu option to reproduce this issue.

Expected behavior
There should be no crash.

Smartphone

  • Device: does not matter but e.g. emulator
  • OS: does not matter but e.g. 5.0
  • Lib version: 3.0.0-alpha2

[Feedback] Chucker usage with Ktor HTTP client

I spent some time learning about the Ktor HTTP client recently, porting the HttpBinClient and HttpBinApi to the Ktor HTTP client as a learning exercise for myself.

In the process I was happy to find that Chucker works perfectly with the Ktor HTTP client when configured to use the OkHttp engine -

private val httpClient = HttpClient(OkHttp) {
    install(JsonFeature) {
        serializer = GsonSerializer()
    }
    engine {
        addInterceptor(chuckerInterceptor)
        addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
        config {
            followRedirects(true)
            readTimeout(30, TimeUnit.SECONDS)
            connectTimeout(30, TimeUnit.SECONDS)
            callTimeout(30, TimeUnit.SECONDS)
        }
    }
}

๐Ÿ‘ Great work all!

request/response time formatting

The request time and response time in the overview tab is not being properly formatted

๐Ÿ”ง Expected behaviour

Previous functionality as expected from Chuck

Screenshot 2019-11-15 at 13 51 12
Screenshot 2019-11-15 at 13 52 26

Display educationnal text in Http or Error tab when they are empty.

Is your feature request related to a problem? Please describe.
Currently, when opening the Chucker activity, the HTTP and Error tab are completely blank and empty when there is no request or no error to display.

Describe the solution you'd like
Each empty tab is a wasted opportunity to educate users about how to use chucker.

  • The Http tab could display something like "This tab displays network requested recorded with the ChuckerInterceptor. Add the interceptor to your OkHttp client to reap the benefits"
  • The Error tab could display something like "This tab displays error recorded with the ChuckerCollector.onError method. Call this method when an error is thrown to check your stacktrace live"

Alternative suggestions welcome :-)

Additional context
Chucker users will probably know how to use the ChuckerInterceptor: it's well documented, the "Getting Started ๐Ÿ‘ฃ" section of the README.md describe how to use it. The Error tab is a more hidden feature (one has to read more of the readme :-P and nobody got time for that)

Do you want to develop this feature yourself?
[yes]

Hide the RetentionManager in the API?

I believe that it would be possible to hide the RetentionManager from the public API and treat it as an implementation detail, so users would only need to supply a retention period and internally the ChuckCollector manages an instance of it.

collector = ChuckCollector(this)
        .showNotification(true)
        .retentionManager(RetentionManager(this, ChuckCollector.Period.ONE_HOUR))

becoming

collector = ChuckCollector(this)
        .showNotification(true)
        .retentionPeriod(ChuckCollector.Period.ONE_HOUR)

I am assuming that you would always want to use the same context for both the collector and the retention manager. Can you imagine any circumstance where this wouldn't be the case and the exposed constructor would be useful?

Do you feel this would be a good way to evolve the API?

Do you want to develop this feature yourself?
Yes, I'd be happy to.

URL Query is populated with `null` if the query is empty

Describe the bug
Looks like the version on development right now has a bug where several paths will be displayed with a null attached at the end.

To Reproduce
Steps to reproduce the behavior:

  1. Build from development
  2. Open the Chucker Sample App
  3. Press on Do HTTP Activity
  4. See the error in the push notification

Expected behavior
The null should not be displayed in the path if the query is missing.

Screenshots
Screenshot_1554058851

Large json responses result in bad user experience

Some of the backends I work with send really large amounts of data.

Here is a sample: https://data.cityofnewyork.us/api/views/kku6-nxdu/rows.json

Moving from the request to response tab is slow, and trying to "Share as text" is also impossible. It'd be great to keep this on the roadmap for improvement.

Edit: Occurs in latest stable and beta

Edit 2: Maybe just show the first x amount of lines, but still provide a way to export or view the json as a file?

Null Pointer Exception

๐Ÿ“ข Describe the bug

App crash because null exception

๐Ÿ’ฃ Stacktrace

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.chuckerteam.chucker.api.internal.data.entity.HttpTransaction.getNotificationText()' on a null object reference
at com.chuckerteam.chucker.api.internal.support.NotificationHelper.show + 96(NotificationHelper.java:96)
at com.chuckerteam.chucker.api.ChuckerCollector.onResponseReceived$library_release + 66(ChuckerCollector.kt:66)
at com.chuckerteam.chucker.api.ChuckerInterceptor.intercept + 138(ChuckerInterceptor.kt:138)
at okhttp3.internal.http.RealInterceptorChain.proceed + 112(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed + 87(RealInterceptorChain.kt:87)
at okhttp3.logging.HttpLoggingInterceptor.intercept + 215(HttpLoggingInterceptor.kt:215)
at okhttp3.internal.http.RealInterceptorChain.proceed + 112(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed + 87(RealInterceptorChain.kt:87)
at com.happyfresh.snowflakes.hoverfly.interceptors.ClientInterceptor.intercept + 60(ClientInterceptor.kt:60)
at okhttp3.internal.http.RealInterceptorChain.proceed + 112(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed + 87(RealInterceptorChain.kt:87)
at okhttp3.RealCall.getResponseWithInterceptorChain + 184(RealCall.kt:184)
at okhttp3.RealCall$AsyncCall.run + 136(RealCall.kt:136)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1167(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 641(ThreadPoolExecutor.java:641)
at java.lang.Thread.run + 764(Thread.java:764)

๐Ÿ“ฑ Smartphone

  • Device: Nokia 6.1
  • OS: 9
  • Lib version: 3.0.1

Java compiler: failed linking references

Build failed after adding dependencies like this:

build.gradle (project)

allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://repo.eclipse.org/content/repositories/paho-snapshots/" }
        maven { url "https://jitpack.io" }
    }
}

build.gradle (app)

dependencies {
    ...
    debugImplementation "com.github.ChuckerTeam.Chucker:library:3.0.1"
    releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1"
}

Android Studio 3.5
Build #AI-191.8026.42.35.5791312, built on August 9, 2019
JRE: 1.8.0_202-release-1483-b49-5587405 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
macOS 10.14.6

rg.gradle.internal.exceptions.LocationAwareException: Execution failed for task ':app:processDebugResources'.
	at org.gradle.initialization.exception.DefaultExceptionAnalyser.transform(DefaultExceptionAnalyser.java:99)
	at org.gradle.initialization.exception.DefaultExceptionAnalyser.collectFailures(DefaultExceptionAnalyser.java:65)
	at org.gradle.initialization.exception.MultipleBuildFailuresExceptionAnalyser.transform(MultipleBuildFailuresExceptionAnalyser.java:39)
	at org.gradle.initialization.exception.StackTraceSanitizingExceptionAnalyser.transform(StackTraceSanitizingExceptionAnalyser.java:29)
	at org.gradle.initialization.DefaultGradleLauncher.finishBuild(DefaultGradleLauncher.java:174)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:165)
	at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:134)
	at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:58)
	at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:55)
	at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:82)
	at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:75)
	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:183)
	at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
	at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:75)
	at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:55)
	at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:54)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:58)
	at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
	at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:49)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:44)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:315)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:305)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:101)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:44)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:49)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:46)
	at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:78)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:46)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:59)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:36)
	at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
	at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
	at org.gradle.util.Swapper.swap(Swapper.java:38)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:81)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:processDebugResources'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:95)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:91)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:57)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:119)
	at org.gradle.api.internal.tasks.execution.ResolvePreviousStateExecuter.execute(ResolvePreviousStateExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:93)
	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:45)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:94)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:56)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:55)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:67)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:315)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:305)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:101)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:49)
	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
	... 3 more
Caused by: com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource linking failed
/Users/andrey/.gradle/caches/transforms-2/files-2.1/933dfe73c201990f7e902c4a956f1aef/res/values-v28/values-v28.xml:9:5-12:13: AAPT: error: resource android:attr/dialogCornerRadius not found.
    
/Users/andrey/Documents/StudioProjects/android-terminal-development/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values-v28/values-v28.xml:11: AAPT: error: resource android:attr/dialogCornerRadius not found.
    
/Users/andrey/.gradle/caches/transforms-2/files-2.1/54606f416f13842dfa024422a8fd0b6d/res/values/values.xml:161:5-202: AAPT: error: resource android:attr/fontVariationSettings not found.
    
/Users/andrey/.gradle/caches/transforms-2/files-2.1/54606f416f13842dfa024422a8fd0b6d/res/values/values.xml:161:5-202: AAPT: error: resource android:attr/ttcIndex not found.
    
error: failed linking references.
	at com.android.builder.internal.aapt.v2.Aapt2Exception$Companion.create(Aapt2Exception.kt:45)
	at com.android.builder.internal.aapt.v2.Aapt2Exception$Companion.create$default(Aapt2Exception.kt:39)
	at com.android.build.gradle.internal.res.Aapt2ErrorUtils.rewriteException(Aapt2ErrorUtils.kt:97)
	at com.android.build.gradle.internal.res.Aapt2ErrorUtils.rewriteLinkException(Aapt2ErrorUtils.kt:73)
	at com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask$AaptSplitInvoker.invokeAaptForSplit(LinkApplicationAndroidResourcesTask.kt:808)
	at com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask$AaptSplitInvoker.run(LinkApplicationAndroidResourcesTask.kt:669)
	at com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask.doFullTaskAction(LinkApplicationAndroidResourcesTask.kt:262)
	at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:106)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:47)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$2.run(ExecuteActionsTaskExecuter.java:284)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:273)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:258)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:67)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:145)
	at org.gradle.internal.execution.impl.steps.ExecuteStep.execute(ExecuteStep.java:49)
	at org.gradle.internal.execution.impl.steps.CancelExecutionStep.execute(CancelExecutionStep.java:34)
	at org.gradle.internal.execution.impl.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:69)
	at org.gradle.internal.execution.impl.steps.TimeoutStep.execute(TimeoutStep.java:49)
	at org.gradle.internal.execution.impl.steps.CatchExceptionStep.execute(CatchExceptionStep.java:33)
	at org.gradle.internal.execution.impl.steps.CreateOutputsStep.execute(CreateOutputsStep.java:50)
	at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:43)
	at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:29)
	at org.gradle.internal.execution.impl.steps.CacheStep.executeWithoutCache(CacheStep.java:134)
	at org.gradle.internal.execution.impl.steps.CacheStep.lambda$execute$3(CacheStep.java:83)
	at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:82)
	at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:36)
	at org.gradle.internal.execution.impl.steps.PrepareCachingStep.execute(PrepareCachingStep.java:33)
	at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:38)
	at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:23)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:89)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:52)
	at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36)
	at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:34)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:91)
	... 32 more
Caused by: com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource linking failed
/Users/andrey/Documents/StudioProjects/android-terminal-development/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values-v28/values-v28.xml:7: error: resource android:attr/dialogCornerRadius not found.
/Users/andrey/Documents/StudioProjects/android-terminal-development/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values-v28/values-v28.xml:11: error: resource android:attr/dialogCornerRadius not found.
/Users/andrey/Documents/StudioProjects/android-terminal-development/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml:4666: error: resource android:attr/fontVariationSettings not found.
/Users/andrey/Documents/StudioProjects/android-terminal-development/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml:4667: error: resource android:attr/ttcIndex not found.
error: failed linking references.

	at com.android.builder.internal.aapt.v2.Aapt2Exception$Companion.create(Aapt2Exception.kt:45)
	at com.android.builder.internal.aapt.v2.Aapt2Exception$Companion.create$default(Aapt2Exception.kt:39)
	at com.android.builder.internal.aapt.v2.Aapt2DaemonImpl.doLink(Aapt2DaemonImpl.kt:191)
	at com.android.builder.internal.aapt.v2.Aapt2Daemon.link(Aapt2Daemon.kt:103)
	at com.android.builder.internal.aapt.v2.Aapt2DaemonManager$LeasedAaptDaemon.link(Aapt2DaemonManager.kt:176)
	at com.android.builder.core.AndroidBuilder.processResources(AndroidBuilder.java:858)
	at com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask$AaptSplitInvoker.invokeAaptForSplit(LinkApplicationAndroidResourcesTask.kt:797)
	... 70 more

Add support for GraphQL

Is your feature request related to a problem? Please describe.
I donโ€™t know the details at first glance. Because every request is a POST method to /graphql

ex)

screenshot

Describe the solution you'd like
I want to change POST /graphql to used Query or Mutation name

Describe alternatives you've considered
Add processing to change the string in TransactionAdapter class when endpoint equals /graphql
If there are other good ways, please suggest ๐Ÿ™

ref: https://graphql.org/learn/serving-over-http/#uris-routes

Do you want to develop this feature yourself?
yes

Response Search Improvements

โš ๏ธ Is your feature request related to a problem? Please describe.

One related problem is that when you perform a search in the response tab, any highlighted matches will be unhighlighted as you scroll through the body of the response. Furthermore, the act of searching does not auto scroll to the first occurrence of the search result as I would expect.

๐ŸŽฏ Describe the solution you'd like

I propose the following:

  • As you type a search query, the body should auto scroll to the first occurrence of the search term
  • Proper highlighting be maintained for search results as you scroll through the body of the response
  • Additional search controls be introduced to allow for navigating between next and previous search results with additional meta data displaying the current visited search result index and the total count of search results shown.

๐Ÿ“Š Describe alternatives you've considered

No other alternatives considered at this time

๐Ÿ“„ Additional context

Thanks for a great product and for your consideration of this request.

๐Ÿ“ Do you want to develop this feature yourself?

  • Yes
  • No

LeakCanary reports a leak

Describe the bug
LeakCanary reports a leak of MainActivity. I've been able to reproduce it in my own application and in the sample app. It doesn't matter if there are captured network requests or not.

To Reproduce
Steps to reproduce the behavior using the sample app:

  1. Go to 'LAUNCH CHUCKER DIRECTLY'
  2. Click on 'Back Button'
  3. See error either in logcat or in LeakCanary UI

Screenshots
LeakCanary result in logcat:

โ”ฌ
โ”œโ”€ android.app.Activity$1
โ”‚    Leaking: UNKNOWN
โ”‚    Anonymous subclass of android.app.IRequestFinishCallback$Stub
โ”‚    GC Root: Global variable in native code
โ”‚    โ†“ Activity$1.this$0
โ”‚                 ~~~~~~
โ•ฐโ†’ com.chuckerteam.chucker.api.internal.ui.MainActivity
โ€‹     Leaking: YES (Activity#mDestroyed is true and ObjectWatcher was watching this)
โ€‹     key = 3d3901ea-a7b9-47fa-ba5a-566d1ede5924
โ€‹     watchDurationMillis = 5185
โ€‹     retainedDurationMillis = 178
, retainedHeapByteSize=165749)], libraryLeaks=[])

Smartphone

  • Device: Pixel 3XL
  • OS: Android Q Beta6
  • Lib version: 3.0.1 and develop branch

Additional context
I haven't being able to reproduce it in other android versions. I suppose this is happening due to Android Q but I don't know if it's a false positive from LeakCanary or not. I've attached the memory dump from LeakCanary

2019-08-23_10-25-44_445.hprof.zip

Fetch Chucker

Hi
I added chucker to project but i get chuck
How am I fix it?

image

Additional GraphQL Support

Is your feature request related to a problem? Please describe.
PR #70 (relating to issue #69) adds support for GraphQL by detecting an operation name field in the request. I believe that there are additional nuances to GraphQL we should address before calling our support "complete"

  • Reading through Serving over HTTP it appears as though we would be missing GraphQL icons on valid outgoing requests as "operation name" is optional. This was the case when I ran the code against my team's soon-to-be-released app.
  • We have the opportunity to parse the "variables" collection to give users a more full-featured summary of the request; perhaps we could tweak the "request" tab to be more GraphQL specific (including operation name, variables and query) in the cases where we detect it's needed.
  • Reading through The Anatomy of a GraphQL Query we could probably detect the operation type (query, mutation, or subscription) without too much effort.

Additional context
PR #70 attempts to parse plain text requests to detect a operationName field and if present, the GUI receives the GraphQL icon. It looks like there are several cases where an operationName will be absent, but we would want to include the icon.

  • a GET request like http://myapi/graphql?query={me{name}} is valid GraphQL
  • the operation name would only appear in a GET when there are multiple operations

    If the query contains several named operations, an operationName query parameter can be used to control which one should be executed

  • for a POST

    If the "query" query string parameter is present (as in the GET example above), it should be parsed and handled in the same way as the HTTP GET case.

  • also, we should be sensitive to the content type and only use GSON if it is "application/json"

    If the "application/graphql" Content-Type header is present, treat the HTTP POST body contents as the GraphQL query string.

Describe the solution you'd like
GraphQL (like SOAP before it) exposes a single HTTP endpoint, perhaps we could register that with the ChuckerInterceptor and avoid introspecting the request looking for an operation name?

Also, we parse the request with GSON for all outgoing network calls, in-line with the actual network call. Knowing that a particular URL is a non-GraphQL endpoint would allow us to skip this step. Perhaps we could defer this work to the HttpTransactionDatabaseRepository as we will be on a background thread away from the actual network call?

Do you want to develop this feature yourself?
I could easily see several user stories to extend the GraphQL support, each of which would add value and could be independently worked by people. I would be happy to work with you on coming up with several new issues, and would also be glad to work on any of them.

Feature Request: Cloud Message Logging

I currently have to log FCM messages for debug builds of my application. It would be great if I could offload this responsibility to chucker. Perhaps by supporting an additional data type that would result in a 3rd tab, "Messages" or "Data" or something along those lines, that I would then be able to call in my FcmMessageReceiver implementation's onMessageReceived handler to be able to pass the message into Chuck for logging.

I don't expect you'd want to add a dependency on the FCM libraries, but supporting most of the values in the RemoteMessage class would be great. The only one that would be mandatory would be the data (Map<String,String>), and the current timestamp.

Something like:

  @Override
  public void onMessageReceived(RemoteMessage remoteMessage) {
     chuckerCollector.onMessage(remoteMessage.getData());
  }

or:

  @Override
  public void onMessageReceived(RemoteMessage remoteMessage) {
     chuckerCollector.onMessage(
       remoteMessage.getData(),
       remoteMessage.getFrom(),
       remoteMessage.getTo(),
       remoteMessage.getMessageId(),
       remoteMessage.getmessageType(),
       remoteMessage.getSentTime(),
       remoteMessage.getTtl()
    );
  }

This or something like it could be useful to a lot of people, even if they're not using it for cloud messaging.

Chucker broken on OkHttp 4.0

Describe the bug
Chunker doesn't work with okhttp 4.0 due to API incompatibility

Error Log:

Caused by: java.lang.NoSuchMethodError: No static method hasBody(Lokhttp3/Response;)Z in class Lokhttp3/internal/http/HttpHeaders; or its super classes (declaration of 'okhttp3.internal.http.HttpHeaders' appears in /data/app/com.jora.android.debug-pyXggfGJ5Y4D-gUqowxVwQ==/split_lib_dependencies_apk.apk!classes2.dex)
    at com.readystatesoftware.chuck.api.ChuckInterceptor.intercept(ChuckInterceptor.java:149)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at com.jora.android.ng.network.authentication.AuthInterceptor.intercept(AuthInterceptor.kt:20)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:37)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:71)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184)
    at okhttp3.RealCall.execute(RealCall.kt:66)
    at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
    at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:45)
    at io.reactivex.Observable.subscribe(Observable.java:12267)
    at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
    at io.reactivex.Observable.subscribe(Observable.java:12267)
    at io.reactivex.internal.operators.observable.ObservableSingleSingle.subscribeActual(ObservableSingleSingle.java:35)
    at io.reactivex.Single.subscribe(Single.java:3603)
    at io.reactivex.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:34)
    at io.reactivex.Single.subscribe(Single.java:3603)
    at io.reactivex.internal.operators.single.SingleOnErrorReturn.subscribeActual(SingleOnErrorReturn.java:38)
    at io.reactivex.Single.subscribe(Single.java:3603)
    at io.reactivex.internal.operators.single.SingleFlatMap$SingleFlatMapCallback.onSuccess(SingleFlatMap.java:84)
    at io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:56)
    at io.reactivex.Single.subscribe(Single.java:3603)
    at io.reactivex.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:36)
    at io.reactivex.Single.subscribe(Single.java:3603)
    at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
    at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
    at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)

Add Cookie support

Is your feature request related to a problem? Please describe.
Chucker should provide a way to show the Cookies that are sent for every request.

Describe the solution you'd like
Ideally having a separated tab for cookies would be helpful. As a MVP having them listed below the headers would be a good starting point.

Do you want to develop this feature yourself?
nop :) It's open for development

Some missing Proguard rules?

Describe the bug
I get a systematic crash on any build using Proguard when I try to launch a Chucker intent like this for example:
context.startActivity(Chuck.getLaunchIntent(context, SCREEN_HTTP))

I don't have any issue if I don't use Proguard, so that's why I guess it may be related to some Proguard rules missing.

Crash logs:

E/AndroidRuntime: FATAL EXCEPTION: ModernAsyncTask #2
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at androidx.i.b.d$3.done(ModernAsyncTask.java:164)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: android.database.sqlite.SQLiteException: no such column: tag (code 1 SQLITE_ERROR[1]): , while compiling: SELECT _id, tag, clazz, message, date FROM 'd' ORDER BY date DESC
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1229)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:703)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:59)
        at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
        at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
        at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1865)
        at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1712)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1583)
        at e.a.a.f$a.a(DatabaseCompartment.java:641)
        at e.a.a.f.a(DatabaseCompartment.java:437)
        at e.a.a.f.a(DatabaseCompartment.java:53)
        at e.a.a.f$b.a(DatabaseCompartment.java:586)
        at e.a.a.f$b.b(DatabaseCompartment.java:595)
        at com.readystatesoftware.chuck.internal.data.ChuckContentProvider.query(ChuckContentProvider.java:95)
        at android.content.ContentProvider.query(ContentProvider.java:1078)
        at android.content.ContentProvider.query(ContentProvider.java:1170)
        at android.content.ContentProvider$Transport.query(ContentProvider.java:241)
        at android.content.ContentResolver.query(ContentResolver.java:808)
        at android.content.ContentResolver.query(ContentResolver.java:758)
        at androidx.core.content.a.a(ContentResolverCompat.java:81)
        at androidx.i.b.b.h(CursorLoader.java:63)
        at androidx.i.b.b.d(CursorLoader.java:41)
        at androidx.i.b.a.e(AsyncTaskLoader.java:307)
        at androidx.i.b.a$a.a(AsyncTaskLoader.java:60)
        at androidx.i.b.a$a.a(AsyncTaskLoader.java:48)
        at androidx.i.b.d$2.call(ModernAsyncTask.java:141)

To Reproduce
Steps to reproduce the behavior:
Enable Proguard and try to launch any Chucker intent.

Thanks a lot in advance for your help! ๐Ÿ™‚๐Ÿ‘‹

Request body is not searchable

Describe the bug
I can search in response, but not in request body.

To Reproduce
Steps to reproduce the behavior:

  1. Go to any request tab
  2. Magnifying class icon is missing

Expected behavior
There is a working magnifying class icon for searching in request body, same as in response tab.

Smartphone

  • Device: Nexus 5X
  • OS: LineageOS 15.1 (8.1)
  • Lib version: 3.0.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.