<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: TheIOn-Project</title>
    <description>The latest articles on Forem by TheIOn-Project (@theionproject).</description>
    <link>https://forem.com/theionproject</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3870378%2Fcb65f36c-600a-49db-afab-dd26631af5f6.png</url>
      <title>Forem: TheIOn-Project</title>
      <link>https://forem.com/theionproject</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/theionproject"/>
    <language>en</language>
    <item>
      <title>The signing key mistake that cost me a week on my first Android release</title>
      <dc:creator>TheIOn-Project</dc:creator>
      <pubDate>Fri, 17 Apr 2026 22:07:02 +0000</pubDate>
      <link>https://forem.com/theionproject/the-signing-key-mistake-that-cost-me-a-week-on-my-first-android-release-1eo1</link>
      <guid>https://forem.com/theionproject/the-signing-key-mistake-that-cost-me-a-week-on-my-first-android-release-1eo1</guid>
      <description>&lt;p&gt;If you've never shipped an Android app to Google Play before, the signing key part is where a lot of people get quietly stuck. It's not a hard concept, but the way Google documents it makes it feel like you're juggling three different keys that could all brick your release if you mess up.&lt;/p&gt;

&lt;p&gt;Here's what actually went wrong for me the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I thought I was doing
&lt;/h2&gt;

&lt;p&gt;I generated a keystore the way most tutorials tell you. Ran keytool, set a password, saved the .jks file somewhere on my machine, and moved on. Then I signed my release APK with that key, uploaded it, and assumed I was done.&lt;/p&gt;

&lt;p&gt;I was not done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I missed
&lt;/h2&gt;

&lt;p&gt;Google Play now uses something called Play App Signing. What that means in practice is that Google manages the actual app signing key on their side. The key you generate locally is called your upload key. Those are two different things.&lt;/p&gt;

&lt;p&gt;The upload key is what you use to sign the AAB before uploading to Play. Play then strips that signature, re-signs the build with the actual app signing key, and ships it to users.&lt;/p&gt;

&lt;p&gt;If you lose your upload key, you can reset it. Annoying, but not fatal.&lt;/p&gt;

&lt;p&gt;If you lose your app signing key and Google doesn't have it, your app is done. You can't update it. Users who installed it will stay on that version forever. I didn't know this at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The week I lost
&lt;/h2&gt;

&lt;p&gt;Here's what ate up my week. I signed my first release build with a key. Uploaded the AAB. Rejected, because I hadn't enrolled in Play App Signing yet. Enrolled, re-uploaded. Accepted.&lt;/p&gt;

&lt;p&gt;Then I made a small fix a few days later. Signed the new build with what I thought was the same key. Rejected again. The fingerprints didn't match.&lt;/p&gt;

&lt;p&gt;Turned out I'd generated a second keystore by accident when I was testing something, and my build gradle was pointing at that one. I spent the better part of an evening trying to figure out which keystore was the real upload key. The one I'd used, the one that was in my backups, or the one gradle was actually loading.&lt;/p&gt;

&lt;p&gt;Eventually got it sorted by comparing SHA1 fingerprints against what Play had on file. But that whole mess could have been avoided if I'd understood the upload key vs app signing key distinction from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do now
&lt;/h2&gt;

&lt;p&gt;Three things.&lt;/p&gt;

&lt;p&gt;First, one keystore per app, named clearly, backed up in two places. I keep the .jks file in a password manager attachment slot and a second copy on an encrypted drive.&lt;/p&gt;

&lt;p&gt;Second, I write down the SHA1 fingerprint of the upload key the moment I create it. That way if anything ever looks weird, I can compare against a known-good value instead of guessing.&lt;/p&gt;

&lt;p&gt;Third, I let tools handle the signing config for me. This is partly why I ended up building IOn Emit. It handles the upload keystore generation, stores the fingerprint, and keeps the signing config consistent across builds so you don't end up pointing at the wrong file halfway through a release cycle.&lt;/p&gt;

&lt;p&gt;Play App Signing is actually a good thing once you understand it. It's just that the docs treat it like you already know the upload key vs app signing key distinction, and nobody explains that clearly until after you've tripped over it.&lt;/p&gt;

&lt;p&gt;If you're about to ship your first Android app and this is new to you, the short version is: generate one upload key, back it up, enroll in Play App Signing, and let Google handle the rest. Don't try to keep your own app signing key. That's the old workflow and it's not worth the risk.&lt;/p&gt;

