It is well know to people using Google Maps in an Android app that they can only use one MapActivity per process. There is a bug discussing this in detail along with the workaround of putting each MapActivity in a separate process. I don't want to do this in my app for a few reason and have developed another workaround that seems to work.
For each Activity that contains a map, I have it extend ActivityGroup and create/destroy the MapActivity in onResume/onPause as a child activity. This ensures there will only be one instance of a MapActivity at a time (assuming you have one Activity showing at a time). Below is a simplified version of my implementation:
public class MyMapActivityGroup extends ActivityGroup {
#Override
protected void onResume() {
super.onResume();
addMapView();
}
#Override
protected void onPause() {
super.onPause();
removeMapView();
}
private void addMapView() {
Intent intent = new Intent(this, MyMapActivity.class);
Window window = getLocalActivityManager().startActivity("map", intent);
setContentView(window.getDecorView());
}
private void removeMapView() {
setContentView(new FrameLayout(this));
getLocalActivityManager().removeAllActivities();
}
}
The MapActivity I am using is nothing special and doesn't require any modification. It just sets a MapView as its content view.
This seems to work fine for me. But is there any downside to doing this? My main concern is a memory leak created when going between activities containing a map.
I would guess that the only reason to not do this would be performance. The map activity can already be a bit of a dog, especially when starting it, so if you find yourself allocating and deallocating the view frequently, this might perform pretty poorly. However, its really dependent on how often the view will be created and removed, which depends entirely on behavioral aspects of your application.
Related
I have a situation for each i am trying to find a better (read optimized) pattern to employ.
Essentially, i have three activities - LaunchActivity, WelcomeActivity and MainActivity.
The LaunchActivity is the DEFAULT LAUNCHER activity and in my case, LaunchActivity does not show any UI i.e i don't call setContentView() at all in onCreate(). All that i am doing is, essentially, in onStart(), i check certain conditions and based on the result, either launch WelcomeActivity or MainActivity.
Now, i am wondering, should i really use an Activity [LaunchActivity's superclass] do some checks? Is there a light weight option that i could use to quicken the launch process since instantiating an Activity could be fairly time consuming and expensive?
Thanks all.
I use activity acting as a splash screen in my applications while dealing with such kind of scenarios.The benefit of doing this is that it is giving my application a nice interface, and a graphically rich promotion, and also in that splash Activity,I am taking decisions that what activity should be started next on the basis of last saved state of my Android Application.
Another alternative(which i will not implement in any application developed by me) is to start the Welcome Activity everytime,and in its onCreate() Check some condition.If that condition is met then, open the MainActivity by using intents...else carry on with the flow of the welcome Activity
public class WelcomeActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(your condition)//check some condtion here
{
// if met,go to MainActivity
}
else
{
//carry on with the flow of WelcomeActivity
}
}
}
Overall, I believe using the first approach is better way , because it is just adding an overhead of only one activity,but making the flow of the application cleaner
I'm working on an application that has multiple Activities, and I'm tired of running back and forth between the Manifest and XML layout and stuff. Is there a way to have
Intent intent = new Intent(MainActivity.this, MainActivity.Settings.class);
Or something? Because I've tried it, it doesn't throw me an error, but it just force closes the application. I'm able to bundle all my classes from different .java into one, for ex.
public class MainActivity extends Activity
{
...
#Override
protected void onCreate(Bundle MainActivityState)
{
...
}
public class Settings extends ...
{
...
}
public class Register extends ...
{
...
}
public class Login extends ...
{
...
}
public class BeautifulLady extends personality ...
}
Simple. Just don't even try.
An activity loosely represents a single screen - something the user interacts with. Android is built around this concept and trying to circumvent it will lead to tears.
Stick with it. Having your classes in separate files, and having layout XML separate for each activity, will become your friend and will actually speed things up once you are familiar.
Start with the Activity life cycle document and read it several times until the penny drops. Then expand out from there.
http://developer.android.com/reference/android/app/Activity.html
Object oriented programming, with classes that take care of themselves, is a joy and regardless of which platform you choose to develop on is the way to go for the foreseeable future (old hands, no debates on OOP vs functional please ;)).
If you are going to do mobile development, then the separation of activities, classes and UI is the same concept, just done differently.
See also MVC programming and its' cousins.
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
Good luck.
Perhaps you can define your Activity as 'Single Top', then launch your activity from herself like MainActivity.this.startActivity(new Intent(MainActivity.this, MainActivity.class). It'll then go into onNewIntent() and you will redisplay what you want to redisplay. This way you will have only one screen.
I am trying to use this feature (Google Analytics) in my app and can't figure out what is the best way to do it.
In first place I began to implement this in each Activity of the application.
public class MyActivity extends Activity {
public static GoogleAnalyticsTracker tracker;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tracker = GoogleAnalyticsTracker.getInstance();
tracker.start("UA-YOUR-ACCOUNT-HERE", this);
tracker.trackPageView("/myActivityView");
}
#Override
public void onDestroy() {
// Stop the tracker when it is no longer needed.
tracker.stop();
super.onDestroy();
}
}
But now I am thinking it would be better to create just one tracker at Application class and reference it from every Activity instead of repeat this code in each Activity I do create.
Can anyone explain which way is better and why?
Thanks.
This: Google Analytics in Android app - dealing with multiple activities
is a good read for coming up with a strategy for using Google Analytics in your Android apps.
In essence, you shouldn't call start()/stop() per activity because start() causes a new visit to be logged which isn't what most people intend or expect. However if this is the behavior you want, you are free to do it that way.
As Lukas said using a singleton or as you said using the Application context to call start()/stop() will get you more accurate tracking, but there are caveats when calling stop() that you need to be aware of. The link above goes into more detail.
Why don't you create a class for your tracker-functions and create and make it a singleton?
This class can then hold all the functions you need (like tracking the page view) and do all the background work for you.
I would like to run a piece of code every time any activity or service is started. In this piece of code, I might do things such as set the default uncaught exception handler and manage log levels.
The problem is that I have an activity which starts with the user clicking the application icon. I have another which starts if a certain intent is broadcasted, possibly from another app and possibly called before the user click the launch icon. Same goes for services.
I need to guarantee that a certain piece of code will be run while keeping the code clean; that is to say, without having to manually add that snippet of code to every activity and service class that I have.
Could you not extend the basic Activity class for Android like this:
public class MyClass extends Activity {
public void onCreate(Bundle bundle) {
//Add custom code here
}
}
Then have all of your actual "Activity"'s in your application extend the custom class?
public class MyInterfaceClass extends MyClass {
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
//Other code here
}
}
That way all your custom code will be called when the Activity starts up.
For an application called Wibble...
public class Wibble extends Application {
protected static void DoSomething()
{
// Do your common code here
}
}
Then extend Activity...
public class WibbleActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Wibble.DoSomething();
}
}
Then derive all activity classes from WibbleActivity...
public class Whatever extends WibbleActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// WibbleActivity calls Wibble.DoSomething()
// so the 'Whatever' class doesn't have to.
}
}
Any Activity derived from WibbleActivity will run Wibble.DoSomething() implicitly.
If you want Services in the mix I can't help - I'm an Android 'rookie' and haven't got on to Services yet but I suspect extending your own app-level Service class might work in the same way.
You could extend Application and do it in its onCreate() method.
You have two choices
A) You can manually add the code - it might be only two lines importing and instantiating something from a source file you copy in unmodified - to every separate component that you write. It will only be in your projects, not in other people's unless they do it too.
B) You can, after no small difficulty, learn to make your own custom version of android that automatically does this each time it starts up a suitable component, and install this customized version on developer phones or hacked consumer phones.
"started" is ambiguous - what are you referring to? onCreate? onResume?
In any case, your best bet is to have a separate class with a static method that does the code you are talking about, and you call that in every single onCreate (or onResume, whichever you need) of each one of your activities.
That, or you create your own Activity subclass and derive all your activites from it, and override onCreate (or onResume). All your onCreate/onResume implementations are required to call the superclass' implementation, so you're guaranteed to have your code caled.
I am working on an Application that require some interaction between two activities, and I am not sure of what is the best way to achieve it:
One of the Activities is a "Logbook" (Just a ListView that displays a bunch of events).
The other Activity allows the user to create the events, that will be sent (and displayed in the Logbook).
How do I notify my Logbook Activity when a new Event is ready to be added?
Also, where should I add the event to the database? From the Logbook Activity, when I add it to the ListView, or from the NewEvents Activity, as soon as it's ready?
Thanks!
Ok, I found how to do it, using a BroadcastReceiver:
In my Logbook activity, I just set up a new custom receiver onCreate():
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logbook);
registerReceiver(new EventReceiver(this), new IntentFilter("SEND_NEW_EVENT"));
Now, I can make the calls in my newEventActivity:
public void sendToLogbook(int eventId){
Intent i = new Intent("SEND_NEW_EVENT");
i.putExtra("newEvent", this.newEvents[eventId]);
sendBroadcast(i);
}
Of course, I had to create my CustomReceiver Class, and override the onReceive() method to do what I want:
public class EventReceiver extends BroadcastReceiver {
private ActivityLogbook activity;
public EventReceiver(ActivityLogbook activity) {
this.activity = activity;
}
public void onReceive(Context context, Intent i) {
this.activity.addToReport((Event)i.getParcelableExtra("newEvent"));
}
}
It works great so far, but if you do have comments/concerns about this, please tell me!
Thank you!
If I recall cporrectly the Notepad project which is included in the android sdk and is also part of the tutorials online is a good examaple which should satisfy your needs.
To borrow from MV-* (Model-View-something or other) patterns, separate your idea of the Model (in this case, your Event objects) and what is displaying them (the View, or in your case an Activity) and it'll become more clear.
If you have your events somewhere global where all activities can interact with them, then you can work with the model and display the model from wherever and however you choose.
One simple suggestion is have a class (EventController or something like that) that allows you to interact with the Events collection, and make it available through a derived Application class. I can explain further if that doesn't make sense. I have a pattern I use in my Android apps whereby all Activity classes have access to a custom global Application instance, so my model is a model and can be accessed by whatever Activities I want to have access.
This is merely one approach, and as always, there are many that may suit your needs.
One possibility would be:
The ListActivity gets all the data each time it is resumed and updates the ListView accordingly
The NewEventActivity does all the job of storing the Event and simply finishes
You can improve it a bit more:
The ListActivity gets all the data when it starts
The ListActivity starts the NewEventActivity expecting a OK/CANCELLED result
The NewEventActivity does all the job of storing the Event and returns a result saying OK or CANCELLED
Depending on the result it gets from the NewEventActivity, ListActivity reloads its data or not