今日已更新 412 条资讯 | 累计 19972 条内容
关于我们

标签:#Android

找到 63 篇相关文章

AI 资讯

The Google / Xreal Aura XR glasses are now available to preorder

The Project Aura glasses collaboration between Xreal and Google is now one step closer to being something you can buy. Reservations for the second Android XR device, now dubbed the Xreal Aura, are available for $99 starting today, with a full launch in the US, UK, Japan, Canada, and South Korea expected sometime this Fall. […]

2026-06-17 原文 →
AI 资讯

android doze kills your react native background tasks--here's why and how to fix it

android doze kills your background tasks and nobody explains why properly been building a react native app that schedules stuff to run later. worked fine every time i tested it. shipped it, and it started missing schedules. only when the phone had been sitting idle for a while. never on my desk. took me way too long to figure out what was going on so writing it up here. what happens you schedule something for 1am. check logs next morning: 01:00:00 alarm fired 01:00:02 connected (while back grounded, 2 seconds) 01:18:xx the actual send ran the connection came up fine. in 2 seconds. while the phone was back grounded. but the code that was supposed to do something with that connection ran 18 minutes later when something else woke the phone up. why doze mode freezes javascript timers. setTimeout, setInterval, any polling loop on the js thread-all frozen. but native events (connection callbacks, lifecycle events, native module bridges) keep firing. i had a setInterval checking "are we connected yet" every second. doze froze that loop. the connection came up, nobody noticed for 18 minutes because the thing checking for it was asleep. the phone could do the work. my code just couldn't tell. stuff i tried that didn't fix it foreground service — keeps the process alive but doesn't unfreeze js timers. not the problem. more setTimeout/setInterval variations, literally the thing causing it. spent two days making the problem worse. HeadlessJS dropped in without changes compiled, never ran on newer RN. lost a few hours there. the actual fix move everything off timers. put your work directly in the event handler. instead of polling to check if you're connected: js // this is frozen by doze. don't. setInterval (() => { if ( isReady ()) doWork () }, 1000 ) do this : jsconnection . on ( ' status ' , ( state ) => { if ( state === ' connected ' ) { doWork ( job ) } }) native events survive doze. timers don't. that's the whole thing. for waking up at the right time — native AlarmManager

2026-06-16 原文 →
AI 资讯

Shipping an Android podcast player with on-device Whisper — 6 lessons from a Czech indie launch

After a year of nights and weekends, I shipped Lucidcast — an Android podcast player I built because every mainstream app I tried was missing the same three things. The app went live on Google Play this week. This post is for indie devs thinking about shipping their own Android project — six lessons I learned the expensive way. What Lucidcast does (90-second context) A podcast player with on-device AI: Whisper transcribes downloaded episodes locally (audio never leaves the phone) AI episode summaries via Gemini, with a live progress ring "Podcast" wake-word voice commands that work on the lock screen and in Android Auto Smart Pause auto-pauses on loud noises or when someone talks to you Plus the usual: chapters, transcripts, value tags (Podcasting 2.0), 22 languages, Android Auto, live radio, no accounts, no ads. Free includes the full podcast player. Pro one-time unlocks the audio intelligence engine. AI Pack subscription enables Whisper + summaries. Made in EU by a one-person Czech indie team (Prismatic s.r.o.). Play Store | Landing OK, lessons. 1. On-device Whisper is harder than it looks (NDK 29 patch needed) I wanted local transcription so audio doesn't leave the device. whisper_ggml is the only Flutter binding I found that works end-to-end. Catch: it needs Android NDK 29.0.13113456 while most other plugins are still on 27. Setting ndkVersion = "29..." in android/app/build.gradle.kts works for new builds, but the plugin's auto-detected version was sometimes off — needed a small patch script ( flutter/tool/patch_whisper_ggml.sh ) to enforce it during CI. Battery cost is real: I gate transcription to charging-only mode by default with a configurable battery threshold (10-80 %, default 50 %). When the user toggles "transcribe downloaded episodes," I queue the work but only execute when the phone is plugged in. Users on r/podcasts would otherwise notice a 5-10 % overnight battery drain. 2. Sharing the microphone is a contract nobody documents Smart Pause uses noise

2026-06-13 原文 →
AI 资讯