&lt;p&gt;Anyway, this is the stuff I wish someone had told me before I spent a week chasing my own tail.&lt;/p&gt;

&lt;p&gt;IOn Emit is freemium and handles a lot of this friction for you: &lt;a href="https://theionproject.com/ionemit" rel="noopener noreferrer"&gt;https://theionproject.com/ionemit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>beginners</category>
      <category>devjournal</category>
      <category>mobile</category>
    </item>
    <item>
      <title>The Play Console steps that quietly kill momentum on Android side projects</title>
      <dc:creator>TheIOn-Project</dc:creator>
      <pubDate>Wed, 15 Apr 2026 22:06:36 +0000</pubDate>
      <link>https://forem.com/theionproject/the-play-console-steps-that-quietly-kill-momentum-on-android-side-projects-4ag4</link>
      <guid>https://forem.com/theionproject/the-play-console-steps-that-quietly-kill-momentum-on-android-side-projects-4ag4</guid>
      <description>&lt;p&gt;Most Android side projects don't die from bad code. They die in that weird last mile where your app works fine on your phone but getting it onto the Play Store feels like a part time job.&lt;/p&gt;

&lt;p&gt;Here's the stretch I see devs lose steam on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing keys
&lt;/h2&gt;

&lt;p&gt;The first time you generate an upload key and a signing key you think it's fine. Six months later you forget which one is which, and the Play Console politely refuses your upload. If you lose the key entirely, you can't push updates to that app again without going through a reset. That alone has killed a few of my projects over the years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Screenshot dimensions
&lt;/h2&gt;

&lt;p&gt;Play wants specific aspect ratios for phone, 7 inch tablet, and 10 inch tablet. Not just "some screenshots." If you've never done it, you spend an hour in Figma trying to figure out safe areas and status bar heights before you get to the actual design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data safety form
&lt;/h2&gt;

&lt;p&gt;This one is the silent killer. Every SDK you pulled in (analytics, crash reporting, ads, whatever) collects something, and you have to declare all of it. Miss one and your submission gets kicked back two days later. Nothing feels more demotivating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content rating questionnaire
&lt;/h2&gt;

&lt;p&gt;Fine for most apps, but the wording is a landmine. Answer "yes" to one ambiguous question about user generated content and suddenly you need a moderation policy document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal testing track before production
&lt;/h2&gt;

&lt;p&gt;You technically need a closed or internal test first, with a minimum number of testers for a minimum number of days. If you don't know that going in, you'll set aside a Sunday to publish and end up two weeks out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I cared enough to build a tool
&lt;/h2&gt;

&lt;p&gt;I got tired of this loop. Ship a small app in two days, then spend five more on Play Console plumbing. That's the reason IOn Emit exists. It's a desktop app that walks you through the publish flow end to end. Screenshots, signing, data safety declarations, the test track setup, the lot. Freemium, so you can try it before deciding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theionproject.com/ionemit" rel="noopener noreferrer"&gt;https://theionproject.com/ionemit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've got an Android app sitting on your machine that you've been meaning to publish, honestly the best thing you can do this week is just get through the Play Console stuff once. The second time is so much easier. And if you want to skip straight to easier, that's what the tool is for.&lt;/p&gt;

&lt;p&gt;What's the step that slows you down most on Play?&lt;/p&gt;

</description>
      <category>androidproductivitymobile</category>
    </item>
    <item>
      <title>The One-Command Android Release That Actually Worked For Me</title>
      <dc:creator>TheIOn-Project</dc:creator>
      <pubDate>Tue, 14 Apr 2026 17:21:43 +0000</pubDate>
      <link>https://forem.com/theionproject/the-one-command-android-release-that-actually-worked-for-me-1450</link>
      <guid>https://forem.com/theionproject/the-one-command-android-release-that-actually-worked-for-me-1450</guid>
      <description>&lt;p&gt;I've shipped a handful of Android apps over the last couple of years and the part that always slowed me down wasn't the code. It was the last mile. Signing, bundling, filling in the same store metadata I've filled in twenty times before, staring at the Play Console wondering which tab the language translations hide behind this week.&lt;/p&gt;

&lt;p&gt;This is a short write up of the release flow I actually settled on. Nothing fancy. No CI pipeline. Just a sane local setup that lets me push a new version without losing half a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: stop relying on memory for keystore stuff
&lt;/h2&gt;

&lt;p&gt;The thing that bit me the most was signing config drift. I'd set up signing once, forget about it, come back three months later and have no idea which variant was actually signed for release.&lt;/p&gt;

