I have a strange behavior of Activity in complicated legacy code.
In LoginActivity I want to start some PromotionActivity but just after onResume it goes to onPause.
As this app has some ActivityUtils in one of its numerous libraries - I used another approach:
I called one default PublicActivity and passed a fragment there.
It looks like
Map<String, String> params = new HashMap<>();
params.put("fragmentName", PromotionFragment.class.getName());
ActivityUtils.showActivity(activity, PublicActivity.class, params);
And all is shown without problems.
To understand why this works, I copied PublicActivity from a library to the main folder as a PublicActivity2 and tried to launch it but failed again. I did different changes, even extended PublicActivity2 from PublicActivity
public class PublicActivity2 extends PublicActivity {}
ActivityUtils.showActivity(activity, PublicActivity2.class, params);
but again failed.
How is it possible that PublicActivity is shown without problems but PublicActivity2 which is extended from PublicActivity and used in the same showActivity method - only goes to onResume and immediately goes to onPause?
I found the issue. As it's complicated legacy code with numerous libraries I didn't notice that there is some Application.ActivityLifecycleCallbacks in one of them which listen lifecycle of activities and compare every launched activity with a list of permitted ones. So, I found that list, added my activity and all works fine.
I didn't find it quickly because it was passed from a library to main app as another interface which extends needed one, luckily searching through the app with a word Lifecycle I found getApplication().registerActivityLifecycleCallbacks(new Analytics().getActivityLifecycleCallbacks())
So, for this weird situation when your activity immediately finishes after launching without any visible reason - my advice is to look for this ActivityLifecycleCallbacks
Related
I have an Android application that uses a class extending the following type:
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class GamePadController extends View implements InputManagerCompat.InputDeviceListener {
// The current device that is controlling the ship
private InputDevice mInputDevice;
private int mDPadState;
...
When I run the apk in a mobile sometimes the Gamepad is captured in android and my custom methods onGenericMotionEvent and onKeyUp are called.
It is a random behaviour, sometimes my methods are called and my behaviour is executed but sometimes only the default behaviour happens (like if my classes were not registered).
Things I observed:
In any case when I run the app it takes some time for my methods to
be called, like if there was some lazy loading that I should force
sooner (maybe).
The code my changes is based on did work, but I introduced
other things that don't look related at all (other classes, a thread)
No exceptions or errors in the LogCat, already made sure of no empty catches and things alike
Do you have any clue or advice on this behaviour?
Thanks in advance
So it seems like I was putting the callback methods in a specific View within the Activity (which had other elements like textviews), meaning that only when that specific element was focused the input was captured in the callback... that is why the documentation tells you to put the callbacks in the Activity or the View... probably it made more sense to put this behaviour in the activity so it was captured no matter what was in focus.
I am new to Android development. After learning from many tutorials I got many Activities and many Fragments. How can I make a core engine to check what Activity is running and what Fragment is showing on a container?
Assume that I have:
Acivity01, Activity02, ... , Activity10
Fragment01, Fragment02, ... , Fragment10
I want to make a class that filters the Activity where Activity is on runtime and what Fragment is embeded to that activity.
How can I do this?
If I understand you correctly, you may want to store some references within your Application class to an Activity and to Fragment instance(-s), which are currently in foreground (by this I mean that user can instantly interact with Activity/Fragment).
As for Activity
Create some Activity field in your Application class and getter/setter methods for it (e.g., setCurrentActivity(), getCurrentActivity()). Then call setCurrentActivity() from onResume() method for each of your Activity instances. Don't forget to call setCurrentActivity, supplying null reference to ir in order to properly handle a case, when there are no foreground activities, but application is stll working.
As for Fragment
The general idea is similar to the first item, but there can be more than one Fragment instance in foreground state at time. So you need to store something like List, where you add your resumed fragments and remove paused.
You may also want to implement something similar for dialogs, for example. Then use the same strategy. Hope it will help.
I'm having a problem instantiating Fragments in my program using the Support Library implementation. Here's a brief description of the task I'm attempting to perform and some of my attempts which haven't yet borne fruit:
The UI of my application is subject to change to meet user preferences. In order to do this, I'm using a Fragment for each different layout and replacing the active Fragment in the UI at a given time as per the user's instructions. Here are some ways I've tried (and failed) to do this:
I've tried adding the Fragments as non-static inner classes in my Activity. This approach worked so long as the user did not rotate the device. As soon as the user rotated the device, the application crashed (this is true for Portrait -> Landscape rotation and for Landscape -> Portrait rotation). Upon checking the issue using the emulator, I was getting an InstantiationException. I checked SO for some help, which led me to:
Implement the Fragment as a static inner class. When the Fragment initiates, it will expand its layout, and then from later in the control flow of the Activity, I can do stuff to the Fragment's subviews (in particular, add listeners to the buttons). Unfortunately this didn't work because I couldn't refer to the Fragment's subviews using [frag_name].getView().findViewById(). Something about referencing static objects in a non-static context. Once again, I checked SO, which led me to:
Implement the Fragment as a separate class altogether from the Activity. This seems to be what the Dev docs on developer.android.com recommend. Upon doing this, everything seems to compile fine, but when I try to refer to the Fragment's subviews (once again, using [frag_name].getView().findViewById()), I get a NullPointerException. When I add System.out.println() statements across my code to find out exactly what is happening, I find that the print statement inside onCreateView in the fragment is never getting fired, which implies that onCreateView is never getting triggered.
So now, I'm stuck. What am I doing wrong? The precise implementation of this isn't as important as learning something from the experience so I can get better at Android development, so if seperate classes are better than static classes or vice-versa, I don't really care which I use.
Thanks.
Figured it out. Turns out that in order to do what I wanted, I had to register the Activity as a Listener to each of the Fragments and pass "ready to enable buttons" messages back and forth between the two. To anyone using this question for further research, the guide on how to do that is located on the Android Developer guide, here: http://developer.android.com/training/basics/fragments/communicating.html
I have 2 versions of an app, free and paid, but have been maintaining the code separately. I've finally moved the code into a library referenced by both to make maintaining the code easier.
I found that changing the AppwidgetProvider caused the launcher to delete any existing widgets, so I moved those classes back out of the library to keep the provider the same so users don't have to recreate their widgets. The launcher no longer deletes the widgets, but instead, they simply don't appear after updating.
If I call AppWidgetManager.getAppWidgetIds for the componentname, as it's always been, the appwidgetid is still there. The appwidgetprovider and service still get called to update the widget, and /data/system/appwidgets.xml still shows the widget, but the launcher never displays it.
It's not that it's invisible, as long pressing in the widget location brings up the wallpaper chooser. I can create new widgets just fine, but I don't want to frustrate users by asking them to recreate their widgets. The logs don't show any errors thrown by the launcher or AppwidgetService.
Any ideas why the widget stops rendering after updating? It's somehow related to moving most of the code into a separate library. Thanks!
Edit: I'm testing on an emulator, api level 15, stock launcher
OK, I found a solution, but I feel sick for what it is...
After reading about how classes declared in the manifest should never change, I went and creating each class in the manifest as a class in the app, extending the corresponding class in the library. Then, I had to change every Intent to include the correct class, using forName. So, an example of this scenario is:
app package: com.sample.package
activity: MyActivity
library: com.sample.package.core
activity: MyActivity
There's a MyActivity in the app, and a MyActivity in the library. The MyActivity in the app simply extends com.sample.package.core.MyActivity.
Then, any occurrence of...
new Intent(context, MyActivity.class)
...in the library must become...
new Intent(context, Class.forName(context.getPackageName() + "." + MyActivity.class.getSimpleName());
If there's a way to do this through the manifest, please let me know!
I am trying to make my Android application run some code when run from the launcher, BEFORE launching into an activity. That is to say I want my app to start with a Sub Main as opposed to going into an Activity first.
Essentially, in pseudo, I want to do something like this:
void main() {
doSomeInitializationStuff();
startActivity(myFirstActivity);
}
According to this question, it looks like Android does not have this concept literally. So I was looking at creating an invisible Activity as my entry point, but cannot figure out how to make an activity invisible. I've tried these two methods, which seem to be the only ones coming up in my searches, but they don't seem to actually do anything...
this.setVisible(false);
this.setTheme(android.R.style.Theme_Translucent_NoTitleBar);
Instead of creating an invisible activity you can create a splash activity and start all your initializations there .
I have not tried this but you can extend the application class and use onCreate in your application class to initialize what you need.
Here is the JavaDoc for onCreate of the application class
/**
* Called when the application is starting, before any other application
* objects have been created. Implementations should be as quick as
* possible (for example using lazy initialization of state) since the time
* spent in this function directly impacts the performance of starting the
* first activity, service, or receiver in a process.
* If you override this method, be sure to call super.onCreate().
*/
public void onCreate() {
}
You will need to let the app know that you are using a custom application class by using the the android:name parameter in the tag of the Android manifest file.
In most of the Android application there is concept of SplashScreen one can use that screen to accomplish such behaviour and the real motif is of this SplashScreen is to proccess such tasks in background while advertising for the app itself and various things related to that
One option would be to not have an invisible Activity, but a SplashScreen. This has the advantage that the user already sees something happening when the app starts up, so that he does not get the impression it is no working. For an example see e.g. this class; you would put the doSomeInitStuff() at around line 54
Otherwise I think, you can just not load a layout in onCreate() of the first activity and then forward from there.