Intent service singleton - java

I want to implement a Service that acts like a Singleton.
I need my App to check if the screen is locked, then start a Listener IntentService. If the screen becomes unlocked, it will kill the Listener service.
I created a ScreenLockService that is an IntentService and is called by the Home activity if the user checked the on/off box because I want the Listener to run even if the the App isn't running.
So the Home activity runs and stops the ScreenLockService service which will run and stop the Listener service.
My problem is that the Home Activity creates multiple instances of ScreenLockService which also creates multiple instances of Listener.
So I'd like to have these two IntentServices run as Singletons, but I'm not sure how to do so.
I've checked out a bunch of tutorials, but they're either out dated or not tailored to IntentServices such as:
http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/
Singleton in Android
I can post some example code of what I have if necessary, but all I'm really looking for is a how-to.

Well the basic idea for implementation of the Singleton patterns is to make a private [or protected] constructor (which means it will not be accessible from outside the class). The class also needs a private field of it's own type (e.g. private MyClass myObj;) Next thing you need is the public static method called something like newInstance() which returns the instance of the class via myObj if it's not null, and instantiate it if it is:
public static MyClass newInstance(){
if (myObj == null) {
myObj = new MyClass();
}
return myObj;
}
Of course it can have a more complex implementation (the constructor does not have to be without parameters).
Now this will always create exactly one instance of the desired class. All you need to do is to always call the method newInstance in the place where you need to use your class. If it was already instantiated, it will give you the old instance, if not, it'll create it.
Hope this was the explanation you were looking for.

Related

Java - Creating a class to dynamically determine if user has access to the calling method

I have tried doing a search for this but I fear I may not be wording what I want to do very well.
Currently, we have about a hundred action classes in our application with each determining if a user has access to it. I would like to make a class that can figure out the calling method, what permissions are required for it, and if the user has those permissions. Unfortunately, I don't really know how to even get started with this as each class may have slightly different requirements.
I'm happy to add more explanation if needed but as I said, I'm not sure I'm wording what I'm trying to do very well so if anyone has a better way of putting it that gets me some google results or a link to a related question here that's already been answered, I know I'd appreciate it.
current permissions checks look like below. This is a simple implementation, there are usually multiple profile checks in one if block.
If (scc.getUser().getCurrentProfile().getSystemAdmin() != 1) {
logIllegalAccess(log);
break;
}
IMHO the most elegant solution would make use of annotation processing. The idea is that you would annotate action classes with a custom annotation, something like:
#RequiredPermission(Permissions.SYSADM)
class ActionA {
public ActionA newInstance() {
return new ActionA_Gen(new ActionA());
}
private ActionA() {...}
...
}
Action classes would have to have a newInstance() method to be used to create instances instead of calling new. The method would create an instance of a class by the same name with _Gen extension. This class would have one method for each method in the original action class, which would perform a permission check and call the corresponding method in the original class instance that was passed to its constructor.
The _Gen class would be generated by an annotation processor.
Note that by using reflection it might be possible to move the newInstance() method in a common superclass.

How to correctly implement communication between Java classes