&lt;p&gt;Fix: keep a single &lt;code&gt;keystore.properties&lt;/code&gt; file (not in git) and reference it in &lt;code&gt;build.gradle&lt;/code&gt;. Then pin it to the release variant only. Once this is set once, it's set forever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;signingConfigs&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"keystore.properties"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
        &lt;span class="n"&gt;storeFile&lt;/span&gt; &lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'storeFile'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;storePassword&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'storePassword'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;keyAlias&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'keyAlias'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;keyPassword&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'keyPassword'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple. But I kept forgetting to pin it to &lt;code&gt;buildTypes.release.signingConfig&lt;/code&gt;. If your upload to Play ever silently fails or shows a weird "invalid signature" error, check that first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: build an AAB, not an APK
&lt;/h2&gt;

&lt;p&gt;I know this sounds obvious in 2026 but I still see people trying to upload APKs. Play wants the App Bundle. One command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew bundleRelease
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output lives in &lt;code&gt;app/build/outputs/bundle/release/&lt;/code&gt;. That's the file you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: the metadata problem
&lt;/h2&gt;

&lt;p&gt;This is the part nobody warns you about. The Play Console asks you for the same 30 fields every time. Screenshots, feature graphic, short description, full description, content rating, target audience, ads, data safety form, translations, etc. Each release.&lt;/p&gt;

&lt;p&gt;If you change literally one screenshot dimension, expect an email the next morning saying your release is held for review.&lt;/p&gt;

