Extending Android Application class for OnCreate mismatch from manifest - android

Android application using Xamarin but I think this applies to non-Xamarin. I read this article while doing research.
In an Android application, you will notice that the AndroidManifest.xml file contains an entry for which is used to configure various properties of your application: icon, label, theme, etc. Depending on your application's needs, this is sufficient. The application when instantiated will perform the necessary initializations based on the values configured in the manifest, and it will then load the Activity that is defined as the view to load on startup.
In some cases, you may wish to extend the Application class in order to perform custom initialization on application startup, or to maintain global application state (for example, in the case of a game that is tracking score across multiple levels). The example that you have shown above is the case where someone has decided to subclass the Application class and override it's OnCreate method, although they haven't included any custom code in the override method. It looks like their purpose was to create a global static property to always have access to the Activity that is currently loaded.
Previously, I did not need to extend the application class so I just had my manifest handle it like this article says. However, I recently had a need come up to extend the application class so I can use the OnCreate event for the application.
I added a new class which extends Application and it looks like this:
namespace MyApp.Droid
{
public class MyApp : Application
{
public MyApp(IntPtr handle, global::Android.Runtime.JniHandleOwnership transfer)
:base(handle, transfer)
{
}
public override void OnCreate()
{
base.OnCreate();
//Do OnCreate things here.
}
}
}
It seems just adding this class is not complete. First question, do I also have to modify my manifest now? Second question, the class can have attributes for theme, icon, etc... which are and have been defined in my manifest. Can they stay in the manifest or do I need to move them to this new class as attributes?
Here is the manifest:
<application android:allowBackup="true" android:icon="#drawable/mainapplogo" android:label="#string/app_name" android:roundIcon="#mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="#style/AppTheme">
Thank you!