What Does Google Actually Look For During the 14-Day Closed Test?

You’ve spent weeks, maybe months, tracking down bugs, optimizing your user interface, and wrestling with backend security rules. You compile your native release build or run your final production compilations, thinking the hardest part of the journey is officially behind you. Then you open the Google Play Console, and you’re hit with the ultimate indie developer roadblock: the mandatory 12-tester and 14-day closed testing requirement . Many independent creators view this process as a simple download checklist. You might think, "I'll just find 12 people to download the app, leave it on their phones for two weeks, and wait it out." However, treating the testing phase as a static metric is the fastest way to get rejected during the final production access review. So, what is Google actually tracking in the background during these two weeks? Let’s take a deep dive into the core algorithmic requirement that determines your success: Continuous Engagement . 🔄 Decoding "Continuous Engagement" Google Play policies are not designed as a simple box-checking exercise. The underlying goal of the algorithm is to verify if your application is genuinely functional, stable, and being tested by an organic user base before it reaches millions of production users. To enforce this, Google's advanced systems actively monitor the devices connected to your closed test track over the 14-day timeline: Background Device Pings: Google Play Services regularly collects background automated signals (ping logs) from the devices where your test build is active. Real User Interaction: Leaving an app to rot in an application drawer without ever opening it is instantly flagged by the algorithm. Google measures whether the app is actively opened daily and tracks active interaction metrics within the build. Feedback Loops: The system monitors whether your test community is utilizing the internal testing channel on the Play Store to send private developer feedback and crash reports. 📉 The Illusion of "Ju

2026-06-10 原文 →
AI 资讯

Injecting WorkManager into ViewModels with Dagger Hilt. No Context, No Boilerplate, Always a WorkQuery Back

WorkManager is the right tool for deferrable, guaranteed background work in Android. But the default setup pushes you toward boilerplate fast: you end up calling WorkManager.getInstance(context) inside ViewModels, "passing Context where it doesn't belong", re-registering observers scattered across the codebase, and getting no consistent way to query the state of your enqueued work. This tutorial shows how to build a clean, injectable WorkManagerHandler using Dagger Hilt, a single interface that any ViewModel can receive through constructor injection, with zero Context and a guaranteed WorkQuery callback on every call so you always know what to observe. By the end, you'll have: A WorkManager singleton provided through Hilt A custom Configuration.Provider that plugs Hilt's HiltWorkerFactory into WorkManager at initialization A WorkManagerHandler interface with a WorkManagerHandlerImpl that encapsulates enqueueing, chaining, and query registration ViewModels that declare WorkManagerHandler as a plain constructor dependency The pattern scales cleanly as you add workers: each new worker is one method on the handler, and the ViewModel never knows or cares how work is scheduled underneath. Prerequisites : familiarity with Dagger Hilt basics, Jetpack WorkManager fundamentals, and Kotlin coroutines. A working Android project with Hilt already configured is assumed. Part 1: Application Setup and Custom Configuration.Provider By default, WorkManager initializes itself automatically using its own internal factory. The problem is that Hilt-injected workers need Hilt's factory HiltWorkerFactory to resolve their @Inject constructor dependencies. If you let WorkManager self-initialize, your workers won't have access to any of your Hilt bindings. The fix is to disable auto-initialization and take manual control via Configuration.Provider and AndroidManifest.xml 1. Disable auto-initialization In your AndroidManifest.xml , remove WorkManager's default initializer: <application ... > <

2026-06-10 原文 →
AI 资讯

I Built a Feature That Automatically Switches Android from USB to Wi-Fi — Here's How It Works

