41554 blogs · [ { "id": "01a087d9-98e7-7124-8d8d-294cf2d59d21", "title": "A Great Gradle Module Structure", "url": "https://ryanharter.com/blog/2026/07/a-great-gradle-module-structure/", "published_at": "2026-07-15T13:38:11+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf2e99c8e", "title": "Graceful Exit", "url": "https://ryanharter.com/blog/2026/06/graceful-exit/", "published_at": "2026-06-19T01:44:39+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf35768e0", "title": "Incremental Maintenance", "url": "https://ryanharter.com/blog/2026/05/incremental-maintenance/", "published_at": "2026-05-14T01:53:09+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf39e328f", "title": "Values", "url": "https://ryanharter.com/blog/2026/01/values/", "published_at": "2026-01-31T04:05:39+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf43e1a24", "title": "Celebrate the code you didn't write", "url": "https://ryanharter.com/blog/2025/06/celebrate-the-code-you-didnt-write/", "published_at": "2025-06-06T03:47:36+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf4c2aeaa", "title": "Start More Projects", "url": "https://ryanharter.com/blog/2024/12/start-more-projects/", "published_at": "2024-12-07T14:42:34+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf5468869", "title": "Make Things Easy", "url": "https://ryanharter.com/blog/2024/07/make-things-easy/", "published_at": "2024-07-25T13:07:35+00:00" }, { "id": "01a087d9-98e7-7124-8d8d-294cf5a220d0", "title": "Extending Coil", "url": "https://ryanharter.com/blog/2024/04/extending-coil/", "published_at": "2024-04-12T01:53:35+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff0bdbddd", "title": "Screenshot Tests Are Manual Tests", "url": "https://ryanharter.com/blog/2023/10/screenshot-tests-are-manual-tests/", "published_at": "2023-10-17T16:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff1b548b2", "title": "Simple APIs are elegant APIs", "url": "https://ryanharter.com/blog/2023/08/simple-apis-are-elegant-apis/", "published_at": "2023-08-10T02:55:50+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff1efd9c7", "title": "Rounded Corners", "url": "https://ryanharter.com/blog/2022/09/rounded-corners/", "published_at": "2022-09-20T03:37:48+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff2a1c6d7", "title": "Building Plugable Features on Android", "url": "https://ryanharter.com/blog/2022/08/building-plugable-features-on-android/", "published_at": "2022-08-07T15:05:54+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff31b0016", "title": "Make a Prototype", "url": "https://ryanharter.com/blog/2020/12/make-a-prototype/", "published_at": "2020-12-16T16:08:53+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff407eb8d", "title": "Handling Dates & Times in SQLite", "url": "https://ryanharter.com/blog/2020/09/handling-dates-times-in-sqlite/", "published_at": "2020-09-04T16:35:01+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff40e70a3", "title": "SQLDelight on the Server", "url": "https://ryanharter.com/blog/2020/08/sqldelight-on-the-server/", "published_at": "2020-08-27T16:05:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff47299f7", "title": "Server Side Analytics with GoAccess", "url": "https://ryanharter.com/blog/2020/06/server-side-analytics-with-goaccess/", "published_at": "2020-06-21T09:01:33+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff5304a34", "title": "Replacing Mocks", "url": "https://ryanharter.com/blog/2020/06/replacing-mocks/", "published_at": "2020-06-09T07:23:09+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff58e44d7", "title": "Your Labor is a Product", "url": "https://ryanharter.com/blog/2020/05/your-labor-is-a-product/", "published_at": "2020-05-26T14:21:05+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff5959ae6", "title": "Easy Android Scopes", "url": "https://ryanharter.com/blog/2020/03/easy-android-scopes/", "published_at": "2020-03-13T16:09:47+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff5dbc53c", "title": "Handling Transient Events", "url": "https://ryanharter.com/blog/2019/07/handling-transient-events/", "published_at": "2019-07-26T15:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff6a16e3f", "title": "Encapsulating View State", "url": "https://ryanharter.com/blog/2019/07/encapsulating-view-state/", "published_at": "2019-07-19T16:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff6ee6a66", "title": "Cloud Build Recipes - Saving the Build Cache", "url": "https://ryanharter.com/blog/2019/02/cloud-build-recipes-saving-the-build-cache/", "published_at": "2019-02-15T20:13:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff740df2d", "title": "Cloud Build Recipes - Incrementing Build Numbers", "url": "https://ryanharter.com/blog/2019/01/cloud-build-recipes-incrementing-build-numbers/", "published_at": "2019-02-01T03:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff745073b", "title": "Google Cloud Build for Android", "url": "https://ryanharter.com/blog/2018/12/google-cloud-build-for-android/", "published_at": "2018-12-21T20:27:21+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff809008b", "title": "Android Development on a Pixelbook", "url": "https://ryanharter.com/blog/2018/06/android-development-on-a-pixelbook/", "published_at": "2018-06-20T21:00:01+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff8a7611e", "title": "Introducing Billingx", "url": "https://ryanharter.com/blog/2018/06/introducing-billingx/", "published_at": "2018-06-17T23:05:10+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff8b6aff6", "title": "Continuous Delivery for Android", "url": "https://ryanharter.com/blog/2018/05/continuous-delivery-for-android/", "published_at": "2018-05-24T20:15:03+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff936e433", "title": "AutoValue Extensions", "url": "https://ryanharter.com/blog/2016/05/autovalue-extensions/", "published_at": "2016-05-16T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff973d4b2", "title": "A Deeper Look at AutoValue", "url": "https://ryanharter.com/blog/2016/04/a-deeper-look-at-autovalue/", "published_at": "2016-04-08T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79aff9d66c9d", "title": "An Introduction to AutoValue", "url": "https://ryanharter.com/blog/2016/03/an-introduction-to-autovalue/", "published_at": "2016-03-22T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affa5c7514", "title": "Dealing with AsyncTask in Unit Tests", "url": "https://ryanharter.com/blog/2015/12/dealing-with-asynctask-in-unit-tests/", "published_at": "2015-12-28T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affb2e85ce", "title": "Should this be a library?", "url": "https://ryanharter.com/blog/2015/08/should-this-be-a-library/", "published_at": "2015-08-20T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affbc5e798", "title": "Wrapping Existing Libraries with RxJava", "url": "https://ryanharter.com/blog/2015/07/wrapping-existing-libraries-with-rxjava/", "published_at": "2015-07-07T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affc9e4ad5", "title": "Using All the App Stores", "url": "https://ryanharter.com/blog/2015/07/using-all-the-app-stores/", "published_at": "2015-07-04T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affcc44e76", "title": "Hosting a Private Maven Repo on Amazon S3", "url": "https://ryanharter.com/blog/2015/06/hosting-a-private-maven-repo-on-amazon-s3/", "published_at": "2015-06-18T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affd822226", "title": "Custom Drawables", "url": "https://ryanharter.com/blog/2015/04/custom-drawables/", "published_at": "2015-04-03T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79affe4ac0de", "title": "The Architecture effect of Test Driven Development", "url": "https://ryanharter.com/blog/2015/04/the-architecture-effect-of-test-driven-development/", "published_at": "2015-04-03T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79afff0e7a85", "title": "Styling Chromecast Icons", "url": "https://ryanharter.com/blog/2015/03/styling-chromecast-icons/", "published_at": "2015-03-06T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79afff243a98", "title": "What's Your Intent?", "url": "https://ryanharter.com/blog/2014/11/whats-your-intent/", "published_at": "2014-11-26T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79afffc7b198", "title": "Using Gestures", "url": "https://ryanharter.com/blog/2014/10/using-gestures/", "published_at": "2014-10-08T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b0001d063c", "title": "Kindly Asking for Ratings and Reviews", "url": "https://ryanharter.com/blog/2014/09/kindly-asking-for-ratings-and-reviews/", "published_at": "2014-09-05T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00056deec", "title": "Building Dynamic Custom Views", "url": "https://ryanharter.com/blog/2014/08/building-dynamic-custom-views/", "published_at": "2014-08-29T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00109a192", "title": "Bringing Fragment to Android", "url": "https://ryanharter.com/blog/2014/08/bringing-fragment-to-android/", "published_at": "2014-08-21T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b001a419bd", "title": "A Modern CI Server for Android", "url": "https://ryanharter.com/blog/2014/07/a-modern-ci-server-for-android/", "published_at": "2014-07-02T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00213af8c", "title": "Using Custom Compound Views in Android", "url": "https://ryanharter.com/blog/2014/05/using-custom-compound-views-in-android/", "published_at": "2014-05-14T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b002d3b3e9", "title": "Customizing the ListView", "url": "https://ryanharter.com/blog/2014/02/customizing-the-listview/", "published_at": "2014-02-23T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b002df492e", "title": "Two Months With the Moto X", "url": "https://ryanharter.com/blog/2014/02/two-months-with-the-moto-x/", "published_at": "2014-02-09T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b003c38969", "title": "Creating an Android Project", "url": "https://ryanharter.com/blog/2014/02/creating-an-android-project/", "published_at": "2014-02-07T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b0049afe2c", "title": "Getting Started with Git", "url": "https://ryanharter.com/blog/2014/01/getting-started-with-git/", "published_at": "2014-01-29T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b004f04ee3", "title": "Developing an Android App - Start to Finish", "url": "https://ryanharter.com/blog/2014/01/developing-an-android-app-start-to-finish/", "published_at": "2014-01-20T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b005655fe7", "title": "Android Emulation Done Right", "url": "https://ryanharter.com/blog/2013/09/android-emulation-done-right/", "published_at": "2013-09-10T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b005ea9ebe", "title": "What to Expect When Being Featured on Google Play", "url": "https://ryanharter.com/blog/2013/08/what-to-expect-when-being-featured-on-google-play/", "published_at": "2013-08-20T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b006a7fd8f", "title": "Almost Git-Flow", "url": "https://ryanharter.com/blog/2013/07/almost-git-flow/", "published_at": "2013-07-31T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b007433118", "title": "Automatic Versioning with Git and Gradle", "url": "https://ryanharter.com/blog/2013/07/automatic-versioning-with-git-and-gradle/", "published_at": "2013-07-30T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b007a4b9e2", "title": "Impress Your Users", "url": "https://ryanharter.com/blog/2013/07/impress-your-users/", "published_at": "2013-07-22T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b007aa7f26", "title": "Hashnote Version Distribution", "url": "https://ryanharter.com/blog/2013/07/hashnote-version-distribution/", "published_at": "2013-07-18T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b007bf89a5", "title": "Migrating Android Projects to Gradle", "url": "https://ryanharter.com/blog/2013/07/migrating-android-projects-to-gradle/", "published_at": "2013-07-17T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b0087b5bd6", "title": "Going ICS Only", "url": "https://ryanharter.com/blog/2013/07/going-ics-only/", "published_at": "2013-07-07T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b0096ce9ea", "title": "Introducing Gradle", "url": "https://ryanharter.com/blog/2013/06/introducing-gradle/", "published_at": "2013-06-17T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b009d50af4", "title": "Absorbing Google I/O", "url": "https://ryanharter.com/blog/2013/05/absorbing-google-i/o/", "published_at": "2013-05-20T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00aaa1cf5", "title": "One Question: Why?", "url": "https://ryanharter.com/blog/2013/04/one-question-why/", "published_at": "2013-04-22T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00b70000b", "title": "Credit Where Credits Due", "url": "https://ryanharter.com/blog/2013/04/credit-where-credits-due/", "published_at": "2013-04-12T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00bea9beb", "title": "Android Tips: Making a Custom Button out of Anything", "url": "https://ryanharter.com/blog/2013/03/android-tips-making-a-custom-button-out-of-anything/", "published_at": "2013-03-19T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00c1869bc", "title": "Hashnote Featured on MakeUseOf.com", "url": "https://ryanharter.com/blog/2013/03/hashnote-featured-on-makeuseof.com/", "published_at": "2013-03-11T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00caef279", "title": "Everyone Should Code", "url": "https://ryanharter.com/blog/2013/02/everyone-should-code/", "published_at": "2013-02-27T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00cbaa757", "title": "The case for Fragment Callbacks", "url": "https://ryanharter.com/blog/2013/02/the-case-for-fragment-callbacks/", "published_at": "2013-02-18T07:00:00+00:00" }, { "id": "01a087d9-98e8-725a-b8d4-79b00d9aee06", "title": "Hi There!", "url": "https://ryanharter.com/about/", "published_at": null } ] posts Claim your blog
Back to ryanharter.com
Blog · corpus.blog/blogs/ryanharter.com/posts

ryanharter.com

ryanharter.com

2026

2025

2024

2023

2022

2020

2019

2018

2016

2015

2014

2013

Undated