First question, do I also have to modify my manifest now?
In this question if you mean just because you have added the new application class is there a need to make any change in the existing manifest then NO there is no such requirement.
Second question, the class can have attributes for the theme, icon, etc... which are and have been defined in my manifest. Can they stay in the manifest or do I need to move them to this new class as attributes?
The Android Manifest's Themes and everything else will stay there, The Android Application class and AndroidManifest.xml work independently and hence adding an extended application class does not require any change in your Manifest file or vice versa.
Good luck,
Feel free to revert in case of queries
UPDATE
See to it that your application class has the [Application] attribute on top of the class name
#if DEBUG
[Application(Debuggable=true)]
#else
[Application(Debuggable = false)]
#endif
public class MyApp: Application
{

Related

Is it possible for an app to have more than one CastOptionsProvider, as a means to cast to 2 different Receiver Apps?

Basically, I'm converting an application to a library module. The problem is that this application has Chromecast capability, and hence has its own CastOptionsProvider in the manifest, and the application that's going to use this library has its own CastOptionsProvider, leading to a manifest merger failure.
I know this is supposed to be a manifest merger problem, but this is more about the Chromecast part of the app. Is it possible for one app to have 2 CastOptionsProviders to cast into 2 different Receiver Apps?
TL;DR You can declare an OptionsProvider class in your library, and if needed, your application can declare its own OptionsProvider class to use instead. To switch between different receiver apps while your application is running, you should use the CastContext.setReceiverApplicationId method to override the settings from the OptionsProvider.
Background
According to the Chromecast codelab, CastOptionsProvider is a class you write yourself. You can actually call it anything you want, as long as it implements com.google.android.gms.cast.framework.OptionsProvider. This also means that you could write more than one CastOptionsProvider class in the same app, as long as you put them in different packages or give them different names. You would declare each one of your OptionsProviders like this:
package your.pkg.goes.here;
import com.google.android.gms.cast.framework.OptionsProvider;
...
public class YourOptionsProvider implements OptionsProvider {
#Override
public CastOptions getCastOptions(Context context) {...}
#Override
public List<SessionProvider> getAdditionalSessionProviders(Context context) {...}
}
So far, so good. Because you can call your OptionsProvider whatever you want, you also need to declare your OPTIONS_PROVIDER_CLASS_NAME in the manifest so that the app knows how to get its cast options. That code belongs in your AndroidManifest.xml file, and it looks like this:
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="your.pkg.goes.here.YourOptionsProvider" />
Here is where it gets tricky. meta-data is for declaring key-value pairs, and you can't have more than one value for the same key. You can have multiple OptionsProvider classes floating around in your code, that's fine, but only one of them can be used by the cast framework at a time. To change which one is used, you need to edit the manifest, which you can't do while the app is running. The closest thing you can do is to have different builds of the app that use different OptionsProviders.
So which OptionProvider should I use?
The behavior of an OptionsProvider is just defined by how it implements the functions, getCastOptions and getAdditionalSessionProviders. Figure out what behavior you need from your library, and write that behavior as library functions or classes that can be expanded on by your app. For example:
package your.library;
import com.google.android.gms.cast.framework.CastOptions;
import com.google.android.gms.cast.framework.OptionsProvider;
...
public class LibraryOptionsProvider implements OptionsProvider {
public String YOUR_LIBRARY_APPLICATION_ID = "ASDFASDF";
#Override
public CastOptions getCastOptions(Context context) {
return new CastOptions.Builder()
.setReceiverApplicationId(YOUR_LIBRARY_APPLICATION_ID)
// maybe set some other settings, too
.build();
}
#Override
public List<SessionProvider> getAdditionalSessionProviders(Context context) {...}
}
For an app that doesn't need special behavior, you can just put LibraryOptionsProvider in the app's manifest:
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="your.library.LibraryOptionsProvider" />
But for apps that need something special, you can declare your own ApplicationOptionsProvider that uses the LibraryOptionsProvider for some of its behavior.
package your.application;
import your.library.LibraryOptionsProvider;
...
public class ApplicationOptionsProvider extends LibraryOptionsProvider {
#Override
public CastOptions getCastOptions(Context context) {
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id)) // use a different application ID from the one in LibraryOptionsProvider
.build();
}
// inherit getAdditionalSessionProviders from LibraryOptionsProvider, no need to override it unless we want different behavior
}
Then your manifest should point to ApplicationOptionsProvider instead of LibraryOptionsProvider:
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="your.application.ApplicationOptionsProvider" />
Summary so far: It's up to the application to decide what behavior it needs from its OptionsProvider. If no special behavior is needed, the application should use an OptionsProvider that you declare in the library. When custom behavior is called for, such as when you need different cast options or a different cast application ID, then the application should declare its own OptionsProvider, which can depend on library code instead of re-implementing shared behavior.
Multiple Application IDs
The OptionsProvider is used to initialize the CastOptions, which is "a singleton class containing global context for the Cast SDK"(source). CastContext is initialized in the background when the app starts, but you can change the application ID whenever you want to, using CastContext.setReceiverApplicationId(String applicationId). By doing so, you will ignore the receiver application ID that was configured in your CastOptions. This is how you can switch between multiple receiver apps within a single build.

Multiple Application name in Android Manifest

I am new to volley.I have two classes,AppController Singleton class, and ImageController Singleton class.But in Manifest,it allows only one application name.So how do I solve this?
You can try this way:
Application Class no one:
public class MyApplication extends Application {
}
Application class no two:
public class MyApplication2 extends MyApplication {
}
In your Manifest:
<application
android:name=".MyApplication2"
android:allowBackup="false"
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:supportsRtl="true"/>
Only the <manifest> and <application> elements are required, they each must be present and can occur only once
According to documentation manifest file with only one application element is valid.
Try to Marge in Single Application Class
First of all, every application should have only one application class that is the concept of MVC in android.
You should remove one application class and do whatever it is doing in another one.
As per your requirement: you have AppController and ImageController application class then remove all the code of ImageController application and merge it in AppController application class. Now use AppController class in manifest.
I'm guessing you are using a Singleton as to have a class that holds your App data for the current session and\or another one for specific stuff (e.g. networking), if so, you have a couple ways of going about that:
Use ONE Application class - you shouldn't have more than one, if so - merge them.
If you insist on having 2 Singleton classes because you want to separate some functionality, you may create 2 Singleton classes, which are NOT your application class.
If you choose option 2, you should initialize(and maybe also control) them from your application class, especially to avoid duplicating a context object (that might lead to a memory leak), but make sure it's really necessary first.
since you tagged your question with the Volley tag, I'm guessing this SO thread about isolating Volley requests might help.
Hope anything here helped!