All tests run on an 8-year-old MacBook Air. All results from shipping 7 Mac apps as a solo developer. No sponsored opinion. You plug in your Android device. A few seconds later, you unplug the cable. The connection stays alive — wirelessly, automatically, without touching a single setting. That's Seamless Link. The Problem ADB over USB is reliable. ADB over Wi-Fi is convenient. But switching between them manually is friction: Plug in USB Run adb tcpip 5555 Find the device IP Run adb connect <IP>:5555 Unplug cable Every. Single. Time. If you're working with multiple Android devices, or doing this across multiple sessions per day, it adds up fast. What Seamless Link Does The moment you plug in a USB cable, Seamless Link runs that entire flow automatically in the background: Detects the USB connection Runs adb tcpip 5555 Grabs the device IP Establishes a Wi-Fi ADB connection By the time you've sat back down, the device is already connected wirelessly. Pull the cable out — everything keeps working. No manual steps. No IP hunting. No re-running commands every session. Working with Multiple Devices This gets more useful the more devices you have. Plug in Device A → Seamless Link connects it wirelessly. Plug in Device B → same thing, simultaneously. Each device goes through the full handover flow independently, in parallel. The more devices on your desk, the more time this saves. Android 16 Compatibility Android 16 changed how wireless debugging ports are assigned — random ports instead of the fixed 5555. Seamless Link handles this automatically. You don't need to know which port the device is using. If you're on an older Android version, it works the same way it always has. Why This Matters for Daily Workflows If you're an Android developer on Mac, you probably already have a USB cable on your desk. Seamless Link just makes that cable optional after the first few seconds. It's one of those features that's hard to go back from once you've used it. The cable becomes a "char

2026-06-08 原文 →
AI 资讯

🚀 Rebuilding My Android App with Jetpack Compose: The Mailfo v2.0 Journey