I'm a beginner in Java programming and I'm currently working on an app with more complex class structure and a GUI. This might be a stupid questions, but it is very hard to google, so I'm asking here.
I have a main class, looking like this:
package app;
public class App {
private FirstClass fc;
private SecondClass sc;
public App () {
fc = new FirstClass ();
sc = new SecondClass ();
// ... code continues ...
}
}
Say the SecondClass is defined outside of this .java file (like GUI forms are). Is there a way for me to access the "fc" instance (or other member variables of the App instance) from the "sc" instance (without passing the "this" pointer)? Something like:
class SecondClass {
public void someMethod() {
getWhoeverCreatedThisInstance().fc.getSomeData();
// ... code continues ...
}
}
And if not, what am I doing wrong? Should I design this differently? Maybe setting the "fc" as static? But what if I want more of my app's classes to communicate with each other, should I make them all static? What would be the point of having something non-static then? I could pass the "this" pointer of "App" or "fc" instance in the constructor of "SecondClass", but that solution just seems non-elegant when the number of classes that need this behavior rises.
Any ideas? Thanks in advance!
My suggestion is to implement a callback system with interfaces. Each of your classes communicating with each other should implement these.
The classes should Register to the creating class.
Then they can call a method in the creating class which invokes the interface method of each registered class and passed the data this way.
This SO answer might help
https://stackoverflow.com/a/18279545
If you want to develop GUI applications, you should really get into the basic concepts. This can be very time-consuming, but it is necessary, otherwise you will encouter strange behaviour. I will just give you a basic understanding to answer your question.
You think of simple console applications, where you usually have a single thread and passing around objects is valid. With multiple threads, this is fatal, even with static variables. Each variable or object can be modified concurrently and the other thread may not be able to 'see' the changes in time. This is a complex matter, since there are also caches and separate stacks for each thread. In short, fc may not always be synchronized in App and sc, therefore reads and writes may be inconsistent.
What to do now? Learn the concepts of GUI programming. Often you do not even have to share objects for simple things. If a GUI control triggers an action, use a Listener, look here. If you want to access a database for example, then just make a new connection object for each request or button click, whatever. This is simple to start, add complexity later.
A simple variant to share objects is to use the synchronized keyword, which ensures that a method or a field is only accessed by one thread at a time. Here is an example. Also look at thread-safe data structures provided by Java (java.util.concurrent).
For advanced purposes you would have a separate thread and you would connect them with Sockets to pass messages or data.

Does static class have the same lifecycle with Android Application?

At the very first, my code looks like this. The datacenter class need context to reach SharedPreference.
class App extends Application
{
private DataCenter dataCenter;
#Override
public void onCreate() {
super.onCreate();
dataCenter = new DataCenter(this);
}
}
When I use dataCenter in my activity, I had to getApplicationContext(), and cast to my App, then get the dataCenter object.
And then I searched stackoverflow, and realize I can make App has a static field to reference itself.
class App extends Application
{
private DataCenter dataCenter;
public static App me;
#Override
public void onCreate() {
super.onCreate();
App.me = this;
dataCenter = new DataCenter(this);
}
}
By doing so, I no longer need to call getApplicationContext() and make the casting, just need App.me.getDataCenter(), in my activity class. And also in the App's constuctor, I could even, not to pass context to dataCenter's consctrutor, just ref App.me in DataCenter class directly.
(Q1) I am woundering if what I am doing is OK, any risk here?
After that, I realise if I want to use dataCenter in my activity, "App.me.getDataCenter()" is still too long for me
(Q2) Can I just make the DataCenter class static as it can access App.me to get the context statically?
(Q3) is static class has the same lifecycle with android's Application ? and the Application class always initial first?
First of all, it's better to change scope of the variable me to private, change its name to something better and more descriptive (e.g. instance) and create get() method, which will return instance of the Application. When you leave this variable public, it can be changed and I guess you don't want it.
(Q1) I am woundering if what I am doing is OK, any risk here?
After that, I realise if I want to use dataCenter in my activity,
"App.me.getDataCenter()" is still too long for me
I think, you should use one instance of SharedPreferences class. If DataCenter uses SharedPreferences, you shouldn't mix context of application and activity. You should choose one context and keep using it constantly. In my opinion, context of the application is a better choice, because you may want to use this object in many activities. Moreover, you don't need to call App.me.getDataCenter() everytime in the activity. Just pass it inside the Application class.
(Q2) Can I just make the DataCenter class static as it can access
App.me to get the context statically?
You can, but you should avoid static classes. When you use static classes, it's harder to write unit tests for your application. Moreover, static objects are not elected for garbage collection while the class is loaded. It means, that your application will consume more memory of the device and will be less efficient.
(Q3) is static class has the same lifecycle with android's Application
? and the Application class always initialed first?
Application's Lifecycle shouldn't change while using static variables in class which derives from Application class.

Android: How do you pass a callback to an activity?

