Android Jetpack Compose: should we do away with the MainApplication file? - android

I'm looking into slowly migrating an existing view-based Android app to a Jetpack Compose app. I figure I will take the opportunity to totally refactor the app, so I'm starting the Compose app from a blank slate, and trying to adopt the latest best practices as I go.
I've created a new project in Android Studio, using the "Empty Compose Activity" that's recommended in some of the docs I've read.
The project it creates lacks a MainApplication.kt file, and the manifest jumps straight into MainActivity, which defines only class MainActivity : ComponentActivity()
I note that the Android docs say "There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way." which has me thinking that, as part of this refactor, I might try follow this implicit recommendation and see where it leads.
So my question is, is there anything that must be done in the Application class that would make me regret the structure that Android Studio has given me?
Does Koin dependency injection work fine outside of the main Application class? My app has services which have Room dependency injections I now do in Application class. All of that can be done elsewhere, presumibly in MainActivity?? (All Koin's examples use the Application class for DI!)
Can setting user permissions like location and file access can be done outside Application class??
I know I'm asking for an opinion here, but do you regard it as best practice to not subclass Application if you can avoid it, as the Android docs seem to suggest?
And lastly, is not subclassing the Application class (ie not having MainApplication.kt) somehow related to the new Compose way of building apps?
thanks!
John

The skeleton code that you get from creating a Compose project from Android Studio does not subclass Application because it just gives you the bare essentials to have a functional compose app.
The Application class is still the right place to initialize your dependency injection graph, plus other libraries that need a one-off initialization, like for instance Timber.
Requesting runtime permissions should be done locally, at the time you need those. If you need some permission to start your application from the get go, ask for those in your activity, the Application is not the right place for that.

Related

How to use Android Jetpack App Startup library

As part of Jetpack, there is now a library to handle App Startup.
Specifically, you can implement a component initializer for any of your dependencies, apparently ones that use ContentProvider for their initialization, in order to speed up the app startup process.
My question is how should I know which of my dependencies deserves its own component initializer?
Do I need to guess that, for example, WorkManager uses ContentProvider and requires its own component initializer while a different dependency doesn't?
Thanks.
I believe this library is meant mostly for cases when the initialization code can't or shouldn't be accessed from a custom Application class.
For example, On Demand Modules or libraries that don't want to require the user to call an initialize(context) method.
This library is for content providers, because content providers slow down your applications startup time. whenever you use any lib like workmanger or firebase it will autmatically add its own content provider in your android manifest xml file.
you can know which providers added to your manifest from android studio "Merged Manfest" tab

Export existing android app as aar (like a library)

Background: I have an android application that has been published in GooglePlay and I want to create SDK from that existing application so that others can use it as a library inside their apps.
So far: I was able to generate .ARR file from the existing app source code with little tweaks. and it is working pretty good.
The problem: is I have some sensitive information stored inside my app
since I made .arr file from my app codebase I'm little worried that they can easily get access to my SharedPreferenceManager (util class of mine to deal with SharedPreference) DataBaseManager so on and they can subclass library class and tweak the behaviors
So How can I avoid library users not to misuse my library to exploit my existing app?
is there any other way to export my app as a library?
The basic process would be as follows:
Figure out what you want to expose in your SDK
Move all of this into an android library module
Deploy the AAR
Can you explain a little more what you mean by "I'm little worried that they can easily get access to my SharedPreferenceManager (util class of mine to deal with SharedPreference) DataBaseManager so on and they can subclass library class and tweak the behaviors" ?
You can always utilize obfuscation techniques and finalize classes to make it difficult. I don't think you can guarantee absolutely no misuse, but I am not sure how this would effect your application. If you have a server, for instance, then you would still control the software there and be able to sanitize and sort through the input.

How can I use WearableActivity with LiveData and ViewModel

I want to be able to use the Lifecycle components from the new Android Architecture Components in my Wearable app (same as I do in my Android app).
In my main Android app I put LiveData fields in a ViewModel. This ViewModel can then be accessed/bound from both my Activity and my Fragments. To do this I use the method ViewModelProviders.of which expects either android.support.v4.app.Fragment or android.support.v4.app.FragmentActivity. So far so good...
The problem I'm facing is that my Wear app is based on the WearableActivity class which extends from android.app.Activity rather than from android.support.v4.app.FragmentActivity. This prevents me from using ViewModelProviders.of in my wearable app.
I've asked around and tried to find alternative solutions, but I don't know the internals of ViewModelProviders so I can't get around this problem right now. If there isn't an answer I hope someone who works on these components can have a look at this. It would be awesome to be able to use ViewModel & LiveData throughout my applications (mobile and wear).
Update:
AmbientMode seems to be the new way to handle this.
As #codingjeremy mentioned in his post, they have now introduced this with Android Support Library 27.0.0.
Original:
I got around this by copying the implementation in WearableActivity verbatim to a new WearableFragmentActivity class defined in my own project and then changing it to extend FragmentActivity. Getting this supported by Google directly would be the ideal solution, but this should work if you're looking for a workaround in the meantime.
This is not yet possible as ViewModel depends on Support Fragments (i.e., FragmentActivity).
Please file a feature request for a WearableFragmentActivity equivalent at issuetracker.google.com
I got it to work using AmbientMode.AmbientCallbackProvider instead of WearableActivity.
It is the new preferred method and it still gives you the onEnterAmbient(), onAmbientUpdate(), and onExitAmbient() but also lets you use Activity (or any sub classes... FragementActivity, etc.)... which allows you to support the Architecture components.
Official docs call out the details and code.
You can use this porting of architecture component: LifeCycleData

Modular android project - how?

My scenario
I have to implement a "modular" android app. There is a core module from which I should be able to invoke other modules. Each module provides a different feature to the user. Imagine I am making a city guide, then one module may contain a map with POIs, another one an event calendar and a third one pre-defined city guides. The modules contain views to be loaded in activities of the core module (like dashboards where each module puts its item/picture). They also contain activities which should be invoked (like when a user taps an item on the dashboard). As far as I know, I will need a database and/or preferences only in the core module. The "plug-in modules" use classes (utilities) of the core module, e.g. when connecting to the backend.
My solution on iOS
For iOS, I achieved this with targets in XCode. I have one project and depending on the customer's needs I compile only the relevant modules. It would be even better if the user can install modules whenever he wants, without the need of reinstalling the "core" application.
My problems on Android
In SO, I already found various solutions like library project, switching from Eclipse to Android Studio + something, using package manager and broadcast receiver... But I still don't understand... How is the modularity of an android application to be achieved?
Here are some concrete problems that I see:
Libraries: My modules all use classes of the core module, so they are not independent. I achieve the modularity by using interfaces/inheritance depending on the flexibility that I need.
Broadcast receiver: This seems to be everything else than recommended. See, for example, here or here.
What I need is, at least, to be able to use the same code for delivering app with features A and B to one customer and with B and C to another one. And, until now, I have no idea how to achieve it.
PS: I don't want to use scripting, I am not familiar with that.
I don't see this "modular" app as anything different from one app, with several packages, each containing discrete functionality, that is adapted to some list of settings or external parameter (either provided by the user or you).
My approach would be to have a "main" package. That package would contain the shared functionality you mention above and serve as the hub for your application. I would then create separate sub-packages for the different "add on" functionality. This allows you to still use the code in your main package with a simple import statement. From your description these additional functions should probably be implemented as a Fragment. A Fragment is almost a stand alone application with the exception that it is "hosted" by an Activity. Depending on how these add on functions are used (I cannot tell if they relate to the UI, just background processing etc) you could easily have 3 of 4 different fragments and choose to load only 1 or 3 or 2 of them at runtime.
To control which parts of the code are used I would just set up a simple switching class (it could even be part of the first activity launched, I cant tell from your description above). Here I would check for some setting indicating which parts of the app will be "active." This could be easily defined using SharedPreferences to store a specific configuration, e.g. use A and B, prior to delivering the final project. You would then just initialize the fragments you need and display them either (1) individually in a Fragment layout element or FrameLayout; (2) collectively in some other view structure like a ViewPager.
I follows your links on the BroadcastReceiver and I am still not sure why they are "everything else than recommended." Used correctly a BroadcastReceiver is very useful. I tend to use a LocalBroadcastManager along with a BroadcastReceiver to notify other sections of the app when some AsyncTask, e.g. downloading a lot of data, is complete. These parts of the app can then access a local database or process the information downloaded on their own time. I wouldn't use a BroadcastReceiver to modulate parts of the app if that is what you're looking for. I would instead just use a SharedPreference file to set the configuration at runtime.
If you need modules like facebook sdk or something like that better use library project. If you use Idea or Android Studio there is such thing like Module. If I need some modeles in one app I prefer just put in different packages like com.appname.model, com.appname.ui and so on. Broadcast Receiver isn't about modules. As I know there isn't analog of ios target.

Integration of smaller apps into bigger one on android

What would be the right way of including smaller android apps, into one bigger if requirements are the following:
little apps should be loosely coupled and should be developed separately
bigger app should handle some common things, instead of each little app do it for itself.
bigger app should now something about state of little apps, in order to do some decisions.
First thing that comes into my mind is some sort of plug-in pattern (although I don't know much about it, so I could say something wrong), so that each little app should implement some common interface, and big app should use that interface when dealing with component.
Is that right approach?
Is this right way of thinking considering android as a platform?
Your best bet is to make each sub app a "library." You create a workspace in Eclipse and create a new Android project and mark it as a Library.
You do that for each sub app.
You then have a non-library application that imports each library and uses each as part of the full application.
This means you don't need to worry about writing a plugin interface, etc.
Also if you follow this sort of pattern, when you create a free vs paid application, you are able to just add another application and remove / change functionality as that one all needs and compile both from the same code base.
Update
Take a look at http://developer.android.com/tools/projects/projects-eclipse.html for some decent documentation.
This shows how to create both types of projects and how to reference them in your manifest which is the annoying part.
Update2
From comments it was asked if you can use a library Activity in a main application that imports the library.
You create an Activity in the library
com.example.myapp.library.MyActivity
Then you add details to your manifest
<activity name="com.example.myapp.library.MyActivity">
This then let's you use it there. You can even use a library Activity as your main startup Activity if that's what you need.
You can also extend a library Activity by changing your manifest to
<activity name="MyNewActivity">
Then create a new activity
class MyNewActivity extends com.example.myapp.library.MyActivity
Then just override what you want, call super to access your library method if desired, etc.
Feel free to ask questions.

Categories

Resources