Unable to extend Main Activity with CustomHashMap

Ref: Android:- How to Make dynamic HashMap Accessible in whole application?
I have set up a CustomHashMap (just a collection of 3 LinkedHashMaps) so that I can access it from 2 Activities, but I am
unable to access it from the SecondActivity! The only way to remove red errors in Manifest.xml is to set the lines below. If I
use android:name="com.example.intents.CustomHashMap" (following the online example) I get an error saying 'is not an enclosing
class'.
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher_icon"
android:label="#string/app_name"
android:theme="#style/CustomActionBarTheme"
android:name="com.example.intents.MainActivity$CustomHashMap"> //--- The system added the $ parts here.
<activity
....
protected CustomHashMap thisMap;
....
thisMap = (MainActivity.CustomHashMap)getApplication();
In MainActivity I can do things like thisMap.getKeyValue(4) but from SecondActivity only null is returned. I feel as if I am
missing something very simple here. Any ideas?
As see here android:name :
The fully qualified name of an Application subclass implemented for the application
Means need to pass class name which extends Application instead of any other component name like Activity,Service,...
See following tutorial for adding Application class in application :
Global Variable Or Application Context Variable - Android Example

How to bypass activity declaration in AndroidManifest.xml?

I'm working on code that will be stuck inside other people's apps. I have two activities that both play off of a video view (with slightly different behavior). However, i'd definitely like to NOT rely on other people manually having to declare AndroidManifest.xml activities that i create. (some developers might just forget to declare it in their manifest)
So essentially, i'd like to be able to tell android to load an activity which is not declared in Manifest. How do i do this?
here are my thoughts:
1) I've tried subclassing a declared activity (declared activity referring to it being declared in AndroidManifest). however, calling this subclass throws a ActivityNotFoundException not surprisingly.
2) i COULD pass in a static view via a static method like:
public class Blah extends Activity {
private static VideoView badIdea;
public void setBadIdeaView(VideoView vv) { badIdea = vv; }
//... start it up as usual, but `badIdea` is now configured
}
but i really don't want to do this because a view holds on to a context, and i DO NOT want a static strong reference to an Activity context.
3) does anyone know how Android actually loads your activities? i'm guessing Android uses reflection to open an instance of the class.... but... i mean, why do activities have to be declared in a Manifest? is this for security purposes in order to prevent bad dynamic classloading? is this a possible solution?
thanks
How do i do this?
You don't. All activities must be declared in the manifest.
However, i'd definitely like to NOT rely on other people manually having to declare AndroidManifest.xml activities that i create.
As suggested in a comment, if your code is implemented as an Android library project, you can try relying upon manifest merging.
some developers might just forget to declare it in their manifest
So? They should catch it in testing. You can also add sanity-checking to your exposed API, where you see if the app has your activities registered, by means of PackageManager, so that way your code will "fail fast" if they did not follow your instructions.

Android multiple <application> in one androidmanifest

I am using
Android global variable
example.
How do I add another "application" tag in AndroidManifest.xml ?
According to the documentation, only one application tag can be inserted in the manifest.
Quote from doc:
"Only the manifest and application elements are required, they each must be present and can occur only once."
If you're following the example at the given link, just add the android:name and android:label XML element to your current application tag and it'll work just fine.
Example of my application tag in an application I'm developing at the moment:
<application
android:name=".Globals"
android:debuggable="true"
android:icon="#drawable/icon"
android:label="#string/app_name" >
Globals is my application class.
I know this question was asked a long time ago but using Android Studio 3.0 and higher, I came across the same problem and did not find anything online that helped.
After a lot of research and my own testing, I found out how to successfully implement two or more classes that both extend android.app.Application into the Manifest's <Application/>.
First Class File:
public abstract class MyClass1 extends Application {
// ...
}
Second Class File:
public class MyClass2 extends MyClass1 {
// ...
}
Manifest File:
<application
android:name="com.mydomain.myapp.MyClass2">
<!-- Rest of code here... -->
</application>
how to handle multiple application classes in android
When a library is already extending the "Applicaton" class just do the following
class lib1 extend Application {
...
}
class lib2 extend lib1{
...
}
in the manifest -> <application android:name = "package.lib2".....

Categories

Resources