Coder Social home page Coder Social logo

whatthestack's Introduction

WhatTheStack

Banner

WhatTheStack is a library to make your debugging experience on Android better.

It shows you a pretty error screen when your Android App crashes, instead of a boring old dialog saying "Unfortunately, <your-app> has crashed".

Demo

Setup

Release

Add Jitpack repository in your root build.gradle file:

allprojects {
  repositories {
    maven { url 'https://jitpack.io' }
  }
}

And then add the dependency to your app:

dependencies {
  debugImplementation 'com.github.haroldadmin:WhatTheStack:(latest-version)'
}

Now when an uncaught exception is thrown in your application, you will be greeted with a screen containing information about the crash. We support light and dark themes too!

Usage

WhatTheStack works by overriding the default exception handler in your app. It processes any uncaught exception in your app, parses it to extract useful information, and then shows it in a pretty screen.

Automatic Initialization

WhatTheStack uses the Jetpack App Startup library to run automatically when your app starts. You don't need to write any code to initialize it manually.

Need to disable automatic initialization? If you want to disable automatic startup, add the following lines to your Manifest file:
<provider
  android:name="androidx.startup.InitializationProvider"
  android:authorities="${applicationId}.androidx-startup"
  android:exported="false"
  tools:node="merge">
  <meta-data  android:name="com.haroldadmin.whatthestack.WhatTheStackInitializer"
    android:value="androidx.startup"
      tools:node="remove"/>
</provider>

Debug vs Release builds

We recommend using WhatTheStack in debug builds only. We see it as a tool to improve the experience of the developer, not the user.

