- Android Enterprise offers job profiles, dedicated devices, and managed configurations to securely manage corporate apps and data.
- Professional development requires a comprehensive training path and a modern architecture based on layers, data models, and unidirectional flow.
- The combination of testing with Test DPC, SSO with custom tabs, and DI best practices ensures scalable, secure, and enterprise-ready apps.
If you're getting into the Android world, sooner or later you're going to need some... Good Android guides that explain both the business side and the app development side.Knowing how to program a couple of screens is not enough: nowadays you need to understand job profiles, managed devices, modern architecture, security, SSO, testing… and much more.
In this comprehensive guide you will find a A complete and up-to-date overview of how to develop Android apps designed for businesses and for multiple devicesFrom the fundamentals of Android Enterprise and device management to structuring code with a robust and scalable architecture, this course will help you develop a clear mental map of everything you need to master to create professional and easily maintainable applications.
Android Enterprise: How to prepare your apps for corporate environments
Android includes a set of standard features Enterprise features that enable organizations to securely manage devices, apps, and dataThe good news is that any standard Android app supports these features; the not-so-good news is that if you want your app to shine in corporate environments, you'll have to go a step further and adapt it.
To get the most out of Android Enterprise, it's best to start with a Android app already created, ready to modify and with a minimum version of 5.0 Lollipop (although 6.0 Marshmallow or higher is recommended). These later levels offer advanced capabilities, especially for dedicated devices and stricter management policies.
Organizations use these features to enable Managed mobility scenarios: from employee mobiles with separate personal and work data, to single-use kiosksAs a developer, you'll want to understand this ecosystem to avoid incompatibilities and, above all, to prevent limiting the adoption of your app by businesses.
Work profiles on Android: separation between personal and professional life
The key concept of Android Enterprise is the work profile, a corporate container managed within the user's deviceThis profile is associated with the device's main account, but maintains a clear separation between applications and personal and professional data.
In practice, the job profile acts as a isolated space where enterprise apps carry a specific badge and are managed with their own policiesThe user retains control of their personal space, while the IT department only manages the business data and applications that interest them, without invading the rest of the device.
Among the most important characteristics of a job profile are the following: secure data separation, app distribution via managed Google Play, and specific management capabilities controlled by an administrator, all backed up by full device encryption.
One important detail is that, when the device has both personal and work profiles, it is usually used a single APK for both spaces, while the policy controller (DPC) is restricted to the work profileAdministration is done through the DevicePolicyManager class, which means you need to take these APIs into account if you develop advanced enterprise solutions.
To avoid problems, it is important that Don't assume that any Intent will simply be able to cross from one profile to another.Some are blocked for security reasons, and you'll only discover this through testing. Before launching an activity, it's advisable to call Intent.resolveActivity()If it returns null, it means there is no component that can handle that Intent in that profile.
When exchanging files between profiles, Android recommends using Content URIs with FileProvider, shared via Intents with specific permissionsThis ensures that access is limited to the correct profile and that other apps only see what is essential. In contrast, the old file:// URIs that point to absolute file system paths do not work across profiles and can cause failures when trying to open resources from the other side.
Managed configurations: remote control of the app by IT
A fundamental pillar in corporate environments is the Managed configurations, a set of parameters that administrators can remotely apply to apps of the users. The big advantage is that they are universal: they work with any EMM (Enterprise Mobility Management) solution.
Thanks to these configurations, the IT department can centrally adjust how the application behaves in critical areas such as connectivity, security, or usage restrictionsFor example, you can decide whether the app syncs only over Wi-Fi or also over mobile data, which URLs are allowed in an integrated browser, how the email account is configured, whether or not printing is enabled, or which favorites are preloaded.
From the developer's point of view, the key is in Check these restrictions at the appropriate times in the app lifecycleAt startup, it's advisable for the code to check in onStart() or onResume() the result of getApplicationRestrictions() to find out if the app is managed, if there are restrictions already defined, or if there is a pending configuration status.
The value returned by getApplicationRestrictions() can be a package with specific restrictions, an empty package, or a structure with the key KEY_RESTRICTIONS_PENDINGIn this last case, your app knows it is under administration, but the DPC has not yet applied the policy correctly, so the prudent thing to do is restrict its use and guide the user to contact the IT administrator.
Furthermore, policies can change at any time, which is why your app must Detect live modifications by dynamically logging the ACTION_APPLICATION_RESTRICTIONS_CHANGED broadcastIdeally, you should subscribe when the activity or service is active and cancel the registration using onPause(), to avoid leaks or unexpected behavior.
Dedicated devices: kiosks, POS systems and digital signage
Another widespread practice in companies is the use of single-purpose devices (dedicated devices), such as kiosks, POS systems, or signage displaysIn these cases, Android is configured to show only one app or a very limited set, blocking access to the main or recent apps.
When a device is set up as dedicated, the user sees a single, controlled experience, with no easy way to escape the main appYou can also define a group of allowed applications, for example in a library kiosk that only displays the catalog and a corporate web browser.
To reach these scenarios, it is necessary to follow the flows of Provision of dedicated devices as described in the official documentationIn these scenarios, the DPC assumes the role of device owner. As a developer, you must ensure your app can run in kiosk mode, without standard navigation buttons or multitasking, and that it responds well to controlled crashes and restarts.
Single sign-on (SSO) with custom Chrome tabs
In the business world, it's very common for users to have to authenticate in several different apps, and if the experience isn't carefully managed, it can end up... repeating username and password over and over againWebView has traditionally been used for login, but this solution has clear disadvantages.
On the one hand, many implementations with WebView do not offer a True SSO, because each WebView manages its own cookies and sessionOn the other hand, there are security risks, since it is possible to inspect cookies or inject malicious JavaScript if any third-party app or SDK behaves inappropriately.
The recommended alternative is to take advantage of the Custom tabs, especially Chrome's Custom Tabs, which have been present since Chrome 45.These tabs act as an integrated system browser view, with a secure context where the host app cannot snoop on the content.
When using Custom Tabs for authentication, the browser-wide cookie status, enabling single sign-on across multiple appsThe user logs in only once, and the rest of the applications can rely on that already authenticated context, improving usability and reducing friction.
To implement SSO with Custom Tabs, you can use AppAuth, an open-source OAuth client library supported by the OpenID Connect working groupThis library simplifies integration with identity providers and handles the security details and compatibility with custom tabs.
App testing in managed environments: DPC testing, profiles, and devices
Once you've added support for work profiles, managed configurations, and dedicated devices, it's time for the less glamorous but more critical part: Test your app on both work profiles and truly managed devicesThis is where the Test DPC application comes into play.
Test DPC is a App designed for developers that simulates the behavior of an enterprise DPC in a test environmentWith it, you can set EMM policies and managed configuration values as if an organization were managing the device through its console.
To test your app in a work profile, the basic workflow is Install Test DPC, open the Test DPC configuration option in the Android selector, and follow the instructions to provision the working profile.Then you install your app and check how it behaves in that profile with a work badge, verifying permissions, Intents, data access, and other sensitive behaviors.
If you want to simulate a fully managed device, you must Make sure the terminal does not have any other users, work profiles, or accounts configured.Next, install Test DPC and run the following command in adb:
adb shell dpm set-device-owner com.afwsamples.testdpc/.DeviceAdminReceiver
Upon completion of this process, the device will be under the full control of Test DPC as the device ownerFrom there, you can test your app in a context of absolute administration, paying special attention to how managed configurations are applied, how restricted Intents react, and what happens to the app in blocking scenarios and strict policies.
Once you've validated the behavior in local tests, the ideal thing to do is take it a step further and do a end-to-end testing in a real cloud environment, replicating the flow that a customer would followThis involves having a test EMM console, claiming a managed Google domain, linking it to that console, and publishing a test version of your app (with a different ApplicationId) in the private Google Play channel of that domain.
From the EMM console you will be able to Configure work devices, distribute the app, set your managed configurations, and set device policiesThis way you verify that everything works as it would in a production deployment, from initial registration to the application of advanced policies.
Android learning guides: from beginner to advanced
Beyond the purely business aspect, if you want to become a good Android developer you need a a structured learning path that covers everything from basic concepts to advanced topics and stay up to date with Technology news about mobile phones, apps and digital cultureIn this sense, guides or courses that divide the content into levels—beginner, intermediate, and advanced—are very useful.
In the initial phase, the focus is on Fundamentals of Android, Kotlin or Java, activity lifecycle, basic views and layout creationMany modern resources are now 100% focused on Kotlin, but there are still excellent books and materials based on Java and environments like Eclipse that, although somewhat outdated, are still useful for understanding the evolution of the platform.
As you progress, it's key to introduce topics such as data persistence, concurrent programming, security, network communication, and testingIt's also a good idea to familiarize yourself with Fragment, modern architectures, and concepts like modularization, so that your projects don't become chaotic as they grow.
At the advanced level, they already come into play Publishing on Google Play, version management, monetization, protection of paid apps (e.g., with LVL), and update mechanismsTopics such as AppWidgets, geolocation access, performance optimization, support for multiple Android versions, and adaptation to tablets and foldable devices are also commonly covered.
Some classic textbooks cover From preparing the development environment, creating the first app, designing the user interface, to the final deployment in productionAs an added value, they are usually accompanied by downloadable example projects that practically illustrate everything explained in the text.
Modern Android app architecture: a foundation for serious projects
If you want your app to not fall apart as soon as it grows a little, you need a A well-designed app architecture, capable of scaling and adapting to mobiles, tablets, foldables, ChromeOS, cars, and XR devices.The idea is to minimize dependence on framework components and ensure that the code is easy to maintain and test.
A typical Android app consists of multiple components declared in the manifesto: services, content providers, broadcast recipients, and activitiesHistorically, the user interface was organized with several activities, but the current recommendation is to use an architecture of unique activity with screens based on fragments or Jetpack Compose destinations.
Since your app can run on very different devices, you can't assume neither a fixed orientation nor a single screen sizeConfiguration changes (rotation, window changes in ChromeOS, folding a foldable device) require recomposing the interface and can cause component recreations, so any important state should be kept outside of Activities and Fragments.
Furthermore, Android is a resource-constrained environment where the system It can kill background app processes to free up memoryIt can also start components in a disordered way and destroy them without warning. Hence the classic recommendation: do not store state or business data in Activities, Services, or BroadcastReceivers, because they are ephemeral by nature.
The guiding principle is the Separation of responsibilities: the UI is responsible for displaying data and responding to events, while business logic and data handling reside in other layers.Thus, when an interface component is recreated, the state persists thanks to well-organized ViewModels, repositories, and data sources.
Architecture layers: UI, data, and domain
The recommended architecture distinguishes at least two layers: UI (presentation) layer and data layerOptionally, a third domain layer can be added to encapsulate complex or reusable business logic between different ViewModels.
The UI layer is responsible for display data on screen and react to changesThis occurs either through user actions or external inputs such as network responses. This is where visual elements (views or composables from Jetpack Compose) and state containers (ViewModel) come into play, maintaining and exposing the interface state.
In adaptive interfaces, ViewModels are usually expose a state that already takes into account the window size classusing utilities such as currentWindowAdaptiveInfo(). Components such as NavigationSuiteScaffold can rely on this information to automatically switch between NavigationBar, NavigationRail, or NavigationDrawer depending on the available space.
The data layer concentrates the business logic and the rules that determine how data is created, stored, and modifiedIt is based on repositories that group and abstract one or more data sources: local databases, network services, files, etc. Each type of information (movies, payments, users, etc.) usually has its own repository responsible for exposing data, centralizing changes, and resolving conflicts.
Data sources are the classes that They communicate directly with the system or with external services: SQL queries, file access, HTTP requests, etc.The rest of the app should not depend on its specific implementation, but only on the interfaces exposed by the repository.
As complexity increases, it is useful to introduce a domain layer consisting of use cases or interactors, each dedicated to a specific functionalityFor example, a GetTimeZoneUseCase that returns the appropriate time zone to construct custom messages, reusable by multiple ViewModels.
Data models, SSOT, and unidirectional data flow
Another key principle is that the interface should feed with data models, preferably persistent onesThese models represent the app's state and are completely independent of the UI and the framework component lifecycle. This way, they survive recreations of Activities and Fragments, and only disappear when the system terminates the process.
Related to this, it is worthwhile to apply the pattern of single source of truth (SSOT)Each important data type has a single owner who can modify it; the other layers only observe it through immutable types. Mutations are performed through well-defined functions or through events that reach that source of truth.
The SSOT is usually combined with the unidirectional data flow (UDF), in which state flows from top to bottom and events flow from bottom to topIn Android, this means that application data travels from the sources (network, database) to the UI, while user actions are transformed into events that travel from the UI to the domain or data layer, where the state is updated.
Following this pattern improves the State consistency reduces errors, facilitates reasoning about app behavior, and simplifies debugging.Having a single component that controls how the data changes makes it easier to pinpoint the source of a fault.
Dependency injection and general best practices
To enable the different classes of the app to cooperate without unnecessary coupling, it is recommended to use a dependency management pattern such as dependency injection (DI) or a service locatorIn Android, the go-to solution is Hilt, which automates object building, checks for dependencies at compile time, and creates specific containers for framework components.
The idea is that the classes State what you need, but don't take charge of building it.This allows you to easily switch from the live implementation to a test version, or adjust behaviors without rewriting half the project. Furthermore, it reduces duplication and clearly outlines how each piece connects in one place.
As general rules of architecture, it is advisable that the Entry points (activities, services, receivers) are not data sourcesInstead, they are simply coordinators that request the necessary information from the repository or use case. It is also recommended to minimize dependencies on Android classes outside of UI components to facilitate testing.
It is important to define Clear boundaries of responsibility between modules, avoiding mixing network code, caching, view binding, and business logic in the same classEach module should expose only what is necessary, without shortcuts that reveal internal implementation details and could become technical debt in the future.
Another recurring piece of advice is Don't reinvent the wheel: rely on Jetpack libraries and established solutions for standard tasks (navigation, persistence, pagination, etc.). Reserve your time for what makes your app special, instead of rewriting the same infrastructure code over and over again.
When designing the UI, it is advisable to opt for reusable and composable components that can be rearranged to adapt to different sizes and orientationsYou should also make sure to preserve the interface state during configuration changes, especially on foldable devices and large screens where resizing is frequent.
Regarding concurrency, each type must be responsible for executing your costly tasks on the right timelineFor example, through coroutines and Flows. The golden rule is that API calls should be safe from the main thread, offloading the heavy lifting to background threads.
Finally, it is worth preserving as much relevant data as possible locally, in an up-to-date mannerThis way your users can continue using the app even without a connection or with poor coverage, something especially common in congested areas or with low-quality networks.
Having good architecture brings very tangible advantages: It improves maintainability, makes it easier for multiple teams to work on the same codebase, speeds up the onboarding of new developers, and makes the app easier to test.All of this translates into fewer bugs, faster updates, and a more stable experience for the end user.
Taken together, mastering Android's enterprise functionalities, understanding how work profiles and dedicated devices function, implementing secure SSO with custom tabs, applying managed configurations, and adopting a modern architecture with layer separation, SSOT, and DI, is what allows you to moving from making simple apps to building professional, robust Android solutions ready for any corporate or consumer environment.

