I'm attempting to add a MediaBrowserService for Android Auto to an existing media-player app. The app has a single activity which manages the MediaSession, Callbacks and related state. It has been set up so that it emits events, which the background MediaBrowserService consumes and uses to build its content tree.
This all works fine when the flow is like:
Start my app -> Start Android Auto -> Browse media
However, it falls flat on its face when the flow is:
Start Android Auto -> Browse media
...as in, when the app is not started and running in the background prior to when Android Auto is launched.
The problem appears to be that although my MediaBrowserService will be automatically launched by Android Auto, it does not create a corresponding instance of my app's Activity when it does so (which means no events to inform the MediaBrowserService, and consequently no content available in Android Auto).
Ideally it seems like the MediaBrowserService needs to be able to check and see if the app's "main" Activity is running, and spawn a new instance if/when it is not. But not sure if that's possible, and it tends to feel like it's the wrong approach to take here.
What's the correct way to work around this issue? I don't want to replicate all of the app's MediaSession handling and playback-related code in the MediaBrowserService implementation. That should be kept as lightweight as possible. Is there a way to ensure that the app's Activity is always running whenever the MediaBrowserService is active?
The answer to this was refactoring. Lots and lots of refactoring.
In a nutshell, Android expects Activities to be used to fill a particular architectural niche. Specifically, the niche where you're displaying an interface to the user via the device's screen. Other use-cases, such as having a 'headless' Activity running in the background, appear to be neither expected nor supported.
Thus the answer was to take all of the app's playback-related code out of the Activity, move it into a background Service, and provide an API for passing on the relevant commands (and receiving data, state updates and so on) either from/to the foreground Activity (if/when the user is interacting with the app's UI) or from/to the MediaBrowserService (if/when the user is interacting through Android Auto's UI). Starting the service is something that can be easily done from either context, if/when needed.
That appears to be the solution. It certainly can be tedious if you've got a nontrivial existing codebase you're working with. Far better to anticipate this sort of issue, and architect your app accordingly from the start; keep things that aren't directly pertinent to your app's UI outside of your Activity implementation(s).
Related
I know that it is a real problem with running apps in background for different OEMs, but how can I solve this problem?
My app has a webview integrated from an online radio, everything is ok, but after 5 minutes (in locked screen mode), the player stop playing... I can configure my mobile settings, going to Apps, Special access, Optimize battery usage, search for my app and disable that button, but I win only 10 minutes (15 in total), and the app will stop again...
I found something about services, but I'm a really beginner, I don't understand why should I use a service to run in foreground... I have also a notification icon (+title+message) which is showing on display even if the mobile screen is locked. For my understandings, that means the app is running in foreground and in background. Can't figure out how to solve this.
I'm a beginner, but I want to go with this app in production (Google Play), and I want to be useful, not to be just another app...
I hope somebody will have the patience to respond on my issue. Thank you!
(At least some advice, what should I do...)
You need services to run in the background when your application is not visible to the user. Android automatically kills some apps especially when they are resource intensive. This can also be done by some antivirus software, task cleaners, memory cleaning apps etc.
You need to build your application around these challenges because users will not be required to optimize their settings for your application to run.
This services can be triggered by some android activity lifecycles. When you lock your screen, some life cycle methods like the onPause() and the onStop() could be called in your applications by default. You need to handle these events.
Services
A Service is an application component that can perform long-running operations in the background. It does not provide a user interface. Once started, a service might continue running for some time, even after the user switches to another application. You need to create a service that will perform the tasks you want and periodically update the call back in your application.
E.g. The app may fetch notifications from a remote backend and periodically show them to the user at the notifications panel.
Android activity life cycles
As a user navigates through, out of, and back to your app, the Activity instances in your app transition through different states in their lifecycle. The Activity class provides a number of callbacks that allow the activity to know that a state has changed: that the system is creating, stopping, or resuming an activity, or destroying the process in which the activity resides.
Within the lifecycle callback methods, you can declare how your activity behaves when the user leaves and re-enters the activity.
References
Android Services -> Learn about android services
Activity Life Cycles -> Learn about activity life cycles
I'm working with realtime database where I want my activities to run even no one is using the app.
swipeRefresh.setOnRefreshListener {
// code
binding.swipeRefresh.isRefreshing = false
}
From the above code, the user needs to swipe to refresh, I want it to be the same but in background and it does itself.
That means the activity is like a 'refresh' in the background every five seconds.
It's not possible to keep an app running while it's not being used. Android app processes will be killed by Android when the user is no longer using the app, and this can't be prevented. Android does this to save resources and allow other apps to run when they are being used. I suggest reading the documentation to understand how it works.
Your app should isntead simply query the database again when it's launched and rebuild the UI.
I know this can be done with some apps with Tasker and Automate, but I want to learn this by myself.
Create a app that runs always in background;
How to read a sensor data(in this case I would like to use the 'Ambient light sensor');
Lock the screen.
I have Android Studio and everything is ready to make a app and compile, but I have no idea how to make this / where to start. Thanks for any help.
The questions you put covers couple of very wide topics and it is very difficult to provide tailor made answer to them. The best that someone can do is to provide some pointer which I will attempt to -
To create an app in the background on Android, you basically create an Android service and keep it running in the background. Make sure it's a sticky service which means, the service will be restarted automatically if it was killed for some reason. If you want to run this app always on background (not a good idea though), you might listen for a Boot completed broadcast and start your background from the broadcast receiver. Below links are on related topics - https://developer.android.com/reference/android/content/BroadcastReceiver.html
https://developer.android.com/reference/android/content/Intent.html#ACTION_BOOT_COMPLETED
https://developer.android.com/guide/components/services.html
https://developer.android.com/reference/android/app/Service.html#START_STICKY
Reading ambient light sensor data is pretty straight forward. Follow the link provided below. Although all the samples shown in the link need your app to be in the foreground, but it is not mandatory. You can basically register for the sensor data change listener from your background service. Listening for sensor data, needs you to create an instance of the sensor manager framework service class and registering for a particular sensor (in your case Light) data change listener
Source page - https://developer.android.com/guide/topics/sensors/sensors_overview.html
I have no personal experience with keyguard locking/unlocking programmatically but few links which provide some sample code are worth looking -
How to Lock/Unlock screen programmatically?
Android screen lock/ unlock programmatically
I was wondering if it's possible in android to embed an application into in another application. In this way you can have control of the embed application and you can add some other functionalities thanks to the parent application.
EDIT :
To be more accurate, I would like to have an application (parent application ) which can overlay the content of another application (embed application) without losing control of the parent application.
Thank you,
You can not specifically embed one app in another. And unless there is a specific inter-application API you have available to you, you cannot control the one app from your parent app either.
However if you just want to be able to view your parent app as some kind of overlay over another app, there are techniques that you might find useful.
It is possible to create an overlay view that can be seen when other apps are in the foreground. This is used by some chat clients, video playback, and task launchers. You can find some info on this method by looking at my answer here:
Background app to listen to Drag gestures
It is important to realise that in "the old days", a technique like this could be used to steal data from someone's phone. It was possible to receive taps & drags, and then pass them on to the other app.
This was a security hole, and has been fixed. So these days, you can choose if your overlay view should receive the taps or not i.e. if it is interactive, or just shows info.
Because of this, you will not want to cover up any of the "embedded" app with your own UI.
It is not possible any more to receive taps in your app, and pass them through to the other app.
This is not possible in general. The only thing that comes close is "embedding" an app widget in a home screen.
I am interested in developing a custom Android launcher which would be installed onto a device primarily for censorship. Ideally a device would divert attempts to launch applications to a service which would decide, based on a profile, whether the user would be allowed to proceed, or be shown a block screen/redirected to an informational web page.
Is it possible to detect and interrupt application launches via some kind of background service or attachable listener? Or alternatively, might it be possible to have a launcher launch a different application than the one clicked on, in order to allow for indirection?
Or, if all of this is impossible, can a service running as part of a custom launcher dynamically hide/unhide launch icons based on triggering events/messages?
There is no way to catch an app being launched and redirect that. If you think about all the horrible things people could do with this it's easy to see why. I think you're going about this in the wrong way. Instead of trying to enforce these rules with a custom launcher you should look into one of the Mobile Device Management options that are available for Android or work on creating your own.