Need to use it in release builds? If you want to use WhatTheStack in release builds, replace the `debugImplementation` dependency with `implementation'.
dependencies {
-  debugImplementation 'com.github.haroldadmin:WhatTheStack:(latest-version)'
+  implementation 'com.github.haroldadmin:WhatTheStack:(latest-version)'
}'

The library ships with Proguard rules to ensure that it works correctly even after minification.

Multi-Process Service

WhatTheStack runs a bound service in a separate process to show you the error screen on a crash.

We need to run this code in a separate process because you can't reliably launch new Activities in the host application's process after an uncaught exception is thrown.

Contributions

We are happy to accept any external contributions in the form of PRs, issues, or blog posts.

Please consider starring the repository if you find it useful or intriguing!

whatthestack's People

Contributors

hameno avatar haroldadmin avatar larissayasin avatar msfjarvis avatar shivam21 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

whatthestack's Issues

Suspected race conditon exception with Encrypted Realm database

Hey,

We're seeing a crash in our debug and release builds with the below stacktrace. The behaviour is strange because the app technically crashes but because the service is going into a fatal state, we just get a dialog to state that this app keeps stopping etc.

I believe it's a race condition issue because when I attach a debugger to sanity check the pid, I can't reproduce the issue. Removing WhatTheStack also resolves it but I'd like to see what I can do to work around this.

When our app starts, our Application will create our Dagger AppModule which includes getting our encrypted realm instance. From your experience with Jetpack Startup, do you believe it would be better for us to adapt it to hopefully prevent this issue?

stacktrace

2021-12-13 13:50:36.546 19590-19590/com.my.app.dev E/REALM_JNI: jni: ThrowingException 7, /data/user/0/com.my.app.dev/files/encrypted-register.realm: Encrypted interprocess sharing is currently unsupported.DB has been opened by pid: 19556. Current pid is 19590. in /tmp/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 106, .
2021-12-13 13:50:36.546 19590-19590/com.my.app.dev E/REALM_JNI: Exception has been thrown: /data/user/0/com.my.app.dev/files/encrypted-register.realm: Encrypted interprocess sharing is currently unsupported.DB has been opened by pid: 19556. Current pid is 19590. in /tmp/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 106
2021-12-13 13:50:36.546 19590-19590/com.my.app.dev D/AndroidRuntime: Shutting down VM
2021-12-13 13:50:36.547 19590-19590/com.my.app.dev E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.my.app.dev:what_the_stack_process, PID: 19590
java.lang.RuntimeException: Unable to create application com.my.app.DebugApplication: java.lang.RuntimeException: /data/user/0/com.my.app.dev/files/encrypted-register.realm: Encrypted interprocess sharing is currently unsupported.DB has been opened by pid: 19556. Current pid is 19590. in /tmp/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 106
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6465)
at android.app.ActivityThread.access$1300(ActivityThread.java:219)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1859)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.RuntimeException: /data/user/0/com.my.app.dev/files/encrypted-register.realm: Encrypted interprocess sharing is currently unsupported.DB has been opened by pid: 19556. Current pid is 19590. in /tmp/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 106
at io.realm.internal.OsSharedRealm.nativeGetSharedRealm(Native Method)
at io.realm.internal.OsSharedRealm.(OsSharedRealm.java:175)
at io.realm.internal.OsSharedRealm.getInstance(OsSharedRealm.java:251)
at io.realm.BaseRealm.(BaseRealm.java:141)
at io.realm.BaseRealm.(BaseRealm.java:108)
at io.realm.Realm.(Realm.java:159)
at io.realm.Realm.createInstance(Realm.java:495)
at io.realm.RealmCache.createInstance(RealmCache.java:494)
at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:461)
at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:422)
at io.realm.Realm.getInstance(Realm.java:424)
at com.my.app.persistence.RealmDao.getRealmInstance(RealmDao.kt:144)
at com.my.app.persistence.RealmDao.executeQuery(RealmDao.kt:137)
at com.my.app.users.persistence.UsersDao.findUserById(UsersDao.kt:47)
at com.my.app.users.service.UsersService.fetchUserById(UsersService.kt:97)
at com.my.app.users.service.UsersService.restorePersistedActiveUser(UsersService.kt:63)
at com.my.app.users.service.UsersService.restoreLastLoggedInUser(UsersService.kt:58)
at com.my.app.users.service.UsersService.(UsersService.kt:46)
at com.my.app.users.service.UsersService_Factory.newInstance(UsersService_Factory.java:65)
at com.my.app.users.service.UsersService_Factory.get(UsersService_Factory.java:51)
at com.my.app.users.service.UsersService_Factory.get(UsersService_Factory.java:15)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.my.app.updates.service.UpdateService_Factory.get(UpdateService_Factory.java:90)
at com.my.app.updates.service.UpdateService_Factory.get(UpdateService_Factory.java:22)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.my.app.updates.service.UpdateService_Factory.get(UpdateService_Factory.java:105)
at com.my.app.updates.service.UpdateService_Factory.get(UpdateService_Factory.java:26)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at dagger.internal.DelegateFactory.get(DelegateFactory.java:36)
at com.my.app.scheduler.service.UpdateTimerTask_Factory.get(UpdateTimerTask_Factory.java:33)
at com.my.app.scheduler.service.UpdateTimerTask_Factory.get(UpdateTimerTask_Factory.java:11)
at com.my.app.scheduler.service.UpdateScheduler_Factory.get(UpdateScheduler_Factory.java:27)
2021-12-13 13:50:36.548 19590-19590/com.my.app.dev E/AndroidRuntime: at com.my.app.scheduler.service.UpdateScheduler_Factory.get(UpdateScheduler_Factory.java:9)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.my.app.modules.DaggerApplicationComponent.injectApplication(DaggerApplicationComponent.java:3989)
at com.my.app.modules.DaggerApplicationComponent.inject(DaggerApplicationComponent.java:3312)
at com.my.app.Application.initializeDagger(Application.kt:87)
at com.my.app.Application.onCreate(Application.kt:63)
at com.my.app.DebugApplication.onCreate(DebugApplication.kt:13)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1182)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6460)

Thanks!

Error when adding to existing project with webviews

Hey! Thank you for this library. I just got it up and running and we're excited to catch those rare but annoying to debug crashes when away from our machines. I implemented it (0.3.0) into our existing project and had to make two changes to our codebase:

  • Add Configuration.Provider interface for WorkManager in the main application, as we provide Workmanager through Dagger WorkManager.getInstance(applicationContext).
  • Add the following block of code in the Application onCreate:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    if (packageName != getProcessName()) WebView.setDataDirectorySuffix(getProcessName())
}

The second fix was a result of whatthestack throwing the following exception:

Stacktrace
  
  2021-12-03 23:59:10.482 17446-17446/com.myapp.name.dev E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myapp.name.dev:what_the_stack_process, PID: 17446
    java.lang.RuntimeException: Unable to create application com.myapp.name.DebugApplication: java.lang.RuntimeException: Using WebView from more than one process at once with the same data directory is not supported. https://crbug.com/558377
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6465)
        at android.app.ActivityThread.access$1300(ActivityThread.java:219)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1859)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.RuntimeException: Using WebView from more than one process at once with the same data directory is not supported. https://crbug.com/558377
        at org.chromium.android_webview.AwBrowserProcess.a(PG:40)
        at kv.c(PG:90)
        at kv.b(PG:160)
        at kv.e(PG:177)
        at com.android.webview.chromium.WebViewChromiumFactoryProvider.getStatics(PG:204)
        at android.webkit.WebView.setWebContentsDebuggingEnabled(WebView.java:1974)
        at com.myapp.name.DebugApplication.onCreate(DebugApplication.kt:17)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1182)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6460)
        at android.app.ActivityThread.access$1300(ActivityThread.java:219) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1859) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

I don't see any webview code in this repo, so I assume it's down to us having multiple webviews (and could be fixed by removing WebView.setWebContentsDebuggingEnabled). Happy to close this issue out as it could help others with the same issue.

language

Does this library automatically change its language according to the system or does it only support English?

Add more themes for the error screen

The current error reporting screen supports both light and dark themes, using the Material Components library. It would be great if we could provide more customization options to the user in the form of additional themes.

Tasks:

  • Add additional themes to styles.xml
  • Make themes configurable through application code, or manifest merger (needs exploration)
  • Perform a check in WhatTheStackActivity to decide which theme to use

Add ability to restart the app from the error screen

The crash screen should provide the user with the ability to restart the app.

Tasks:

  • Record information to build an intent for the app when it crashes
  • Add a button below Share Stacktrace which fires the intent to launch the app again
  • Finish the crashed activity

I am not sure how this would affect the task-stack. Might need to fiddle with launch options to fix unexpected behaviours.

Error screen does not work if the app crashes very quickly after launching

The library relies on a service running in a different process to process and display the error screen. This means that if the application crashes immediately after start, the service might not get enough time to be prepared for accepting new messages.

Unfortunately it looks like there is no easy solution for this problem.

Add feature to share stacktrace text via email and text

The library currently allows copying the stack trace error text to be pasted somewhere else. It would be nice if we provided an option to directly share the text through email or text too.

Tasks:

  • Add a share intent to the stack trace in WhatTheStackActivity
  • Make sure the added code passes the CI pipeline.

Add ability to view stacktraces of all threads when the exception is captured

It is helpful to view the stacktraces of all active threads during the time an exception is thrown. Representing each thread's stacktrace in a list of collapsible items would make it easy to go through each one of them.

Tasks:

  • Capture all active stacktraces using the Thread.getAllStackTraces() API in the exception handler
  • Parse the captured values and send them over the service connection
  • Create an accordion-style list to display the stacktrace of each thread

This is a fairly huge change. Discussing exact UI implementations would be helpful before starting work on the PR.

Additional stack trace options & list items

This library is incredibly awesome, it's a tiny idea that can dramatically improve developing experience.

I haven't had the pleasure yet to test and use it yet but I can tell you a couple of ideas that came to my mind (Maybe with time I can create a pr and add them)

Instead of exception, cause, message thrown, a RecyclerView listing an icon together with the title, and a content TextView for each field could be used, so you have nicer animations, better graphic and higher flexibility (If one day you want to add another field to show).

Plus, you could add a "Share Logcat" button alongside "Copy Logcat", to provide more options.

Error screen does not work with minifyEnabled = true

Hi,

Great idea with the library! Unfortunately I cannot make it work on minified builds: the Service simply doesn't get the message to start the Activity. I can reproduce the issue by building the release variant of the demo app in this repository, without modifying anything. Devices: OnePlus 3T (Android 9), Galaxy Note 10+ (Android 10)

I've spent some time trying to fix this as I'm working on something similar, but couldn't make it work. I tried starting the service in different ways (starting the Activity in onStartCommand()) which, again, works in debug builds but not after enabling minification. @Keep-ing every relevant class didn't fix the issue either.

Is there a limitation regarding ProGuard I wasn't aware of?

Thanks,
Peter

Large exceptions (such as stack overflow error) can crash the library, eating the original exception

When app crashes with a really large exception (such as stack overflow error with a really long stack trace), WhatTheStack will crash:

kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for CancellableContinuation(DispatchedContinuation[AndroidUiDispatcher@491392b, Continuation at androidx.compose.runtime.PausableMonotonicFrameClock.withFrameNanos(PausableMonotonicFrameClock.kt:63)@382a188]){Completed}@3066721. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
	at kotlinx.coroutines.DispatchedTask.handleFatalException(DispatchedTask.kt:144)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:115)
	at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
	at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
	at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:68)
	at [android.view.Choreographer$CallbackRecord.run(Choreographer.java:1035)](http://android.view.Choreographer$CallbackRecord.run(Choreographer.java:1035))
	at [android.view.Choreographer.doCallbacks(Choreographer.java:845)](http://android.view.Choreographer.doCallbacks(Choreographer.java:845))
	at [android.view.Choreographer.doFrame(Choreographer.java:775)](http://android.view.Choreographer.doFrame(Choreographer.java:775))
	at [android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)](http://android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022))
	at [android.os.Handler.handleCallback(Handler.java:938)](http://android.os.Handler.handleCallback(Handler.java:938))
	at [android.os.Handler.dispatchMessage(Handler.java:99)](http://android.os.Handler.dispatchMessage(Handler.java:99))
	at [android.os.Looper.loopOnce(Looper.java:201)](http://android.os.Looper.loopOnce(Looper.java:201))
	at [android.os.Looper.loop(Looper.java:288)](http://android.os.Looper.loop(Looper.java:288))
	at [android.app.ActivityThread.main(ActivityThread.java:7840)](http://android.app.ActivityThread.main(ActivityThread.java:7840))
	at java.lang.reflect.Method.invoke(Native Method)
	at [com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550)](http://com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550))
	at [com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)](http://com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003))
Caused by: android.os.TransactionTooLargeException: data parcel size 7859848 bytes
	at android.os.BinderProxy.transactNative(Native Method)
	at [android.os.BinderProxy.transact(BinderProxy.java:571)](http://android.os.BinderProxy.transact(BinderProxy.java:571))
	at [android.os.IMessenger$Stub$Proxy.send(IMessenger.java:125)](http://android.os.IMessenger$Stub$Proxy.send(IMessenger.java:125))
	at [android.os.Messenger.send(Messenger.java:59)](http://android.os.Messenger.send(Messenger.java:59))
	at com.haroldadmin.whatthestack.WhatTheStackExceptionHandler.uncaughtException(WhatTheStackExceptionHandler.kt:22)
	at [java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073)](http://java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073))
	at [java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)](http://java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068))
	at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:45)
	at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:39)
	at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:192)
	at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
	at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
	at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
	at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.UndispatchedCoroutine.afterResume(CoroutineContext.kt:147)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:102)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:33)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:102)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)

Even worse, this exception will override original exception, making it unaccessible unless I disable WhatTheStack.

Maybe in this rare case, WhatTheStack could try catch this error, print original exception to the logcat and just display the message (without the stacktrace)?

Experiment with Jetpack Compose in WhatTheStackActivity

Jetpack Compose is the next generation UI toolkit for Android. Creating an experimental version of the error screen in compose would serve as a nice playground for the project.

Tasks:

  • Setup project for Jetpack Compose (enable compose in build features)
  • Create an experimental version of WhatTheStackActivity using composables
  • Incorporate Jetpack Compose's Material Theming for implementing dark mode support

Separate the library into a runtime-module and a ui-module

This library consists of two parts: A background service, and a UI Activity. Consider separating them into different modules and allow more flexibility between them.

Separating these classes will allow for features such as:

  • Adding custom exception handlers
  • Showing a different Activity when the app crashes
  • Selectively including only the required dependencies in projects

Crash when using newer systemuicontroller dependency

Hello

If target app is using newer version of systemuicontroller from accompanist (anything newer than 0.24.0), then Whats The Stack screen crashes with the following stack trace

Process: com.haroldadmin.crashyapp:what_the_stack_process, PID: 9954
java.lang.NoSuchMethodError: No static method rememberSystemUiController(Landroidx/compose/runtime/Composer;I)Lcom/google/accompanist/systemuicontroller/SystemUiController; in class Lcom/google/accompanist/systemuicontroller/SystemUiControllerKt; or its super classes (declaration of 'com.google.accompanist.systemuicontroller.SystemUiControllerKt' appears in /data/app/~~_4awURteYBFPZaFNkqrgiA==/com.haroldadmin.crashyapp-qVRDMtt8OFur9dGDn3-XHQ==/base.apk)
       at com.haroldadmin.whatthestack.WhatTheStackActivity$onCreate$1.invoke(WhatTheStackActivity.kt:28)
       at com.haroldadmin.whatthestack.WhatTheStackActivity$onCreate$1.invoke(WhatTheStackActivity.kt:27)

It looks like in version 0.25.0 the rememberSystemUiController function signature changed as seen here. It now takes an additional param of a Window, which I think breaks binary compatibility (even though a default is used in the accompanist library)

I think a simple version bump of the dependencies of this library should be enough to fix this issue. I can open a PR if necessary

Migrate to ViewBinding in the project

WhatTheStack started as a small project to only display very basic information on a crash. findViewById sufficed for this purpose.

However, the complexity of the error screen has increased since then, and is going to continue in that direction. Therefore it makes sense to now refactor the project to migrate to ViewBinding instead.

Tasks:

  • Enable ViewBinding in the project's build configuration
  • Migrate to ViewBinding in the sample app
  • Migrate to ViewBinding in the library

Support for targeting sdk 31

To support users of the library who are targeting SDK 12/S/31 or higher, please add android:exported="true|false" in AndroidManifest.xml for these components:

com.haroldadmin.whatthestack.WhatTheStackService
com.haroldadmin.whatthestack.WhatTheStackActivity

Currently the only way to get my app to build with targetSdkVersion 31 is to add mergeable entries for these components in my app's Manifest with android:exported="true" to overwrite the library manifest entries i.e.

<service
          android:name="com.haroldadmin.whatthestack.WhatTheStackService"
          android:process=":what_the_stack_process"
          android:exported="false"
          tools:node="merge"/>
<activity
          android:name="com.haroldadmin.whatthestack.WhatTheStackActivity"
          android:process=":what_the_stack_process"
          android:exported="true"
          tools:node="merge"/>

see https://developer.android.com/about/versions/12/behavior-changes-12#exported

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.