I am creating a library. It creates an activity, starts it, and finishes it after a button is pressed.
After the button is pressed, I'd like to execute some client code through an interface.
That is, users of this library pass in an implementation, and I simply execute it.
The analogous iOS code would be:
MyViewController *vc = [[MyViewController alloc] init];
vc.callOnComplete = ...
[self presentViewController:vc animated:YES completion:nil];
The desired code is:
public interface SaveStuff {
void save();
}
In my library's Activity:
private SaveStuff saveStuff;
public void onButtonClicked(View v) {
saveStuff.save() // client passes in saveStuff obj
finish();
}
I've tried serialization. I made a class that implemented the interface and also implemented Serializable, and tried passing that in and extracting it with getSerializableExtra. I end up getting a non serializable exception. So far as I know, this is probably not a viable solution, as it would mean that clients must use only serializable classes in their implementations. Correct me if I am wrong on this. In my trials, the client activity was showing up in the non serializable exception.
I've tried using a static reference. Basically global state/singleton. As it turns out, according to a variety of answers such as this one: Java Static Variable becomes null, I cannot rely on any static state, and any solutions that do work with static state are just working coincidently.
I haven't tried simply starting the activity with startActivityForResult, because that would require me to cast the context we are accepting as a parameter to an Activity.
The activity is started inside the library with this:
private void startNewActivity(int newVersion) {
Intent i = new Intent(context, MyActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i); // context variable is passed in by the client
}
As you can see, context is passed in by the client. I could perhaps cast the context to an Activity in order to call startActivityForResult, but I don't want to do this, as I have read that is not always safe. I could require that an Activity be passed in. This is perhaps a reasonable requirement, but I don't want to go there just yet.
I've looked at the existing questions and something I haven't tried is using broadcasts. Correct me if I am thinking about this incorrectly, but the best I could do is have the object that holds the reference to client interface implementation be a broadcast receiver, and then send a broadcast in the activity that I create. I am worried that the receiver will not persist, however. What happens if my library shows the user the activity, but then the user kills the app before pressing the button? The reference to the client code was held by the previous activity. Will nothing happen upon pressing the button?
Should I just broadcast a message, and leave it up to the client to handle these cases? How would the client handle this? Register something on app start up/shutdown? Do I have to force the user to do this to use my library? Is it reasonable?
Update:
As it turns out, we are just going to have the activity in the library access a singleton.
To avoid all the issues with state being wiped based on activities being killed and the like, users of this library will be required to run a 'setup' method on the singleton, and pass in the callback obj there. They will run this on some sort of base Activity's onResume.
I'll wait a little before answering self-answering this question to see if there any alternatives.
Why don't you use same process for android as well i.e.
1) make an interface
2) declare a public variable of interface in your activity.
3) user will initialize that interface when start to launch your activity.
4) use the interface variable to call the method.

Can one class in java control object in another class?

Suppose I have a class called Factory. I intend to have that class publicly accessible so anyone can create and access the factory. I want the factory to create and distribute widgets. I only want the factory to be able to create widgets, not anyone in the public program space. However, I'd like to have a method called distribute() that would give out a widget to the main program. At that point the main program could access all the public methods of that widget. It could also give it back to the factory if need be, thereby removing any public access to that object.
If this is possible, how does one accomplish this?
What you're looking for is an inner class. By declaring the constructor of the inner class private, only the encapsulating class can access it! Then you create a factory method in the outer class to build the widget and distribute it. I've declared it static here, but that's not necessary, depending on your needs.
public class Factory {
public static Widget buildWidget() {
Widget widget = new Widget();
return widget;
}
public class Widget {
private Widget() { ... }
public void someMethod() { ... }
}
}
Note that in clean code your other concerns must be addressed by being careful about your referential integrity. To 'give back' the widget all other references to it must be released. Your Factory can certainly keep track of what widgets it's given out, but it's very hard to 'recall' widgets reliably.
You're describing access control that changes over time ("It could also give it back to the factory if need be, therby removing any public access to that object."). Java doesn't work that way. All of the access qualifiers are statically checked, and remain constant for the entire lifetime of the program.
Place the widgets in the same package as the factory, and set the widget's constructors to have protected visibility. This will restrict the creation of objects to the factory.
For each widget, the access control can be partially implemented. You can keep a List in each of the widgets of Objects that are allowed to access, and only the factory can modify this list (protected visibility). For all public functions, you require the user to pass in an object that has been authorized to access the functions of the widget. You can return the object by passing the object that is authorized back to the factory so that it will remove the authorization.
You can pass a private object in the main class as authorization object - this will prevent other classes from using the widget. However, this doesn't prevent other classes from asking for authorization, though.
This is a bit flaky, since you may forgot to release the authorization and clutter the widget with "undead object" (not used anywhere else except for the access control list in the widget).

Categories

Resources