So, I'm working inside the android framework classes (AOSP). Since I'm technically working on Cyanogenmod, I'm supposed to set the settings for my patch in an app called CMParts, which just throws the strings and ints into the system settings via Settings.System.
Unfortunately, down in the framework (non application) code, I don't have access to a Context object (because I'm not inside an Activity or Application) to give to the usual method call to get those settings back out. Passing a null doesn't work.
Anyone know ANY way to get to those settings from framework-level-code? Passing down a context reference isn't really an option down that far...
The thing you wrote where quite close to mean something. Can you be more specific?
I do not know what framework you are using. But I'm guessing that it is something internal for your company.
But generically speaking:
if you are not aloud to change the code extend it.
if you need something from the user implementer, force the user to give it to you.
public MyNewFrameWorkClass extends AnotherFrameWorkClass {
private Context context;
// Disallow the user to create an
// instance with out giving you the context
private MyNewFrameWorkClass() {}
public MyNewFrameWorkClass(Context context) {
this.context = context;
}
}
Related
I have several classes in my application that uses the Context object to access SharedPreferences and serialize files. Simply put, I want to know how to "design away" the Context.
The background to why I want to do this is because:
The classes should be created in the onCreate() method of a Fragment (and the Context is not decided at this point)
It's just plain ugly to pass around the Context all the time. Especially since I use Singleton-reminding instantiation of these classes (Don't judge, please)
The specific context isn't really needed here, so it should be possible to design away... (What I mean is that I only need the Application Context)
An example of why this is ugly is my Cache object. It holds cached values downloaded from 1-5 different sources decided at runtime.
public static Cache getInstance(Context context) {
if(instance == null) {
instance = new Cache(context);
}
return instance;
}
When later using this object, it needs to read a SharedPreference which needs the Context, so it has to be passed around every single time I want to get an instance of the Cache.
So how can I get rid of these ridiculous contexts? Using the Application Context should be just fine... I guess that the problem can be boiled down to something like "How do I get a SharedPreferences object" in an object without a specific Context?"
I guess that the problem can be boiled down to something like "How do
I get a SharedPreferences object" in an object without a specific
Context?"
Using the Application Context. For this purpose you can subclass Application, registering it in your AndroidManifest file, and have a method to retrieve it from every where, like a singleton
I have seen the static getContext() method on the Application object before and I think it's slightly ugly and I wasn't sure that it was "Risk free" and correct. I was just about to implement it when I found this: https://androidcookbook.com/Recipe.seam?recipeId=1218 which basically says that the Application object in Android can be treated as a Singleton and that I should place my own Singletons inside that object.
It's essentially the same as #Blackbelt 's solution, but gives a slightly nicer vibe!
Going through some supposedly "good" sources sources to learn the details and tricks of context handling in Android I have come across one pattern multiple time that I fail to understand.
What is the advantage of using a ContextWrapper when you could equally well use the implicit context?
For example why use the following in an activity method (defined directly in an Activity class)
...
ContextWrapper cw = new ContextWrapper(getApplicationContext())
File filesDir = cw.getFilesDir();
...
Instead of just
...
File filesDir = getFilesDir();
...
even though getFilesDir() is defined in the ContextWrapper class the Activity is anyway a subclass of ContextWrapper so you have direct access to the method anyway.
So what potential issue (that I fail to see) does this added complexity address?
I'd say (and I might be wrong) that in the scenario (and context) you presented might not make a difference. getApplicationContext().getFilesDir() could have been used just as easily.
However, I believe ContextWrapper might be useful in other scenarios. From what I understand, this is the adapter pattern. You may want to provide different behaviour only for certain methods while proxying all other to the original context reference you pass in.
Check out this piece of code from RemoteViews:
// RemoteViews may be built by an application installed in another
// user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats
// are loaded without requiring cross user persmissions.
final Context contextForResources = getContextForResources(context);
Context inflationContext = new ContextWrapper(context) {
#Override
public Resources getResources() {
return contextForResources.getResources();
}
#Override
public Resources.Theme getTheme() {
return contextForResources.getTheme();
}
};
The work flow of my program is:
Launch app
Splash screen, check the server api, from the api get a list of file name
Download some of the file in file list , remove the downloaded file name from the list
App opened
when the download is finished , jump to main page that will start download another file in the list
The problem is , the list I was keep in the download manager , when I select don't leave activities in android setting , it will be killed. If I need a class that is some Data Class , that means I put a share data (A several hash map , array list) in it, and it keep updating (delete after async download finish) , and it never get killed. How can it be done? Thanks
The more general problem you are encountering is how to save state across several Activities and all parts of your application. A static variable (for instance, a singleton) is a common Java way of achieving this. I have found however, that a more elegant way in Android is to associate your state with the Application context. As you know, each Activity is also a Context, which is information about its execution environment in the broadest sense. Your application also has a context, and Android guarantees that it will exist as a single instance across your application. The way to do this is to create your own subclass of android.app.Application, and then specify that class in the application tag in your manifest. Now Android will automatically create an instance of that class and make it available for your entire application. You can access it from any context using the Context.getApplicationContext() method (Activity also provides a method getApplication() which has the exact same effect):
class MyApp extends Application {
private String myState;
public String getState() {
return myState;
}
public void setState(String s) {
myState = s;
}
}
class Blah extends Activity {
#Override public void onCreate(Bundle b) {
...
MyApp appState = ((MyApp) getApplicationContext());
String state = appState.getState();
...
}
}
This has essentially the same effect as using a static variable or singleton, but integrates quite well into the existing Android framework. Note that this will not work across processes (should your app be one of the rare ones that has multiple processes).
I am looking for how to share functions and data across multiple activities within a single application. I researched the daylights out of it and find some ideology war between overriding the extend for the application and doing a singleton, neither of which I can find examples sufficient to make me understand. Basically I want to share data and share functions. All activities need the same functions and data so this is not one activity sharing data with another activity. It is all activities needing to have access to the same functions and data.
What I want to know is what is the way to go and how do I do it. I need to see what I need to do in my 34 activities, what the class that is going to be common looks like, and what the Manifest entry needs to be. I also need to be sure the common data area will not be closed by the OS.
This is my first Android - Java program and now find my 15,000 line, 34 activity application needs some structure. I know, should have done things differently but the app works really well with two exceptions. One is that it is structurally a mess. Two is that the fact it is a mess is making it hard to fix one behavior I would like to fix.
This is a GPS based application for racing sailboats. It is timing critical and every activity basically runs a once a second loop inside the location manager onLocationChanged function. That part is fine and I do not want to put the GPS code in one place. The problem is that most activities need to filter the data so a lot of code is copied and pasted to the activities. The filter needs history so it needs to remember a state. There are other functions that are used by several activities so these have been copied as well. Think of a function that averages the last three GPS speed readings. It needs to save some history, do its thing, and give a result. All activities need to do the exact same thing. All this works but the problem is that the averaging starts over every time I switch activities because every activity has its own filter. That gives a glitch in the data that I need to get rid of. I need common place to save the data and hopefully a common place to run the filtering and other functions that are common. If every activity can call the filter function that is using common state data, there will be no glitch across activity changes.
I would appreciate some guidance.
Why you don't just make a Class with only static functions, passing needed Parameters? An example if you want to show an ErrorDialog
public class SharedHelper{
public static Dialog showErrorDialog(Context ctx, String message, String title, DialogInterface.OnClickListener okListener, DialogInterface.OnClickListener cancelListener){
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setMessage(message).setTitle(tilte);
if (okListener != null){
builder.setPositiveButton(R.string.button_positive, okListener);
}
if (cancelListener != null){
builder.setNegativeButton(R.string.button_negative, cancelListener);
}
return builder.show();
}
}
Singletons are (from my point of view) one of the uglyest design pattern and will bite you sooner or later. Putting anything in Application requires you to cast it everytime to the Special Application class you designed. A class with only statics however is very flexible in its usage and doesn't need an instance to work.
For the storage-issue:
lookup "SharedPreferences" & "SQLite" and decide afterwards which storage-type suits your needs more.
For the methods-issue:
This question is a bit more complex and there are different ways to do it. For example you could write a parent-class that implements all your globally needed questions and you let all your activity-classes inherit from it.
public class MyParentActivity extends Activity {
public void myMethod() {
}
}
and:
public class Activity1of34 extends MyParentActivity {
myMethod();
}
I think what this comes down to is not an Android problem but an Object-Oriented Programming problem. If I understand the situation correctly, I'm betting the best solution would be to take your shared filter and create a new Filter class that is instantiated within each Activity (this is likely more manageable than a singleton, but not having seen your use case, it's hard to say for sure). If you need to centrally track the averaging, you can simply create a static variable within the Filter class that maintains the same value during the life of the application. If you really want to maintain that average (even past the application's current lifecycle), you can persist it in a database or other local data options. However, I don't see any reason to put everything in a singleton just to maintain that average. Singletons (and all static data structures) can be potentially troublesome if used incorrectly.
I, for one, do not mind the singleton pattern. Of course as everything else it should not be abused.
This is the construction I use for my shared objects. My app is divided into modules this way but can just as well be used in your case.
public class SharedDataObject {
private Context context;
private static SharedDataObject instance;
public static SharedDataObject getInstance() {
if (instance == null) throw new RuntimeException("Reference to SharedDataObject was null");
return instance;
}
public static SharedDataObject createInstance(Context context) {
if (instance != null) {
return instance;
}
return instance = new SharedDataObject(context.getApplicationContext());
}
// notice the constructor is private
private SharedDataObject(Context context) {
this.context = context;
}
...
public void myMethod() {
// do stuff
}
}
Notice that it uses the application context, that means among other things, means that the context owned by SharedDataObject cannot be used for GUI operations. But, the context will live for the entire lifetime of the application, which is nice.
Furthermore I hate having to pass a context everytime I wish to call methods on my SharedDataObject, thus I have a splashscreen calling SharedDataObject.createInstance() on all my modules.
Once an instance is create, I can call:
SharedDataObject.getInstance().myMethod();
Anywhere in my code, regardless of a context being present or not (from the place calling this code that is).
I was wondering what is the best way to handle global variables for android apps. For example, I'm just trying to create a basic login/register system. I've created a user class (that has various attributes like username, password, etc..), so that when we go to the register activity, the User class constructor is called to create a unique user object once all the fields are filled out. I was then thinking of simply having a global arrayList of type User so that I could just loop through all the users on a login attempt.
So far (due to a combined lack of experience in java, and being very new to this android stuff), I haven't been able to implement this successfully. I have a class which I call "globalStuff" which has a bunch of public static variables (i.e. the list of users and current user), which I thought could be accessed from any activity the user navigates to.
There must be a better way to go about this. I've been reading through a few tutorials and a few posts on here, but none address this very basic idea. So what would be the best way to approach something like this?
Thanks for any help!
It's called a static singleton and it looks like this:
public class Global {
private static Global instance = null;
public static Global getInstance() {
if( instance == null )
instance = new Global();
return instance;
}
// additional methods, members, etc...
}
Then you just refer to it in your code as:
Global.getInstance().getUserList();
etc.