&lt;p&gt;My current solution is to template the whole thing. I keep a folder for each app with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;metadata/en-US/short_description.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata/en-US/full_description.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata/en-US/images/phone/*.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata/en-US/changelogs/default.txt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I either upload manually in a fixed order (my printed checklist is a lifesaver) or use a tool to push it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: the tool I actually use now
&lt;/h2&gt;

&lt;p&gt;Full disclosure, I built a desktop app for this because the manual loop was eating my Saturdays. It's called IOn Emit. It reads the metadata folder, handles the AAB upload, and pushes translations. If that sounds useful: &lt;a href="https://theionproject.com/ionemit" rel="noopener noreferrer"&gt;https://theionproject.com/ionemit&lt;/a&gt;. It's freemium.&lt;/p&gt;

&lt;p&gt;If you'd rather stay manual, I honestly understand. The command line plus a good checklist gets you 80 percent of the way there. The one thing I'd push for either way is that your release process lives in version control, not in your head.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: the boring stuff that matters
&lt;/h2&gt;

&lt;p&gt;A few habits that saved me from shipping bugs to prod:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Always bump &lt;code&gt;versionCode&lt;/code&gt; by at least 1, never reuse.&lt;/li&gt;
&lt;li&gt;Tag the commit as &lt;code&gt;v1.4.2&lt;/code&gt; the second you upload. If you ever need to reproduce that exact build, you'll thank yourself.&lt;/li&gt;
&lt;li&gt;Keep a &lt;code&gt;RELEASE_NOTES.md&lt;/code&gt; with what's different in each version. This is what goes into the Play Store changelog. No rewriting it on the fly.&lt;/li&gt;
&lt;li&gt;Do a dry run on internal testing track before production. Yes every time.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The goal isn't to automate everything. The goal is to make the release feel boring. If pushing a new version feels dramatic, something is wrong with your process, not your willpower.&lt;/p&gt;

&lt;p&gt;If this was useful, I write more about solo dev stuff over at &lt;a href="https://theionproject.com" rel="noopener noreferrer"&gt;https://theionproject.com&lt;/a&gt;. Happy to answer questions on signing config gotchas, I've hit most of them.&lt;/p&gt;

</description>
      <category>android</category>
    </item>
    <item>
      <title>The Google Play Console Is Still a Time Sink in 2026</title>
      <dc:creator>TheIOn-Project</dc:creator>
      <pubDate>Fri, 10 Apr 2026 22:39:50 +0000</pubDate>
      <link>https://forem.com/theionproject/the-google-play-console-is-still-a-time-sink-in-2026-2h9h</link>
      <guid>https://forem.com/theionproject/the-google-play-console-is-still-a-time-sink-in-2026-2h9h</guid>
      <description>&lt;p&gt;I've been publishing Android apps for a few years now. The actual coding part is usually the fun part. What isn't fun is the Google Play Console.&lt;/p&gt;

&lt;p&gt;Every time I go to upload a new build or update a listing, I end up spending way more time than I planned. Between the screenshot requirements, the content rating questionnaires, the store listing details, and whatever new compliance form they've added since last time, it's a whole thing.&lt;/p&gt;

&lt;p&gt;And I'm not even talking about complicated apps. Even for a simple utility app, you're looking at a solid chunk of your afternoon just getting everything formatted and submitted correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stuff that eats the most time
&lt;/h2&gt;

&lt;p&gt;If you've done this more than once, you know the drill:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Screenshots need to be specific dimensions for each device type. You need phone screenshots, tablet screenshots, and if you're feeling ambitious, Chromebook screenshots. Each set has its own size requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The content rating questionnaire asks you the same questions every time, and you still second-guess your answers because getting it wrong can get your app flagged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store listing copy has character limits that don't quite match what you want to say, so you end up rewriting your description three times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privacy policy links, data safety forms, target audience declarations. It all adds up.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is hard exactly. It's just tedious. And if you're a solo dev shipping multiple apps, you're doing this whole dance repeatedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built something to speed it up
&lt;/h2&gt;

&lt;p&gt;After going through this process enough times, I decided to build a tool that handles most of the repetitive parts. It's called &lt;a href="https://theionproject.com/ionemit" rel="noopener noreferrer"&gt;IOn Emit&lt;/a&gt;, and it's basically a desktop app that simplifies the whole publishing workflow.&lt;/p&gt;

&lt;p&gt;The idea is pretty straightforward: instead of clicking through dozens of console screens, you configure your app details once and let the tool handle the submission. It cuts what used to take me an hour or more down to about five minutes.&lt;/p&gt;

&lt;p&gt;It's freemium, so you can try the core features without paying anything. I built it for myself originally, but figured other Android devs might find it useful too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not everything needs to be painful
&lt;/h2&gt;

&lt;p&gt;There's this weird acceptance in the Android dev community that publishing is just supposed to be annoying. Like it's the price you pay for being on the platform. But it really doesn't have to be that way.&lt;/p&gt;

&lt;p&gt;If you're spending more time in the Play Console than you are actually building your app, something's off. That's time you could spend on features, testing, or honestly just not staring at Google's UI.&lt;/p&gt;

&lt;p&gt;If you've felt this pain before, I'd love to hear how you deal with it. And if you want to try Emit, the link is above. Happy to answer any questions about it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building &lt;a href="https://theionproject.com" rel="noopener noreferrer"&gt;The IOn Project&lt;/a&gt; as a solo dev. Follow along on &lt;a href="https://x.com/TheIOnProject_" rel="noopener noreferrer"&gt;X @TheIOnProject_&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>devtools</category>
      <category>productivity</category>
      <category>googleplay</category>
    </item>
    <item>
      <title>I Published My Android App in Under 5 Minutes. Here's Exactly How.</title>
      <dc:creator>TheIOn-Project</dc:creator>
      <pubDate>Thu, 09 Apr 2026 18:09:45 +0000</pubDate>
      <link>https://forem.com/theionproject/i-published-my-android-app-in-under-5-minutes-heres-exactly-how-3i81</link>
      <guid>https://forem.com/theionproject/i-published-my-android-app-in-under-5-minutes-heres-exactly-how-3i81</guid>
      <description>&lt;p&gt;I spent weeks the first time I tried to get an app on Google Play. The console is a maze of forms, policy checkboxes, and requirements that look optional but aren't. Privacy policy URLs, data safety declarations, content ratings. Miss one thing and you're stuck in review limbo.&lt;/p&gt;

&lt;p&gt;After going through that pain enough times, I built a desktop tool called &lt;a href="https://theionproject.com/ionemit" rel="noopener noreferrer"&gt;IOn Emit&lt;/a&gt; that handles the entire publishing flow. You point it at your APK or AAB, fill in the basics, and it walks you through every step the Play Console requires. No browser tabs, no guessing what's missing. It's freemium, so the core stuff is free to use.&lt;/p&gt;

&lt;p&gt;Here's the thing though. Even if you don't use a tool, the biggest time saver is just knowing what Google actually requires upfront. So I wrote a quick walkthrough covering the whole process from start to finish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full guide:&lt;/strong&gt; &lt;a href="https://theionproject.com/blog/publish-android-app-5-minutes" rel="noopener noreferrer"&gt;Publish Your Android App in Under 5 Minutes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever rage-closed the Play Console tab, this might save you some headaches. Happy to answer questions about the process.&lt;/p&gt;

</description>
      <category>beginners</category>
    </item>
  </channel>
</rss>
