I have seen a JS talk about Redux recently. The speaker programmed a working application without any classes, just with const variables. He even excluded classes in his lint file (https://github.com/MartinSeeler/redux-presentation/tree/master/demo).
So I tried to do the same in my Android apps, which are written in Kotlin. Unfortunately, I get the following error when I try to make my MainActivity class an object:
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{blog.app.niklas.flyingbytes/blog.app.niklas.flyingbytes.MainActivity}: java.lang.IllegalAccessException: void blog.app.niklas.flyingbytes.MainActivity.<init>() is not accessible from java.lang.Class<android.app.Instrumentation>
Caused by: java.lang.IllegalAccessException: void blog.app.niklas.flyingbytes.MainActivity.<init>() is not accessible from java.lang.Class<android.app.Instrumentation>
Is there a way to work around this? I really like the idea of having as many singleton objects as possible in my app.
Thank you in advance,
Niklas
You can't replace Activity class by kotlin object on Android, for the same reason you don't instantiate Activities by calling it's constructor:
activities are managed by the platform.
When you ask (via an Intent) the platform for an Activity, the platform will try to instantiate it by calling it's constructor with zero parameter. Which doesn't exist for an object, giving the mentioned error.
That's said, some developer dodge around the frame given by Android, like mortar, by having only one activity and using custom logic for navigation between views.
As Geoffrey said, the Android platform manages your activities, but that also means that the platform is responsible for keeping track of your Activity's instances - which is the purpose of Singleton.
So, while you can't make your Activity an object, you can still make it a Singleton by using the android:launchMode attribute in your AndroidManifest:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleInstance">
For more information on the launchMode attribute (including other possible values), check out the Official Documentation
Related
I need to create 2 native activities in my android app where one activity will be communicating with another. I would like to avoid java coding involved, there is a way to do that if activity name is set as
android:name="android.app.NativeActivity"
The problem is that I cannot declare 2 activities with the same name and in order to avoid this problem I have to do something silly like defining another class as a dummy extension of NativeActivity
public class MyAnotherActivity extends NativeActivity {}
and then I can have both the activities declared in my manifest:
<activity android:name="android.app.NativeActivity"
...
</activity>
<activity
android:name="MyAnotherActivity"
...
</activity>
This looks odd to me, maybe there is a better way to do that without creating dummy java files ?
I would expect ability to declare several native activities without involving java.
I don't think you can.
But creating 2 Java Activity classes that do no more than extend from NativeActivity is trivial as you have shown in your question.
I noticed that one of my colleagues is declaring all the member variables of an activity as static. His point is that there will never be two instances of the activity, and static member variables are more efficient than non-static. Of course, when the activity is created, he will initialize all the members variables as one would do.
I feel this is wrong. I don't think the gain is even justifiable. But I wanted to run this by you guys. Whether or not it is a good programming practice is probably beyond the scope of stackoverflow's mandate. So my specific question is if using static member variables for an activity ever break anything (besides coder's error of not initializing them properly in onCreate).
Thank you in advance for your help.
Yes, android can create 2 instances of the same activity, so your friend is wrong.
To have only one instance, you must declare the following in manifest
<activity android:name=".YourActivity"
android:launchMode="singleTask"
android:label="#string/app_name" />
Yes, you can have multiple instances on the same activity and you often want to.
For example, if I have 3 views that simply compose of a ListView. You can create 3 activities that had the same code duplicated and small changes, or one activity that handles the loading of the layout and getting a reference to the ListView and extend it to add functionality.
You can limit an activity to one instance by declaring it that way in the manifest file.
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.
I have a project (in Eclipse) which I've turned into an Android Project Library so as to re-use some of the code in another similar project. I think I've shot myself in the foot however as I'm getting the error:
Unable to start activity ComponentInfo{com.test.scroller1/com.lib.scrolltest.ScrollTestActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.lib.scrolltest.resAppVars
com.lib.scrolltest is my Project Library which instantiates a class extending Application (resAppVars). In the onCreate() method I call:
mRav = (resAppVars) getApplicationContext ();
This way, I can use methods in the mRav object which would otherwise be a lot of duplicated code in other classes (such as passing a query to a generic select statement which returns an ArrayList of results).
What's the problem here? It seems I've hit a limitation in the way I've implemented the Application class.
Calling getApplicationContext() returns the Application object for the current application (i.e. the application that owns the activity that onCreate() is running inside of).
Unless you're doing something strange, you don't get to pick which Application class is used. There's even a note in the documentation for Application saying not to do this:
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), the function to retrieve it can be given a
Context which internally uses Context.getApplicationContext() when
first constructing the singleton.
You should just create a regular shared class inside of your library project. Or if you don't have a need for the special functionality library projects offer, you can also just use a regular .jar file.
And if you need shared state, just make it a singleton. ;)
Although this is a very old post. I encountered the same problem and solved it. So I thought I'll post the solution for everyone.
It turns out that I forgot to declare the subclassed application name in the manifest file.
The android:name should point to the extended app class, even if it is defined in the referenced library.
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:name="com.example.lib.MyApp">
After I added that I could use the extended app with (<cast>) getApplication() anywhere in my project.
Assuming I have a shared activity class defined in a Library project, which does not change for any application using it and thus does not need to be subclassed, can I get a way with creating applications without subclassing this activity for them?
To better explain my question, say I have a single activity in a Library project:
public class LibActivity extends Activity {
...
}
And now I am creating an application using that Library project. Do I really need to create
public class AppActivity extends LibActivity {
// totally empty!
}
Only so that the application have its own activity to be referenced in its own AndroidManifest.xml?
Can I get a way with a minimalistic approach, in which I subclass the activity only if I need to modify the library's activity core behavior?
Here is the fully qualified answer:
Yes, an activity based application doesn't have to derive an activity from the library's activity. The application simply uses the library's activity verbatim, unmodified.
Yes, I can get a way with a minimalistic approach, in which I subclass the activity only if I need to modify the library's activity core behavior.
I have been able to verify this with an AndroidManifest.xml that is identical in both the library and the application. It would be interesting to see whether some of this redundancy can be eliminated. I will experiment with this and report back.
UPDATE: Sure enough, it is possible to create a perfectly running application in which the only activity is defined in the library and the library's AndroidManifest.xml doesn't have any <application> or <activity>! This is possible if the application's AndroidManifest.xml has them.
You can reference library Activity classes directly from your application AndroidManifest.xml. Just specify the fully qualified name like so android:name="com.example.LibActivity"