Hey DEV community! 👋 I just completely rebuilt and launched Mailfo v2.0 , an privacy-focused temporary disposable email app for Android[cite: 1, 2]. The first version got the job done, but it lacked the fluid user experience, offline reliability, and sleek UI that modern mobile apps need. I decided to tear it down and rewrite it from scratch using Jetpack Compose , Room DB , and modern Android architecture[cite: 1]. Here is a breakdown of what went into the rebuild, why privacy tools like this are essential, and what's new[cite: 1]. 🛡️ Why Use a Temporary Disposable Email? We’ve all been there: you want to download a single source-code snippet, test a new app, or sign up for a one-time service, but you don't want your primary inbox flooded with endless marketing spam[cite: 1]. A disposable email address acts as your personal buffer[cite: 1]. It protects your personal data, prevents tracker exposure, and keeps your real inbox clean[cite: 1]. ⚠️ Pro-tip: Mailfo is designed strictly for low-risk temporary email needs[cite: 1]. Do not use disposable email addresses for banking, legal accounts, or primary account recoveries[cite: 1]! 🛠️ The Tech Stack & Architecture Upgrades Moving from version 1.0 to 2.0 meant migrating away from legacy views to a fully declarative UI workflow[cite: 1, 2]. UI/UX Architecture: Built entirely with Jetpack Compose for smooth performance, a modern look, and native Light, Dark, and System theme switching[cite: 1]. Navigation: Implemented an intuitive bottom navigation system dividing the app into distinct Home, Inbox, and Profile tabs[cite: 1]. Caching & Offline Stability: Integrated a local Room SQLite database to cache inbox summaries and message data[cite: 1]. This guarantees instantaneous screen transitions without annoying network loading spinners[cite: 1]. ✨ Key Features in Mailfo v2.0 Custom & Random Email Generator: Instantly spin up a completely randomized address or build a custom email username using multiple searchable domains[ci

2026-06-08 原文 →
AI 资讯

Project Log #1: I'm Building an AI Agent That Controls a Phone

I'm starting a new project. It's the most ambitious thing I've attempted from a phone. The goal: an AI agent that controls a smartphone. It opens apps, navigates screens, taps buttons, types text, and completes multi-step tasks. All offline. All local. No cloud. This is Day 1 of a public build log. No fluff. Just what I'm building, how it works, and what breaks along the way. What I'm Building An autonomous AI agent that runs entirely on an Android phone. You give it a command in plain English: · "Open WhatsApp and message Mom I'll call later." · "Search for Kotlin jobs on Wellfound." · "Open my notes and summarize what I wrote yesterday." The agent parses the command, plans the steps, and executes them—opening apps, finding the right buttons, typing text, hitting send. No cloud. No API keys. Just a phone that acts on your behalf. The Stack Component Tool AI Brain Gemma 4 E4B (local, via Ollama) Runtime Termux (Linux on Android) Phone Control ADB + UI Automator Orchestration Python Why This Matters Most AI agents live in the cloud. They need internet, APIs, and someone else's server. A local agent that runs on a phone means: · Privacy: your data never leaves your device. · Offline: works even without internet. · Accessible: built for the device billions of people already own. The Hard Parts I Already See · The agent needs to "see" the screen to know where to tap. Text detection is doable. Image-based buttons are harder. · Multi-step tasks need verification. If one tap misses, the whole chain fails. · Android permissions. ADB requires developer mode. A user-facing version would need a workaround. What's Next · Day 2: Create the repo. Set up the project structure. Push the first working script. · Day 3: Get screen text detection working with OCR. · Day 4: Test a full 3-step task. This is Day 1. The repo goes live tomorrow. Follow along if you want to see something rare get built from scratch.

2026-06-08 原文 →
AI 资讯

I built a word puzzle RPG where you swipe letters to attack enemies — 2+ years solo, now live on Android

I just launched Kotobato on Google Play after about two and a half years of solo development. It's a word puzzle RPG — you swipe connected letters on a board to form words, and those words become attacks. Longer words deal more damage. Rarer words hit harder. I want to share what I built, why I built it this way, and what surprised me most during development. The core mechanic The board is a grid of letters. You swipe a path through connected letters to form a word. When you submit the word, it becomes an attack against the enemy. The twist: word length isn't the only thing that matters . The game has six elemental types — Animal, Nature, Knowledge, Food, Life, and Fantasy — and each word is categorized into one of these elements. Enemies have elemental weaknesses, so the right word beats a long word if you're hitting a weakness. This created an interesting design problem. In most word games, you're just maximizing point value. In Kotobato, you're making tactical choices: do I use a short word that hits a weakness, or a long word that deals raw damage? Why hiragana and English both work The game runs in both Japanese (hiragana) and English. This wasn't a late addition — it was part of the original design. Japanese hiragana is a syllabic script with 46 base characters. Because each character represents a whole syllable rather than a single phoneme, even short hiragana words feel phonetically "weighty." A 4-character hiragana word might correspond to an 8-letter English word in spoken syllables. This means the game feels different in each language — not just translated, but genuinely different. Japanese mode rewards knowledge of vocabulary that uses phonetically distinctive combinations. English mode rewards knowledge of unusual high-value words (think quixotic , ephemeral ). What I actually built 100-floor tower with escalating bosses, including historical Japanese figures like Oda Nobunaga and Toyotomi Hideyoshi Gacha character system — collectible characters with d

2026-06-07 原文 →
AI 资讯

Why MTP Batch Transfers Slow Down Between Files

All tests run on an 8-year-old MacBook Air. You're transferring a batch of large files over MTP. The first one flies at 45 MB/s. Then the second file starts — and you're at 30 MB/s. The third is slower still. Nothing changed. Same cable, same device, same app. So what's happening? The Cause Is in the Protocol Itself Between every file, MTP requires a full negotiation cycle — SendObjectInfo followed by SendObject . This isn't an implementation detail you can optimize away. It's how MTP works. During that gap, a few things happen in sequence: The Android device's flash controller is still committing the previous file to storage The USB pipe is flushed and re-established for the next object The device's MTP stack is processing metadata before it's ready to receive data again The result is a speed dip at every file boundary. The longer the previous file, the longer the device needs to catch up. What I Tried Building HiyokoMTP, I went through the obvious candidates: Tokio thread pool exhaustion — sync Read/Write calls blocking async threads were a real issue. Fixing it improved overall stability, but didn't eliminate the inter-file dip. Chunk size tuning — adjusting the USB bulk transfer buffer (up to 4 MB per chunk) helped peak throughput, but not the boundary behavior. Intentional cooldown between files — adding a short pause actually helped in some cases, giving the device's flash controller time to breathe before the next transfer starts. Why It Can't Be Fully Fixed The inter-file overhead is structural. MTP was designed as a stateful, command-response protocol — not a streaming pipeline. Every file is a discrete transaction with its own negotiation. There's no mechanism to pre-stage the next file while the current one is still writing. Non-async bulk transfer pipelining (similar to io_uring or Zero Copy USB) could theoretically reduce this, but it would require deep nusb-level changes and device-side support that most Android MTP stacks don't expose. MTP vs ADB: A F

2026-05-31 原文 →