نویسنده: post bot

  • Foundational Tools in Android | Kodeco

    Foundational Tools in Android | Kodeco


    Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive
    catalogue of 50+ books and 4,000+ videos.

    Learn more

    © 2025 Kodeco Inc



    Source link

  • Zoho Achieves 6x Faster Logins with Passkey and Credential Manager Integration



    Posted by Niharika Arora – Senior Developer Relations Engineer, Joseph Lewis – Staff Technical Writer, and Kumareshwaran Sreedharan – Product Manager, Zoho.

    As an Android developer, you’re constantly looking for ways to enhance security, improve user experience, and streamline development. Zoho, a comprehensive cloud-based software suite focused on security and seamless experiences, achieved significant improvements by adopting passkeys in their OneAuth Android app.

    Since integrating passkeys in 2024, Zoho achieved login speeds up to 6x faster than previous methods and a 31% month-over-month (MoM) growth in passkey adoption.

    This case study examines Zoho’s adoption of passkeys and Android’s Credential Manager API to address authentication difficulties. It details the technical implementation process and highlights the impactful results.

    Overcoming authentication challenges

    Zoho utilizes a combination of authentication methods to protect user accounts. This included Zoho OneAuth, their own multi-factor authentication (MFA) solution, which supported both password-based and passwordless authentication using push notifications, QR codes, and time-based one-time passwords (TOTP). Zoho also supported federated logins, allowing authentication through Security Assertion Markup Language (SAML) and other third-party identity providers.

    Challenges

    Zoho, like many organizations, aimed to improve authentication security and user experience while reducing operational burdens. The primary challenges that led to the adoption of passkeys included:

      • Security vulnerabilities: Traditional password-based methods left users susceptible to phishing attacks and password breaches.
      • User friction: Password fatigue led to forgotten passwords, frustration, and increased reliance on cumbersome recovery processes.
      • Operational inefficiencies: Handling password resets and MFA issues generated significant support overhead.
      • Scalability concerns: A growing user base demanded a more secure and efficient authentication solution.

    Why the shift to passkeys?

    Passkeys were implemented in Zoho’s apps to address authentication challenges by offering a passwordless approach that significantly improves security and user experience. This solution leverages phishing-resistant authentication, cloud-synchronized credentials for effortless cross-device access, and biometrics (such as a fingerprint or facial recognition), PIN, or pattern for secure logins, thereby reducing the vulnerabilities and inconveniences associated with traditional passwords.

    By adopting passkeys with Credential Manager, Zoho cut login times by up to 6x, slashed password-related support costs, and saw strong user adoption – doubling passkey sign-ins in 4 months with 31% MoM growth. Zoho users now enjoy faster, easier logins and phishing-resistant security.

    Quote card reads 'Cloud Lion now enjoys logins that are 30% faster and more secure using passkeys – allowing us to use our thumb instead of a password. With passkeys, we can also protect our critical business data against phishing and brute force attacks.' – Fabrice Venegas, Founder, Cloud Lion (a Zoho integration partner)

    Implementation with Credential Manager on Android

    So, how did Zoho achieve these results? They used Android’s Credential Manager API, the recommended Jetpack library for implementing authentication on Android.

    Credential Manager provides a unified API that simplifies handling of the various authentication methods. Instead of juggling different APIs for passwords, passkeys, and federated logins (like Sign in with Google), you use a single interface.

    Implementing passkeys at Zoho required both client-side and server-side adjustments. Here’s a detailed breakdown of the passkey creation, sign-in, and server-side implementation process.

    Passkey creation

    Passkey creation in OneAuth on a small screen mobile device

    To create a passkey, the app first retrieves configuration details from Zoho’s server. This process includes a unique verification, such as a fingerprint or facial recognition. This verification data, formatted as a requestJson string), is used by the app to build a CreatePublicKeyCredentialRequest. The app then calls the credentialManager.createCredential method, which prompts the user to authenticate using their device screen lock (biometrics, fingerprint, PIN, etc.).

    Upon successful user confirmation, the app receives the new passkey credential data, sends it back to Zoho’s server for verification, and the server then stores the passkey information linked to the user’s account. Failures or user cancellations during the process are caught and handled by the app.

    Sign-in

    The Zoho Android app initiates the passkey sign-in process by requesting sign-in options, including a unique challenge, from Zoho’s backend server. The app then uses this data to construct a GetCredentialRequest, indicating it will authenticate with a passkey. It then invokes the Android CredentialManager.getCredential() API with this request. This action triggers a standardized Android system interface, prompting the user to choose their Zoho account (if multiple passkeys exist) and authenticate using their device’s configured screen lock (fingerprint, face scan, or PIN). After successful authentication, Credential Manager returns a signed assertion (proof of login) to the Zoho app. The app forwards this assertion to Zoho’s server, which verifies the signature against the user’s stored public key and validates the challenge, completing the secure sign-in process.

    Server-side implementation

    Zoho’s transition to supporting passkeys benefited from their backend systems already being FIDO WebAuthn compliant, which streamlined the server-side implementation process. However, specific modifications were still necessary to fully integrate passkey functionality.

    The most significant challenge involved adapting the credential storage system. Zoho’s existing authentication methods, which primarily used passwords and FIDO security keys for multi-factor authentication, required different storage approaches than passkeys, which are based on cryptographic public keys. To address this, Zoho implemented a new database schema specifically designed to securely store passkey public keys and related data according to WebAuthn protocols. This new system was built alongside a lookup mechanism to validate and retrieve credentials based on user and device information, ensuring backward compatibility with older authentication methods.

    Another server-side adjustment involved implementing the ability to handle requests from Android devices. Passkey requests originating from Android apps use a unique origin format (android:apk-key-hash:example) that is distinct from standard web origins that use a URI-based format (https://example.com/app). The server logic needed to be updated to correctly parse this format, extract the SHA-256 fingerprint hash of the app’s signing certificate, and validate it against a pre-registered list. This verification step ensures that authentication requests genuinely originate from Zoho’s Android app and protects against phishing attacks.

    This code snippet demonstrates how the server checks for the Android-specific origin format and validates the certificate hash:

    val origin: String = clientData.getString("origin")
    
    if (origin.startsWith("android:apk-key-hash:")) { 
        val originSplit: List<String> = origin.split(":")
        if (originSplit.size > 3) {
                   val androidOriginHashDecoded: ByteArray = Base64.getDecoder().decode(originSplit[3])
    
                    if (!androidOriginHashDecoded.contentEquals(oneAuthSha256FingerPrint)) {
                throw IAMException(IAMErrorCode.WEBAUTH003)
            }
        } else {
            // Optional: Handle the case where the origin string is malformed    }
    }
    

    Error handling

    Zoho implemented robust error handling mechanisms to manage both user-facing and developer-facing errors. A common error, CreateCredentialCancellationException, appeared when users manually canceled their passkey setup. Zoho tracked the frequency of this error to assess potential UX improvements. Based on Android’s UX recommendations, Zoho took steps to better educate their users about passkeys, ensure users were aware of passkey availability, and promote passkey adoption during subsequent sign-in attempts.

    This code example demonstrates Zoho’s approach for how they handled their most common passkey creation errors:

    private fun handleFailure(e: CreateCredentialException) {
        val msg = when (e) {
            is CreateCredentialCancellationException -> {
                Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_CANCELLED", GROUP_NAME)
                Analytics.addNonFatalException(e)
                "The operation was canceled by the user."
            }
            is CreateCredentialInterruptedException -> {
                Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_INTERRUPTED", GROUP_NAME)
                Analytics.addNonFatalException(e)
                "Passkey setup was interrupted. Please try again."
            }
            is CreateCredentialProviderConfigurationException -> {
                Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_PROVIDER_MISCONFIGURED", GROUP_NAME)
                Analytics.addNonFatalException(e)
                "Credential provider misconfigured. Contact support."
            }
            is CreateCredentialUnknownException -> {
                Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_UNKNOWN_ERROR", GROUP_NAME)
                Analytics.addNonFatalException(e)
                "An unknown error occurred during Passkey setup."
            }
            is CreatePublicKeyCredentialDomException -> {
                Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_WEB_AUTHN_ERROR", GROUP_NAME)
                Analytics.addNonFatalException(e)
                "Passkey creation failed: ${e.domError}"
            }
            else -> {
                Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_FAILED", GROUP_NAME)
                Analytics.addNonFatalException(e)
                "An unexpected error occurred. Please try again."
            }
        }
    }
    

    Testing passkeys in intranet environments

    Zoho faced an initial challenge in testing passkeys within a closed intranet environment. The Google Password Manager verification process for passkeys requires public domain access to validate the relying party (RP) domain. However, Zoho’s internal testing environment lacked this public Internet access, causing the verification process to fail and hindering successful passkey authentication testing. To overcome this, Zoho created a publicly accessible test environment, which included hosting a temporary server with an asset link file and domain validation.

    This example from the assetlinks.json file used in Zoho’s public test environment demonstrates how to associate the relying party domain with the specified Android app for passkey validation.

    [
        {
            "relation": [
                "delegate_permission/common.handle_all_urls",
                "delegate_permission/common.get_login_creds"
            ],
            "target": {
                "namespace": "android_app",
                "package_name": "com.zoho.accounts.oneauth",
                "sha256_cert_fingerprints": [
                    "SHA_HEX_VALUE" 
                ]
            }
        }
    ]
    

    Integrate with an existing FIDO server

    Android’s passkey system utilizes the modern FIDO2 WebAuthn standard. This standard requires requests in a specific JSON format, which helps maintain consistency between native applications and web platforms. To enable Android passkey support, Zoho did minor compatibility and structural changes to correctly generate and process requests that adhere to the required FIDO2 JSON structure.

    This server update involved several specific technical adjustments:

    // Convert rawId bytes to a standard Base64 encoded string for storage
    val base64RawId: String = Base64.getEncoder().encodeToString(rawId.toByteArray())
    

        2. Transport list format: To ensure consistent data processing, the server logic handles lists of transport mechanisms (such as USB, NFC, and Bluetooth, which specify how the authenticator communicated) as JSON arrays.

        3. Client data alignment: The Zoho team adjusted how the server encodes and decodes the clientDataJson field. This ensures the data structure aligns precisely with the expectations of Zoho’s existing internal APIs. The example below illustrates part of the conversion logic applied to client data before the server processes it:

    private fun convertForServer(type: String): String {
        val clientDataBytes = BaseEncoding.base64().decode(type)
        val clientDataJson = JSONObject(String(clientDataBytes, StandardCharsets.UTF_8))
        val clientJson = JSONObject()
        val challengeFromJson = clientDataJson.getString("challenge")
        // 'challenge' is a technical identifier/token, not localizable text.
        clientJson.put("challenge", BaseEncoding.base64Url()
            .encode(challengeFromJson.toByteArray(StandardCharsets.UTF_8))) 
    
        clientJson.put("origin", clientDataJson.getString("origin"))
        clientJson.put("type", clientDataJson.getString("type"))
        clientJson.put("androidPackageName", clientDataJson.getString("androidPackageName"))
        return BaseEncoding.base64().encode(clientJson.toString().toByteArray())
    }
    

    User guidance and authentication preferences

    A central part of Zoho’s passkey strategy involved encouraging user adoption while providing flexibility to align with different organizational requirements. This was achieved through careful UI design and policy controls.

    Zoho recognized that organizations have varying security needs. To accommodate this, Zoho implemented:

      • Admin enforcement: Through the Zoho Directory admin panel, administrators can designate passkeys as the mandatory, default authentication method for their entire organization. When this policy is enabled, employees are required to set up a passkey upon their next login and use it going forward.
      • User choice: If an organization does not enforce a specific policy, individual users maintain control. They can choose their preferred authentication method during login, selecting from passkeys or other configured options via their authentication settings.

    To make adopting passkeys appealing and straightforward for end-users, Zoho implemented:

      • Easy setup: Zoho integrated passkey setup directly into the Zoho OneAuth mobile app (available for both Android and iOS). Users can conveniently configure their passkeys within the app at any time, smoothing the transition.
      • Consistent access: Passkey support was implemented across key user touchpoints, ensuring users can register and authenticate using passkeys via:
          • The Zoho OneAuth mobile app (Android & iOS);

    This method ensured that the process of setting up and using passkeys was accessible and integrated into the platforms they already use, regardless of whether it was mandated by an admin or chosen by the user. You can learn more about how to create smooth user flows for passkey authentication by exploring our comprehensive passkeys user experience guide.

    Impact on developer velocity and integration efficiency

    Credential Manager, as a unified API, also helped improve developer productivity compared to older sign-in flows. It reduced the complexity of handling multiple authentication methods and APIs separately, leading to faster integration, from months to weeks, and fewer implementation errors. This collectively streamlined the sign-in process and improved overall reliability.

    By implementing passkeys with Credential Manager, Zoho achieved significant, measurable improvements across the board:

      • Dramatic speed improvements
          • 2x faster login compared to traditional password authentication.
          • 4x faster login compared to username or mobile number with email or SMS OTP authentication.
          • 6x faster login compared to username, password, and SMS or authenticator OTP authentication.
      • Reduced support costs
          • Reduced password-related support requests, especially for forgotten passwords.
          • Lower costs associated with SMS-based 2FA, as existing users can onboard directly with passkeys.
      • Strong user adoption & enhanced security:
          • Passkey sign-ins doubled in just 4 months, showing high user acceptance.
          • Users migrating to passkeys are fully protected from common phishing and password breach threats.
          • With 31% MoM adoption growth, more users are benefiting daily from enhanced security against vulnerabilities like phishing and SIM swaps.

    Recommendations and best practices

    To successfully implement passkeys on Android, developers should consider the following best practices:

      • Leverage Android’s Credential Manager API:
          • Credential Manager simplifies credential retrieval, reducing developer effort and ensuring a unified authentication experience.
          • Handles passwords, passkeys, and federated login flows in a single interface.
      • Ensure data encoding consistency while migrating from other FIDO authentication solutions:
          • Make sure you handle consistent formatting for all inputs/outputs while migrating from other FIDO authentication solutions such as FIDO security keys.
      • Optimize error handling and logging:
          • Implement robust error handling for a seamless user experience.
          • Provide localized error messages and use detailed logs to debug and resolve unexpected failures.
      • Educate users on passkey recovery options:
          • Prevent lockout scenarios by proactively guiding users on recovery options.
      • Monitor adoption metrics and user feedback:
          • Track user engagement, passkey adoption rates, and login success rates to keep optimizing user experience.
          • Conduct A/B testing on different authentication flows to improve conversion and retention.

    Passkeys, combined with the Android Credential Manager API, offer a powerful, unified authentication solution that enhances security while simplifying user experience. Passkeys significantly reduce phishing risks, credential theft, and unauthorized access. We encourage developers to try out the experience in their app and bring the most secure authentication to their users.

    Get started with passkeys and Credential Manager

    Get hands on with passkeys and Credential Manager on Android using our public sample code.

    If you have any questions or issues, you can share with us through the Android Credentials issues tracker.



    Source link

  • Prepare your apps for Google Play’s 16 KB page size compatibility requirement



    Posted by Dan Brown – Product Manager, Google Play

    Google Play empowers you to manage and distribute your innovative and trusted apps and games to billions of users around the world across the entire breadth of Android devices, and historically, all Android devices have managed memory in 4 KB pages.

    As device manufacturers equip devices with more RAM to optimize performance, many will adopt larger page sizes like 16 KB. Android 15 introduces support for the increased page size, ensuring your app can run on these evolving devices and benefit from the associated performance gains.

    Starting November 1st, 2025, all new apps and updates to existing apps submitted to Google Play and targeting Android 15+ devices must support 16 KB page sizes.

    This is a key technical requirement to ensure your users can benefit from the performance enhancements on newer devices and prepares your apps for the platform’s future direction of improved performance on newer hardware. Without recompiling to support 16 KB pages, your app might not function correctly on these devices when they become more widely available in future Android releases.

    We’ve seen that 16 KB can help with:

      • Faster app launches: See improvements ranging from 3% to 30% for various apps.
      • Improved battery usage: Experience an average gain of 4.5%.
      • Quicker camera starts: Launch the camera 4.5% to 6.6% faster.
      • Speedier system boot-ups: Boot Android devices approximately 8% faster.

    We recommend checking your apps early especially for dependencies that might not yet be 16 KB compatible. Many popular SDK providers, like React Native and Flutter, already offer compatible versions. For game developers, several leading game engines, such as Unity, support 16 KB, with support for Unreal Engine coming soon.

    Reaching 16 KB compatibility

    A substantial number of apps are already compatible, so your app may already work seamlessly with this requirement. For most of those that need to make adjustments, we expect the changes to be minimal.

      • Apps with no native code should be compatible without any changes at all.
      • Apps using libraries or SDKs that contain native code may need to update these to a compatible version.
      • Apps with native code may need to recompile with a more recent toolchain and check for any code with incompatible low level memory management.

    Our December blog post, Get your apps ready for 16 KB page size devices, provides a more detailed technical explanation and guidance on how to prepare your apps.

    Check your app’s compatibility now

    It’s easy to see if your app bundle already supports 16 KB memory page sizes. Visit the app bundle explorer page in Play Console to check your app’s build compliance and get guidance on where your app may need updating.

    App bundle explorer in Play Console

    Beyond the app bundle explorer, make sure to also test your app in a 16 KB environment. This will help you ensure users don’t experience any issues and that your app delivers its best performance.

    For more information, check out the full documentation.

    Thank you for your continued support in bringing delightful, fast, and high-performance experiences to users across the breadth of devices Play supports. We look forward to seeing the enhanced experiences you’ll deliver with 16 KB support.



    Source link

  • Kodeco Podcast: Kotlin Symbol Processing – Podcast V2, S3 E4

    Kodeco Podcast: Kotlin Symbol Processing – Podcast V2, S3 E4


    If you’ve ever grumbled at boilerplate code or watched your Kotlin build crawl, this episode is your shortcut to sanity. Android engineer and Kodeco veteran Dean Djermanović joins us to break down Kotlin Symbol Processing (KSP) — a powerful tool for clean code and fast builds. Whether you’re new to KSP or curious how it stacks up against kapt, Dean brings real-world insights, practical tips, and an inspiring journey from coder to conference speaker. Tune in to learn why KSP might just be your new favorite dev tool.

    [Subscribe in Apple Podcasts] [Listen in Spotify] [RSS Feed]

    Interested in sponsoring a podcast episode? Check out our Advertise With Kodeco page to find out how!

    Show Notes

    Join Jenn and Dru as they chat with Android engineer and Kodeco contributor Dean Djermanović about Kotlin Symbol Processing (KSP). Whether you’re curious about speeding up your Kotlin builds or tired of repetitive boilerplate, KSP might be the tool you didn’t know you needed. Dean walks us through how it works, when to use it, and how he’s applied it to real-world projects.

    Highlights from this episode:

    • What Kotlin Symbol Processing (KSP) is and how it helps Kotlin developers generate code more efficiently.
    • The differences between KSP and kapt—and why KSP is now the preferred approach.
    • A step-by-step walkthrough of building a simple KSP processor.
    • How Dean used KSP in production to automate mapper class generation and reduce manual updates.
    • Tips for learning KSP, avoiding common pitfalls, and integrating it smoothly into your projects.

    Mentioned in This Episode

    • Kodeco’s Kotlin Symbol Processing Tutorial — Learn how to get rid of the boilerplate code within your app by using Kotlin Symbol Processor (KSP) to generate a class for creating Fragments.
    • DroidCon — Conferences where Dean has presented KSP use cases in real-world apps.
    • Kotlin Slack — Look for the #ksp channel to connect with the KSP team and other devs using it.
    • Fuel your brain and body with Eggs in a Basket.

    Contact Dean and the Hosts

    Follow Kodeco

    Where to Go From Here?

    We hope you enjoyed this episode of our podcast. Be sure to subscribe in Apple Podcasts or Spotify to get notified when the next episode comes out.

    Hoping to learn more about a particular aspect of mobile development or life and work as a dev? Please write in and tell us and we’ll do our best to make that happen! Write in too if you yourself would like to be a guest or your have a particular guest request and we’ll see what we can do. Drop a comment here, or email us anytime at podcast@teamkodeco.com.



    Source link

  • Galaxy S25 Edge photo leak lands ahead of Monday launch

    Galaxy S25 Edge photo leak lands ahead of Monday launch


    Samsung Galaxy S25 Edge (2)

    Paul Jones / Android Authority

    TL;DR

    • Samsung is just about to launch the Galaxy S25 Edge, an extra-thin variant of this year’s S25 flagship.
    • Ahead of Monday’s Unpacked event, new promotional imagery of the hardware has leaked.
    • We’re also getting a new look at a few cases and Samsung’s screen protector.

    It’s official: In just a few short days, on May 12, Samsung is formally launching the Galaxy S25 Edge. Depending on who you ask, the controversial extra-thin smartphone is either the most desirable flagship Samsung’s cooked up in a while, or a symbol of everything that’s wrong with modern phone design trends. You’ll be able to get your hands on the phone and make up your own mind soon. Until then, why wait all weekend for the official reveal when we’ve got a new leak to check out today that lays bare the S25 Edge and its accessories?

    What we’ve got here appears to be some very official-looking Samsung imagery shared by Android Headlines, detailing the S25 Edge and some of its stand-out features. That side-view teaser we first checked out back at the start of the month returns once again, though now in sharp focus, highlighting the handset’s slim build.

    galaxy s25 edge ah leak 06

    We can glean confirmation of a few camera details from these graphics, and spot that mention of ingress protection, but sadly these paint a less than complete picture of the hardware. While there’s no denying that’s a very svelte handset we’re looking at, Samsung doesn’t seem to be going out of its way to highlight the actual measurement (which we’ve heard before as 5.8mm thin) — not in this imagery, anyway.

    Although these pics aren’t overloaded with juicy specs, this image dump does manage to give us a nice preview of some of the cases set to be available for the Galaxy S25 Edge. We’re not saying that an extra-thin handset is necessarily going to be that much easier to accidentally drop, but we’d sure like to be covered, all the same. First up, we’ve got Samsung’s silicone case:

    If that one’s not to your taste, Samsung will also be bringing back its “Kindsuit” cases with that classy leather-esque finish:

    As you can see, all these will be available in a variety of colors, coordinated to match the hues the S25 Edge itself will arrive in. But if you’d rather just let the phones shine through, that’s an option, too:

    Lest you think we were playing a little fast and loose with that “accessory” label when we really meant “just cases,” we’re wrapping up this leak with Samsung’s screen-protection solution for the S25 Edge:

    Check back with Android Authority this coming Monday, May 12, for full coverage of the Samsung Galaxy S25 Edge launch.

    Got a tip? Talk to us! Email our staff at news@androidauthority.com. You can stay anonymous or get credit for the info, it’s your choice.



    Source link

  • How I Built a 7-Figure Business With This Simple Strategy

    How I Built a 7-Figure Business With This Simple Strategy


    Opinions expressed by Entrepreneur contributors are their own.

    One of the biggest mistakes entrepreneurs make is thinking they need to do everything themselves, or, even worse, thinking that hiring one “rockstar” full-time employee will solve every problem in their business (and if they do find this diamond in the rough, which is highly unlikely, they’re usually not in a position to hire and manage that person effectively). In my experience, I’ve found that success comes from not how you do it but who helps you do it, and a team of experts is the most effective way to get there.

    Today’s small business owners and solopreneurs are under more pressure than ever. The market is rapidly shifting, consumers are cautious about spending, and there’s a constant demand to stay visible and relevant in an increasingly crowded market. Entrepreneurs are expected to wear every hat, from visionary to strategist and social media manager, and still find time to grow their business. It’s insanity, isn’t it?

    After starting my business, I quickly realized that the most effective way for it to be successful was to bring on outside help. Through strategic outsourcing, I was able to grow my first business, the Boutique COO, to seven figures in under eight months.

    So, how do you know when it’s time to bring in outside help or where to even start? Here are four main steps to guide you.

    Related: How to Outsource Your Way to a $10-Million Business

    1. Stop trying to find your unicorn

    When most business owners realize they need help, their first instinct is to look for one full-time hire who can help manage ops, run their marketing campaigns, handle admin tasks and maybe even update the website and post on social media.

    That, my friends, is what we call a unicorn. They just don’t exist. And if they do, they’re either incredibly expensive or burned out from being pulled in a thousand directions. Plus, as a busy business owner who may not be comfortable with effective performance management or trained in it, you might not be able to best leverage your unicorn even if you found them.

    Early on in my business, I tried to find someone who could take a lot of things off my plate. I thought that if I could just find the right person, I’d be set. But in reality, no single human (including you) will be amazing at everything your business needs, and expecting them to be amazing is unfair.

    The better and smarter approach is to build a dream team of specialists who each do what they’re great at. Hire a bookkeeper who has a penchant for numbers. Bring on a virtual assistant who gets giddy about organization. Add a marketing specialist who loves to write. When everyone is working in their zone of genius and gets in their flow state, the quality of work skyrockets. The natural result is authentic and much more sustainable business growth.

    It’s also more cost-effective and less risky. Instead of paying a full-time salary plus benefits for one person, you can outsource even just a few ad hoc hours at a time for highly skilled support in each important area of your business. This way, you aren’t betting your business on a single person — and you get better results, spend less money and free up your own time. It’s a win-win.

    2. Identify the workload, not the title

    Before you start outsourcing, you need to stop thinking in terms of job titles. You don’t need a COO or a marketing manager (not yet, at least). What you do need is clarity on what tasks are taking up most of your time.

    Related: What You Need to Know Before Hiring Independent Contractors

    When I talk to clients whose businesses are taking off, I do a quick audit. I look at where they spend the most time and what drains their energy. If something is time-consuming and doesn’t provide much impact, that is a big red flag that the task either needs to be discontinued entirely or outsourced. Think in terms of categories that don’t necessarily contribute to revenue growth, like admin, onboarding new clients, invoicing and bookkeeping or the ever-dreaded payroll.

    Here’s a general rule: If your plate is full and you’re spending more than three to five hours a week on something that doesn’t require your specific expertise, outsource it.

    Related: Your Time is Money, Start Saving It By Outsourcing

    3. Decide what to outsource first

    Think about the tasks that don’t directly generate revenue or that someone else could do better and faster than you can.

    For most entrepreneurs, this includes tasks like

    • Scheduling and calendar management

    • Invoicing and payments

    • Emailing newsletters and planning social media

    • Doing basic admin, such as organizing files and documents

    When I first started outsourcing, I handed off two things that took a big chunk of my time but didn’t actually need my time: scheduling and inbox management. It was a small change, but the impact was massive. Not only did I gain back time during the week, but I also felt mentally clear enough to focus on strategies to grow my business.

    4. Set your contractors up for success

    Hiring help is just the first step. Being a good leader is what makes a huge difference.

    My non-negotiables: Be specific about expectations, and make your onboarding process crystal clear. Give your contractors access to the shared tools you use so they have everything they need to get started. At the Boutique COO and our new sister company, Brick by Brick Collective, we’re big fans of Notion and Paymo, and we basically live in Slack.

    Set up regular check-ins, especially during onboarding. Plan time to train contractors and give them feedback early on. Set clear goals and expectations. Your best hire will still feel ineffective if you aren’t investing in getting them ramped up.

    Be prepared to accept that things will be done 80% to 90% of the way you’d do it. If you expect someone to do something exactly how you’d do it, you are not weighing the benefit of outsourcing with the small cost of things not being exactly “perfect.” Remember, if you hire someone to clean your house or mow your lawn, you wouldn’t be complaining if they folded your clothes slightly differently than you do or if they did yardwork in a slightly different order.

    These tips have been instrumental in my growing a seven-figure business in under eight months, starting two new businesses and bringing on almost 150 team members without sacrificing my sanity.

    Related: What Not to Do When Outsourcing

    Do more with less, and build bigger than you’d thought possible

    Ultimately, it’s about asking a better question:

    Not “How can I get this done?” but “Who can help me get it done?” and “Who do I need to be to enable those people best?”

    If you’re truly ready to grow, pick one task you’re doing regularly that doesn’t require you to do it, and find someone to take it off your plate this week. You’ll be surprised at how much that tiny shift opens up everything else for you.

    Outsourcing is a strategy that, when done with intention, can be one of the most powerful ways to do more for your business and keep your clients (and you!) happy.



    Source link

  • Don’t just collect feedback. Act on it!

    Don’t just collect feedback. Act on it!


    In the retail industry, customer feedback is your early warning system, your innovation engine, and your most honest performance review. But this system only works if you take action on the feedback collected.  

    The best retail companies use feedback to inform product decisions, align teams around the Voice of the Customer, and fix what’s not quite working.  
     
    Here’s how to take insights from customer feedback and turn them into results.  

    The following post references our new e-guide, “The Retail Industry’s Blueprint to Leveling Up CX”. You can download the free e-guide, here

    Build a foundation that drives action  

    Turn survey responses, review data, and post-purchase feedback into clear dashboards your teams can actually use. Spot product issues, website friction, or shipping delays—then track them to resolution 

    Prioritize the issues that impact your bottom line. 

    Every retailer gets product complaints and feature requests. Start with the pain points that affect cart abandonment, store conversions, or customer churn—like long checkout lines, low in-store staff ratings, or hard-to-navigate mobile apps. 

    Assign ownership so nothing slips through the cracks 

    Route feedback to the right team. Whether it’s store ops, merchandising, digital, or support and clearly define who’s responsible for acting on it. When accountability is built in, customers are far more likely to see their feedback drive real change.  

    Close the loop with your customers 

    When you make a change based on feedback, say so. Let shoppers know you updated return policies, fixed a product page, or improved delivery tracking. Small touches build trust and show you’re listening. Salesforce research shows 62% of customers expect companies to adapt based on their behavior and feedback. 

    Monitor Net Promoter Score (NPS), CSAT, and repeat purchase rates. If you can show how a better pickup experience increased return visits or how fixing inventory visibility boosted conversion, you’ll have the data to back every CX investment.  

    Level it up! Make CX a lasting advantage 

    Once you’ve established a solid foundation, it’s time to level up your feedback strategy: 

    Segment feedback by shopper type and journey stage 

    A loyalty member leaving a negative review may need a different response than a first-time buyer. Segmenting by demographics, purchase history, and channel helps tailor your response and your fixes. 

    Use AI to uncover the “why” behind the feedback 

    Customers don’t always fill out perfect surveys, but they do leave clues in reviews, chat transcripts, and open-text feedback. New AI-powered tools help you uncover the emotion and sentiment behind each piece of feedback 

    PWC research shows that 32% of customers will walk away from a brand they love after just one bad experience, so finding and fixing root causes matters more than ever. 

    Automate follow-ups to scale a personalized experience 

    Send thank-you’s, discounts, or how-to content based on specific feedback triggers—like complaints about a confusing checkout or praise for a staff member. Automation ensures every customer feels heard without adding manual work. 

    Establish a continuous feedback loop. 

    Don’t wait for quarterly NPS reports. Set weekly or campaign-specific review cycles so you’re acting in near real time. Run quick post-purchase or post-service surveys to catch issues early. Before they show up in returns or lost sales. 

    Tie improvements to revenue. 

    Track the business impact of your CX investments. Forrester’s research shows that improving customer experience drives billions of dollars in increased revenue across industries, including retail. 

    Create a culture where everyone owns CX. 

    From cashiers to digital product managers, customer experience is everyone’s responsibility. Reinforce this with regular CX syncs, shout-outs for teams who act on feedback, and training on how to spot and solve customer pain points. 

    Continue reading  

    It’s no secret, the economy is a little uncertain right now. But remember, the retail brands that act on feedback most effectively are the brands that will emerge stronger with loyal customers, stronger pricing power, and a clearer understanding of what drives their success. 

    Out new (and free) e-guide, “The Retail Industry’s Blueprint to Leveling Up CX”, is a great place to get started.  

    Looking for something else? Checkout Alchemer’s solutions for retail and learn how we help you collect feedback, uncover insights, and act on them!



    Source link

  • Foundational Tools in iOS | Kodeco

    Foundational Tools in iOS | Kodeco


    Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive
    catalogue of 50+ books and 4,000+ videos.

    Learn more

    © 2025 Kodeco Inc



    Source link

  • Building delightful Android camera and media experiences



    Posted by Donovan McMurray, Mayuri Khinvasara Khabya, Mozart Louis, and Nevin Mital – Developer Relations Engineers

    Hello Android Developers!

    We are the Android Developer Relations Camera & Media team, and we’re excited to bring you something a little different today. Over the past several months, we’ve been hard at work writing sample code and building demos that showcase how to take advantage of all the great potential Android offers for building delightful user experiences.

    Some of these efforts are available for you to explore now, and some you’ll see later throughout the year, but for this blog post we thought we’d share some of the learnings we gathered while going through this exercise.

    Grab your favorite Android plush or rubber duck, and read on to see what we’ve been up to!

    Future-proof your app with Jetpack

    Nevin Mital

    One of our focuses for the past several years has been improving the developer tools available for video editing on Android. This led to the creation of the Jetpack Media3 Transformer APIs, which offer solutions for both single-asset and multi-asset video editing preview and export. Today, I’d like to focus on the Composition demo app, a sample app that showcases some of the multi-asset editing experiences that Transformer enables.

    I started by adding a custom video compositor to demonstrate how you can arrange input video sequences into different layouts for your final composition, such as a 2×2 grid or a picture-in-picture overlay. You can customize this by implementing a VideoCompositorSettings and overriding the getOverlaySettings method. This object can then be set when building your Composition with setVideoCompositorSettings.

    Here is an example for the 2×2 grid layout:

    object : VideoCompositorSettings {
      ...
    
      override fun getOverlaySettings(inputId: Int, presentationTimeUs: Long): OverlaySettings {
        return when (inputId) {
          0 -> { // First sequence is placed in the top left
            StaticOverlaySettings.Builder()
              .setScale(0.5f, 0.5f)
              .setOverlayFrameAnchor(0f, 0f) // Middle of overlay
              .setBackgroundFrameAnchor(-0.5f, 0.5f) // Top-left section of background
              .build()
          }
    
          1 -> { // Second sequence is placed in the top right
            StaticOverlaySettings.Builder()
              .setScale(0.5f, 0.5f)
              .setOverlayFrameAnchor(0f, 0f) // Middle of overlay
              .setBackgroundFrameAnchor(0.5f, 0.5f) // Top-right section of background
              .build()
          }
    
          2 -> { // Third sequence is placed in the bottom left
            StaticOverlaySettings.Builder()
              .setScale(0.5f, 0.5f)
              .setOverlayFrameAnchor(0f, 0f) // Middle of overlay
              .setBackgroundFrameAnchor(-0.5f, -0.5f) // Bottom-left section of background
              .build()
          }
    
          3 -> { // Fourth sequence is placed in the bottom right
            StaticOverlaySettings.Builder()
              .setScale(0.5f, 0.5f)
              .setOverlayFrameAnchor(0f, 0f) // Middle of overlay
              .setBackgroundFrameAnchor(0.5f, -0.5f) // Bottom-right section of background
              .build()
          }
    
          else -> {
            StaticOverlaySettings.Builder().build()
          }
        }
      }
    }
    

    Since getOverlaySettings also provides a presentation time, we can even animate the layout, such as in this picture-in-picture example:

    moving image of picture in picture on a mobile device

    Next, I spent some time migrating the Composition demo app to use Jetpack Compose. With complicated editing flows, it can help to take advantage of as much screen space as is available, so I decided to use the supporting pane adaptive layout. This way, the user can fine-tune their video creation on the preview screen, and export options are only shown at the same time on a larger display. Below, you can see how the UI dynamically adapts to the screen size on a foldable device, when switching from the outer screen to the inner screen and vice versa.

    What’s great is that by using Jetpack Media3 and Jetpack Compose, these features also carry over seamlessly to other devices and form factors, such as the new Android XR platform. Right out-of-the-box, I was able to run the demo app in Home Space with the 2D UI I already had. And with some small updates, I was even able to adapt the UI specifically for XR with features such as multiple panels, and to take further advantage of the extra space, an Orbiter with playback controls for the editing preview.

    moving image of suportive pane adaptive layout

    What’s great is that by using Jetpack Media3 and Jetpack Compose, these features also carry over seamlessly to other devices and form factors, such as the new Android XR platform. Right out-of-the-box, I was able to run the demo app in Home Space with the 2D UI I already had. And with some small updates, I was even able to adapt the UI specifically for XR with features such as multiple panels, and to take further advantage of the extra space, an Orbiter with playback controls for the editing preview.

    moving image of sequential composition preview in Android XR

    Orbiter(
      position = OrbiterEdge.Bottom,
      offset = EdgeOffset.inner(offset = MaterialTheme.spacing.standard),
      alignment = Alignment.CenterHorizontally,
      shape = SpatialRoundedCornerShape(CornerSize(28.dp))
    ) {
      Row (horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.mini)) {
        // Playback control for rewinding by 10 seconds
        FilledTonalIconButton({ viewModel.seekBack(10_000L) }) {
          Icon(
            painter = painterResource(id = R.drawable.rewind_10),
            contentDescription = "Rewind by 10 seconds"
          )
        }
        // Playback control for play/pause
        FilledTonalIconButton({ viewModel.togglePlay() }) {
          Icon(
            painter = painterResource(id = R.drawable.rounded_play_pause_24),
            contentDescription = 
                if(viewModel.compositionPlayer.isPlaying) {
                    "Pause preview playback"
                } else {
                    "Resume preview playback"
                }
          )
        }
        // Playback control for forwarding by 10 seconds
        FilledTonalIconButton({ viewModel.seekForward(10_000L) }) {
          Icon(
            painter = painterResource(id = R.drawable.forward_10),
            contentDescription = "Forward by 10 seconds"
          )
        }
      }
    }
    

    Jetpack libraries unlock premium functionality incrementally

    Donovan McMurray

    Not only do our Jetpack libraries have you covered by working consistently across existing and future devices, but they also open the doors to advanced functionality and custom behaviors to support all types of app experiences. In a nutshell, our Jetpack libraries aim to make the common case very accessible and easy, and it has hooks for adding more custom features later.

    We’ve worked with many apps who have switched to a Jetpack library, built the basics, added their critical custom features, and actually saved developer time over their estimates. Let’s take a look at CameraX and how this incremental development can supercharge your process.

    // Set up CameraX app with preview and image capture.
    // Note: setting the resolution selector is optional, and if not set,
    // then a default 4:3 ratio will be used.
    val aspectRatioStrategy = AspectRatioStrategy(
      AspectRatio.RATIO_16_9, AspectRatioStrategy.FALLBACK_RULE_NONE)
    var resolutionSelector = ResolutionSelector.Builder()
      .setAspectRatioStrategy(aspectRatioStrategy)
      .build()
    
    private val previewUseCase = Preview.Builder()
      .setResolutionSelector(resolutionSelector)
      .build()
    private val imageCaptureUseCase = ImageCapture.Builder()
      .setResolutionSelector(resolutionSelector)
      .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
      .build()
    
    val useCaseGroupBuilder = UseCaseGroup.Builder()
      .addUseCase(previewUseCase)
      .addUseCase(imageCaptureUseCase)
    
    cameraProvider.unbindAll()
    
    camera = cameraProvider.bindToLifecycle(
      this,  // lifecycleOwner
      CameraSelector.DEFAULT_BACK_CAMERA,
      useCaseGroupBuilder.build(),
    )
    

    After setting up the basic structure for CameraX, you can set up a simple UI with a camera preview and a shutter button. You can use the CameraX Viewfinder composable which displays a Preview stream from a CameraX SurfaceRequest.

    // Create preview
    Box(
      Modifier
        .background(Color.Black)
        .fillMaxSize(),
      contentAlignment = Alignment.Center,
    ) {
      surfaceRequest?.let {
        CameraXViewfinder(
          modifier = Modifier.fillMaxSize(),
          implementationMode = ImplementationMode.EXTERNAL,
          surfaceRequest = surfaceRequest,
         )
      }
      Button(
        onClick = onPhotoCapture,
        shape = CircleShape,
        colors = ButtonDefaults.buttonColors(containerColor = Color.White),
        modifier = Modifier
          .height(75.dp)
          .width(75.dp),
      )
    }
    
    fun onPhotoCapture() {
      // Not shown: defining the ImageCapture.OutputFileOptions for
      // your saved images
      imageCaptureUseCase.takePicture(
        outputOptions,
        ContextCompat.getMainExecutor(context),
        object : ImageCapture.OnImageSavedCallback {
          override fun onError(exc: ImageCaptureException) {
            val msg = "Photo capture failed."
            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
          }
    
          override fun onImageSaved(output: ImageCapture.OutputFileResults) {
            val savedUri = output.savedUri
            if (savedUri != null) {
              // Do something with the savedUri if needed
            } else {
              val msg = "Photo capture failed."
              Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
            }
          }
        },
      )
    }
    

    You’re already on track for a solid camera experience, but what if you wanted to add some extra features for your users? Adding filters and effects are easy with CameraX’s Media3 effect integration, which is one of the new features introduced in CameraX 1.4.0.

    Here’s how simple it is to add a black and white filter from Media3’s built-in effects.

    val media3Effect = Media3Effect(
      application,
      PREVIEW or IMAGE_CAPTURE,
      ContextCompat.getMainExecutor(application),
      {},
    )
    media3Effect.setEffects(listOf(RgbFilter.createGrayscaleFilter()))
    useCaseGroupBuilder.addEffect(media3Effect)
    

    The Media3Effect object takes a Context, a bitwise representation of the use case constants for targeted UseCases, an Executor, and an error listener. Then you set the list of effects you want to apply. Finally, you add the effect to the useCaseGroupBuilder we defined earlier.

    moving image of sequential composition preview in Android XR

    (Left) Our camera app with no filter applied. 
     (Right) Our camera app after the createGrayscaleFilter was added.

    There are many other built-in effects you can add, too! See the Media3 Effect documentation for more options, like brightness, color lookup tables (LUTs), contrast, blur, and many other effects.

    To take your effects to yet another level, it’s also possible to define your own effects by implementing the GlEffect interface, which acts as a factory of GlShaderPrograms. You can implement a BaseGlShaderProgram’s drawFrame() method to implement a custom effect of your own. A minimal implementation should tell your graphics library to use its shader program, bind the shader program’s vertex attributes and uniforms, and issue a drawing command.

    Jetpack libraries meet you where you are and your app’s needs. Whether that be a simple, fast-to-implement, and reliable implementation, or custom functionality that helps the critical user journeys in your app stand out from the rest, Jetpack has you covered!

    Jetpack offers a foundation for innovative AI Features

    Mayuri Khinvasara Khabya

    Just as Donovan demonstrated with CameraX for capture, Jetpack Media3 provides a reliable, customizable, and feature-rich solution for playback with ExoPlayer. The AI Samples app builds on this foundation to delight users with helpful and enriching AI-driven additions.

    In today’s rapidly evolving digital landscape, users expect more from their media applications. Simply playing videos is no longer enough. Developers are constantly seeking ways to enhance user experiences and provide deeper engagement. Leveraging the power of Artificial Intelligence (AI), particularly when built upon robust media frameworks like Media3, offers exciting opportunities. Let’s take a look at some of the ways we can transform the way users interact with video content:

      • Empowering Video Understanding: The core idea is to use AI, specifically multimodal models like the Gemini Flash and Pro models, to analyze video content and extract meaningful information. This goes beyond simply playing a video; it’s about understanding what’s in the video and making that information readily accessible to the user.
      • Actionable Insights: The goal is to transform raw video into summaries, insights, and interactive experiences. This allows users to quickly grasp the content of a video and find specific information they need or learn something new!
      • Accessibility and Engagement: AI helps make videos more accessible by providing features like summaries, translations, and descriptions. It also aims to increase user engagement through interactive features.

    A Glimpse into AI-Powered Video Journeys

    The following example demonstrates potential video journies enhanced by artificial intelligence. This sample integrates several components, such as ExoPlayer and Transformer from Media3; the Firebase SDK (leveraging Vertex AI on Android); and Jetpack Compose, ViewModel, and StateFlow. The code will be available soon on Github.

    moving images of examples of AI-powered video journeys

    (Left) Video summarization  
     (Right) Thumbnails timestamps and HDR frame extraction

    There are two experiences in particular that I’d like to highlight:

      • HDR Thumbnails: AI can help identify key moments in the video that could make for good thumbnails. With those timestamps, you can use the new ExperimentalFrameExtractor API from Media3 to extract HDR thumbnails from videos, providing richer visual previews.
      • Text-to-Speech: AI can be used to convert textual information derived from the video into spoken audio, enhancing accessibility. On Android you can also choose to play audio in different languages and dialects thus enhancing personalization for a wider audience.

    Using the right AI solution

    Currently, only cloud models support video inputs, so we went ahead with a cloud-based solution.Iintegrating Firebase in our sample empowers the app to:

      • Generate real-time, concise video summaries automatically.
      • Produce comprehensive content metadata, including chapter markers and relevant hashtags.
      • Facilitate seamless multilingual content translation.

    So how do you actually interact with a video and work with Gemini to process it? First, send your video as an input parameter to your prompt:

    val promptData =
    "Summarize this video in the form of top 3-4 takeaways only. Write in the form of bullet points. Don't assume if you don't know"
    
    val generativeModel = Firebase.vertexAI.generativeModel("gemini-2.0-flash")
    _outputText.value = OutputTextState.Loading
    
    viewModelScope.launch(Dispatchers.IO) {
        try {
            val requestContent = content {
                fileData(videoSource.toString(), "video/mp4")
                text(prompt)
            }
            val outputStringBuilder = StringBuilder()
    
            generativeModel.generateContentStream(requestContent).collect { response ->
                outputStringBuilder.append(response.text)
                _outputText.value = OutputTextState.Success(outputStringBuilder.toString())
            }
    
            _outputText.value = OutputTextState.Success(outputStringBuilder.toString())
    
        } catch (error: Exception) {
            _outputText.value = error.localizedMessage?.let { OutputTextState.Error(it) }
        }
    }
    

    Notice there are two key components here:

      • FileData: This component integrates a video into the query.
      • Prompt: This asks the user what specific assistance they need from AI in relation to the provided video.

    Of course, you can finetune your prompt as per your requirements and get the responses accordingly.

    In conclusion, by harnessing the capabilities of Jetpack Media3 and integrating AI solutions like Gemini through Firebase, you can significantly elevate video experiences on Android. This combination enables advanced features like video summaries, enriched metadata, and seamless multilingual translations, ultimately enhancing accessibility and engagement for users. As these technologies continue to evolve, the potential for creating even more dynamic and intelligent video applications is vast.

    Go above-and-beyond with specialized APIs

    Mozart Louis

    Android 16 introduces the new audio PCM Offload mode which can reduce the power consumption of audio playback in your app, leading to longer playback time and increased user engagement. Eliminating the power anxiety greatly enhances the user experience.

    Oboe is Android’s premiere audio api that developers are able to use to create high performance, low latency audio apps. A new feature is being added to the Android NDK and Android 16 called Native PCM Offload playback.

    Offload playback helps save battery life when playing audio. It works by sending a large chunk of audio to a special part of the device’s hardware (a DSP). This allows the CPU of the device to go into a low-power state while the DSP handles playing the sound. This works with uncompressed audio (like PCM) and compressed audio (like MP3 or AAC), where the DSP also takes care of decoding.

    This can result in significant power saving while playing back audio and is perfect for applications that play audio in the background or while the screen is off (think audiobooks, podcasts, music etc).

    We created the sample app PowerPlay to demonstrate how to implement these features using the latest NDK version, C++ and Jetpack Compose.

    Here are the most important parts!

    First order of business is to assure the device supports audio offload of the file attributes you need. In the example below, we are checking if the device support audio offload of stereo, float PCM file with a sample rate of 48000Hz.

           val format = AudioFormat.Builder()
                .setEncoding(AudioFormat.ENCODING_PCM_FLOAT)
                .setSampleRate(48000)
                .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
                .build()
    
            val attributes =
                AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .build()
           
            val isOffloadSupported = 
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    AudioManager.isOffloadedPlaybackSupported(format, attributes)
                } else {
                    false
                }
    
            if (isOffloadSupported) {
                player.initializeAudio(PerformanceMode::POWER_SAVING_OFFLOADED)
            }
    

    Once we know the device supports audio offload, we can confidently set the Oboe audio streams’ performance mode to the new performance mode option, PerformanceMode::POWER_SAVING_OFFLOADED.

    // Create an audio stream
            AudioStreamBuilder builder;
            builder.setChannelCount(mChannelCount);
            builder.setDataCallback(mDataCallback);
            builder.setFormat(AudioFormat::Float);
            builder.setSampleRate(48000);
    
            builder.setErrorCallback(mErrorCallback);
            builder.setPresentationCallback(mPresentationCallback);
            builder.setPerformanceMode(PerformanceMode::POWER_SAVING_OFFLOADED);
            builder.setFramesPerDataCallback(128);
            builder.setSharingMode(SharingMode::Exclusive);
               builder.setSampleRateConversionQuality(SampleRateConversionQuality::Medium);
            Result result = builder.openStream(mAudioStream);
    

    Now when audio is played back, it will be offloading audio to the DSP, helping save power when playing back audio.

    There is more to this feature that will be covered in a future blog post, fully detailing out all of the new available APIs that will help you optimize your audio playback experience!

    What’s next

    Of course, we were only able to share the tip of the iceberg with you here, so to dive deeper into the samples, check out the following links:

    Hopefully these examples have inspired you to explore what new and fascinating experiences you can build on Android. Tune in to our session at Google I/O in a couple weeks to learn even more about use-cases supported by solutions like Jetpack CameraX and Jetpack Media3!



    Source link

  • Big Changes Are Coming to Netflix’s App on Apple TV, iOS

    Big Changes Are Coming to Netflix’s App on Apple TV, iOS


    First up, Netflix on the big screen will change for the better. Here’s some of what to expect:

    • Discover Your Next Great Watch More Easily: We’re putting all the information you need to make an informed choice about what to watch front and center. That way you can better focus on what makes each title relevant for you, with callouts like “Emmy Award Winner” or “#1 in TV Shows.”
    • More Visible Shortcuts: Until now, shortcuts to Search and My List were somewhat hidden on the left-hand side. We’re moving them to the top of the page where they’re more noticeable and easier to access.
    • Better Realtime Recommendations: We’re making the recommendations on the homepage more responsive to your moods and interests in the moment.
    • Elevated Design: The new homepage has a clean and modern design that better reflects the elevated experience you’ve come to expect on Netflix.

    And on the smaller screen of your iPhone or iPad, the streaming service will also look different.

    •A New Way to Search: We’re also exploring ways to bring Generative AI to our members’ discovery experience, starting with a search feature on iOS that is a small opt-in beta. This will allow members to search for shows and movies using natural, conversational phrases like “I want something funny and upbeat.”
    • A New Way to Discover: In the coming weeks, we’ll be testing a vertical feed filled with clips of Netflix shows and movies to make discovery easy and fun. You’ll be able to tap to watch the whole show or movie immediately, add it to My List, or share with friends.

    All of the changes will arrive “in the coming weeks and months” according to Netflix.



    Source link