I write an Android application. I have a lot of Activities in my application with a large number of transitions between Activities. I decided to realize a state machine, which will switch my activities.
I hoped to realize a State Machine in my Application class or its subclass, but I can't start any Activity from it.
public class MainAppClass extends Application {}
the code like this is failing:
Intent intent = new Intent();
intent.setClass(this.MyActivity, Screen2Activity.class);
StartActivity(intent);
Maybe, is it unreal? Are there other methods for such tasks?
Thanks for your answers!
Here's another question: Why are you trying to start an activity from a subclass of Application?
Read this (from the documentation) and you'll see why what you are trying to do doesn't make any sense.
The Application class is the base class for those who need to maintain global application state. 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.
If you edit your original post, clarifying why you are trying to do this, perhaps I can point you to a more suitable means of launching your Screen2Activity.
Related
I am reading that the playframework is removing global state that is in older 2.4.x versions.
Can someone explain where the global state currently is and what are the benefits of removing global state?
What is the global state?
There is an object play.api.Play with the following field:
#volatile private[play] var _currentApp: Application = _
Where is it used?
Whenever you do Play.current you refer to that single mutable global field. This is used all across the framework to access things such as:
play.api.Play.configuration takes an implicit app
play.api.libs.concurrent.Execution.defaultContext calls the internal context, which uses the currently running app to get the actor system
play.api.libs.concurrent.Akka.system takes an implicit app
play.api.libs.ws.WS.url takes an implicit app
and many more places..
Why is that bad?
A number of functions just take an implicit app, so that's not really global state, right? I mean, you could just pass in that app. However where do you get it from? Typically, people would import play.api.Play.current.
Another example: Let's say you want to develop a component that calls a webservice. What are the dependencies of such a class? The WSClient. Now if you want to get an instance of that, you need to call play.api.libs.ws.WS.client and pass in an application. So your pretty little component that logically only relies on a webservice client, now relies on the entire application.
Another big factor and a direct consequence of the previous point is testing. Let's say you want to test your webservice component. In theory, you'd only need to mock (or provide some dummy implementation of) the webservice client. However now that somewhere in your code you're calling play.api.Play.current, you need to make sure that that field is set at the time it is called. And the easiest way to ensure that is to start the play application. So you're starting an entire application just to test your little component.
Objective: I want to develop an UI application that runs a service/ task/method
periodically to update database. This service should start after
periodically even if my application is not active/visible/user exits
app. Similar to an Android Service .
I'm using BlackBerry Java 7.1 SDK eclipse plugin .
The options I came across are the following:
1) How to run BlackBerry application in Background
This link suggests that I extend Application instead of UIApplication. But I can't do that as my application has a user interface.
2) Make application go in background
I don't want my UI application to go in background, instead i just want my application to call the service periodically .
3) Run background task from MainScreen in BlackBerry?
This link suggests to run I a thread, but I don't think that if user exits my application then the thread will run in background
4) Blackberry Install background service from UI application?
This suggests using CodeModuleManager ,whose usage I'm unable to figure .
Please suggest what is the best way to achieve this objective or suggests any other better method .
I am new to blackberry so please pardon my ignorance.
To expand on Peter's Answer:
You will need to create two classes :
class BgApp extends Applicaton
class UiApp extends UiApplication
I guess you have already created the class that extends UiApplicaiton. So add another class that extends Application.
Then create a class that extends TimerTask and implement its run method to call the method that updates the database.
class UpdateDatabaseTask extends TimerTask
In the BgApp constructor, create a Timer. And schedule the UpdateDatabaseTask using the schedule(TimerTask, long, long) method.
Define alternate entry points, check the "Do not show on homescreen" and "auto run on startup" checkboxes for the bgapp's entry point.
It is easiest and simplest to use the builtin persistence mechanism (PersistentStore and Persistable interface) for storing data. Even if you use any other means like RecordStore or SQLDb, both UiApp and BgApp can use access the same database. The values updated by the bgapp will be accessible by the uiapp and vice-versa, automatically.
If you want to send a signal from bgapp to uiapp (for example when bgapp downloads new data you want the uiapp to reload the data instantaneously), post a Global Event (ApplicationManager.postGlobalEvent()) when the download is complete and listen for it in the screen that is displaying the data (GlobalEventListener interface).
There are code samples for each of these available as part of the SDK or search on the internet and you'll find a lot of implementations.
Good research, lots of interesting thoughts.
I think the best thing to do is to try the simple standard approaches and only make something more sophisticated if you need to.
Here are two options that would be regarded as 'standard', with brief advantages and disadvantages:
a) Make your UiApplication go to the Background
Instead of exiting when the user presses the 'close' button, your UiApplication will "requestBackground()". it will automatically be bought to the foreground when the user clicks on the icon, or selects your application from the task switcher. Then you can run a Thread whenever you want or in fact leave one running to update the database.
This is my preferred method. But you have to careful with memory management to make sure there are no leaks. And some people don't like the idea that the Application is visible on the Task Switcher all the time.
b) Alternate Entry
With this option, your one Application package contains two Applications, or more accurately, one Application and one UiApplication. The UiApplication is run when the user clicks on the icon. The Application runs as a background task, and updates the database for your UiApplication.
This looks like a more elegant solution, but introduces some possible communication issues, and is more difficult to debug.
In your case, since you are relatively new to BB, I would suggest that you use option a, and if you find it doesn't work for you, you will not find it that difficult to swap to option b.
And to comment on the Options you have already presented:
Sort of covered with option b
Option a
You are correct - if an Application exits, all the Threads are killed
Leaves the problem of creating the application in the first place and then debugging it. This is not really a solution for you, more an implementation method.
The above is brief, please ask if it is not clear.
This might help with b:
http://supportforums.blackberry.com/t5/Java-Development/Set-up-an-alternate-entry-point-for-an-application/ta-p/444847
Edit:
Editing this to respond to the questions and to expand on the alternative answer, which expanded on this one (bit circular I know...).
To answer the second question first, I agree with the other answer which states the alternate entry (background) and the foreground app can share an SQLite database.
With respect to how these two communicate, while they work just fine, personally I am not a great fan of Global Events because they are propagated to all Applications on the BlackBerry. You can achieve similar things in many alternative ways - the trick is to find something that is common to both applications so that they can communicate. To this end, I recommend using RuntimeStore. See this KB article:
http://supportforums.blackberry.com/t5/Java-Development/Create-a-singleton-using-the-RuntimeStore/ta-p/442854
Regarding how you persist your database, I like PersistentStore because it is present on all devices. But if you really have a database, and not persistent Objects, then SQLite seems the ideal thing to use. Personally I would not use RecordStore, but here is a discussion of the options:
http://supportforums.blackberry.com/t5/Java-Development/Introduction-to-Persistence-Models-on-BlackBerry/ta-p/446810
And just a clarification - in the example given, you have two applications, BgApp and UiApp. You will only have one main() method. This main method will use the args that you specify to determine which one to start, which it will create and have it "enter the dispatcher". If I could make a recommendation - use "gui" as the argument to specify that you will start your UiApplication. I have experienced a circumstance that the OS attempted to start my alternate entry Ui application with this String, regardless of what I had actually specified. Might have been a one off, but I have stuck to doing that ever since.
Finally two comments on the use of Timers and Timertask to provide triggered events. The first comment to make is whatever you run in the TimerTask should not take that long - so you should just use the TimerTask to initiate the download Thread (which might take a long time). Secondly for me, in this situation, I would not use Timer/TimerTask. I would rather just have a single Thread, which 'waits', and then processes. The advantage to me is that this can be adaptive. For example, if you fail to connect, then you might shorten the time till the next connection attempt. Or if it is after hours, then you might lengthen the time between connections to reduce battery usage. Or you might stop connecting completely when the battery is very low.
Hope this helps.
I have a program with about 8 Activity classes, and 1 Application class. I want my Application class to be able to communicate with every Activity, but on its own terms. I don't want the activity to ask the Application for data, I want the Application to send the Activity data. The problem with this, is that depending on the current state of the program I'm unsure what Activity will be open.
Is there a method of some sort which will send information from the Application to the CURRENT activity?
The Application class connects with an embedded Bluetooth Device and needs to receive different pieces of data depending on which Activity the user is currently in. I originally had it as a regular class, which was initialized in the MainMenu of my program and passed a Handler. However, it seemed like weak design to pass that Handler from Activity to Activity time and time again.
You could use a Callback Method
Every Activity has it's own callback method and registers that method onResume() in the Application Class. (it's like an onApplicationWantsToDoSomethingWithMeListener() ;)
or why not a Service in background? instead of the Application, since what you want sounds like a Service. More details?
EDIT:
I made a similar application with bluetooth, you should definetly use a Service for that, but you can communicate with your service per Application. Say the Service calls the callback in the Application look here for an implementation uf such a thing
I have a GWT MVP application using Activities and Places. This is inspired by Mauro Bertapelle's sample (in this thread), apparently based on some of Thomas Broyer's work.
Here's the problem: I have LoginActivity make an RPC call, which for a successful login, returns a User. This user has a role (e.g., admin, regular user, guest). Several Views and Activities, including a NavigatorView, depend on this role for what they show or do. How do I get this User instance to the other Activities?
I do not have a ClientFactory; injection (Gin) is used for instantiating the Views in the ActivityProviders which provide my Activities/Presenters, and the ActivityProviders are injected into my ActivityMapper. So this may reduce to a Gin question: how do I get the user reference where it's needed? This seems to be similar to this SO question about global references in MVP.
Consider me a Gin newbie, this is my first attempt at using it. I'm guessing there is a "Gin way" to make this happen, but I don't know Gin well enough to know the best way to do this (if Gin should be used at all).
Much thanks.
Edit 1: Despite my best efforts searching SO for a similar question, I just found this question which is pretty much identical to mine (is the SO algorithm for finding "Related" links better than the search?). I'm thinking that the Gin answer by David is on the right track.
I don't think that an EventBus solution is possible. I'm following the Google guidelines which involve instantiating Activity at every Place change, so a single Event by itself will not suffice.
Something that I'm using on the server-side with Guice, and would work just as well on the client-side, is to bind to a custom Provider. In your case though, you'd have to make the provider a singleton and push the value into it from your RPC callback (rather than pulling it from some context).
You'd first need a specific provider:
#Singleton
public class CurrentUserProvider implements Provider<User> {
private User currentUser;
public User get() { return currentUser; }
public void setCurrentValue(User currentUser) {
this.currentUser = currentUser;
}
}
You'd bind User to the provider: bind(User.class).toProvider(CurrentUserProvider.class)
In your RPC callback you'd inject a CurrentUserProvider so you can setCurrentValue but everywhere else you'd inject Provider<User> to keep CurrentUserProvider as an implementation detail. For very short-lived objects, you could directly inject a User value rather than a Provider<User>.
If you need to notify objects of the value change, you could dispatch an event on the global event bus.
Alternately, you could always use the concrete CurrentUserProvider type (which wouldn't have to implement Provider anymore) and possibly make it a HasValueChangeHandlers so you could register listeners on it rather than on the event bus (but you'd have to clean-up after yourself in your activities' onStop and onCancel to avoid memory leaks, whereas it's taken care of automatically if you register handlers on the event bus in onStart).
(if you ask me, I'd rather go away with authenticating from within the app whenever possible)
I had similar requirements on a recent project.
When I get a reply from login (or logout) RPC I send a custom AuthenticationEvent on EventBus. All activities that are interested in this listen for this event. AuthenticationEvent has a reference to AppUser object which is null if user just logged out. AppUser contains all necessary data (privileges, groups, etc..) so that activities can inspect it and act upon it.
About global references: you can have a class with static methods providing data that you need. This class internally holds singleton references to needed instances. In my example I have static method AppUtils.getCurrentUser(). Internally it holds a reference to AppUser and also listens to AuthenticationEvent to set/reset this field.
As a side note: don't rely on client side to enforce access restrictions - you should separate your RPC servlets into two groups: public and private. Public can be accessed by anybody (this is basically login/logout RPC and some other public info RPC), while private RPC requires user to be authenticated. Access restrictions can be set per path/servlet: http://code.google.com/appengine/docs/java/config/webxml.html#Security_and_Authentication
Update:
As you noted, class with static methods is not advisable in this setup, because it is not replaceable and this prevents testing (which is the whole point of using GIN).
The solution is to inject a utility class holding globals (AppUtils) into activities that need the globals. AppUtils should be declared singleton in GIN configuration as one instance is enough for the whole app.
To use Provider or not is just a question if you want to delay the initialization of dependencies (AppUtil is dependency). Since AppUtils is a singleton for the whole app it makes no sense to have it lazy initialized.
Sometimes you will have a situation where you have multiple Activities shown on screen (in my case it was MenuBar and InfoBar). In this case, when user logs in you will need a way to notify them of the change. Use EventBus.
I'm working on a new iPhone/iPod app that includes the need to do web services requests. I've found methods for doing these requests synchronously, or asynchronously by setting the controller as the delegate. What I'd really like to be able to do, though, is to create a single class that can handle all web requests for the whole application, and just create an instance of that class when I need to use it. That way, cookies and common pieces of code can be handled in one place, rather than all over the app.
So far the only thing I thought of that could accomplish what I'm trying to do is to create a new thread that handles the request synchronously within itself, then sends a message back to the calling controller once the request is complete. Is there a better way to accomplish what I'm trying to do?
Cookies are already a shared resource.
I would suggest reading the URL Loading System Overview to get an idea of how Apple set everything up. From what you describe, you want something very similar to how they have set up the system, maybe with a Singleton class for the connection. You can also look at ASIHTTPRequests which is a good wrapper around all of the connections stuff.
I would not suggest writing my own code here. Lots and lots of people have solved this problem for you.