Is there any reliable way to get a Context from a Service?
I want to register a broadcast receiver for ACTION_PHONE_STATE_CHANGED but I don't need my app to always get this information, so I don't put it in the Manifest.
However, I can't have the broadcast receiver be killed by the GC when I need this information so I'm registering the broadcast receiver in a Service.
Hence, I need a Context to to call registerReceiver().
When I no longer need the ACTION_PHONE_STATE_CHANGED I unregister it.
Any tips?
Service is a Context
Service extends ContextWrapper which extends Context. Hence the Service is a Context.
Use 'this' keyword in the service.
Service extends ContextWrapper
ContextWrapper extends Context
So....
Context context = this;
(in Service or Activity Class)
just in case someone is getting NullPointerException, you need to get the context inside onCreate().
Service is a Context, so do this:
private Context context;
#Override
public void onCreate() {
super.onCreate();
context = this;
}
Note:
Read: "Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)" Do you know what context classes are? Activity is one of them, and you should not store Activity as a static field, (or it will leak memory). However, you can store Context (as long as it is the application context) as a static field, since it outlives everything.
Since Service is a Context, the variable context must be this:
DataBaseManager dbm = Utils.getDataManager(this);
As Service is already a Context itself
you can even get it through:
Context mContext = this;
OR
Context mContext = [class name].this; //[] only specify the class name
// mContext = JobServiceSchedule.this;
If you want service context then use this keyword. if you want activity context you can access that by using by making static variable like this
public static Context context;
in the activity onCreate()
context=this;
now you can access that context inside the service
Related
I have a class that's inputting some data into SharedPreferences.
private static Context context;
context = MainActivity.getContext();
sp = (SharedPreferences) context.getSharedPreferences("currentData", Context.MODE_PRIVATE).edit();
SharedPreferences.Editor editor = sp.edit();
editor.putString("name", placeName);
editor.apply()
I set the context using a method in my MainActivity class:
public static Context getContext(){
return context;
}
However I keep getting a null object reference. Tried multiple solutions from stack overflow and can't overcome the issue.
Why is context returning null?
This is because MainActivity.getContext() is null try passing the context from MainActivity to your class.
public Context context;
public YourClass(Context context) {
this.context= context;
}
In MainActivity init it like this:-
YourClass yours = new YourClass(MainActivity.this);
And also avoid using static contexts it might cause memory leaks !!
Context is an abstract class whose implementation is provided by the
Android system
Context is provided to any Activity by the android system during runtime (Activity indirectly extends Context). You are trying to get Context from MainActivity class via static method, which will not work and will always return null:
context = MainActivity.getContext();
You should always get Context from an instance of Activity, not the class itself. You can do this easily by passing an instance of your current Activity to the constructor of your class. Then, you call getContext() on an INSTANCE of that Activity, not the Activity class itself.
Also, wanted to mention that your code is mostly anti-pattern. You should never store Context in static variables. I'd recommend you read more about Activity lifecycle in android and Context - these are fundamental knowledge.
You can get context statically throughout the application
please try below code:
In the Android Manifest file, declare the following.
<application android:name="com.xyz.MyApplication">
</application>
Use this class
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Now you can call MyApplication.getAppContext() to get your application context statically.
You are getting the context from a static method in the class, that mean that method is called before the class is actually initialized. If there is no actual instance of the activity or if the OS haven't provide with context to the activity, then is null. The Activity has access to the contexto but after the Android underlining management initialized it, the class won't have the context by it self because it is there, if you notice Activities are never instantiated using the constructor because Android does it for you.
If you want to use a static method to having a nice syntax then the static method should be inside the class that use the shared preferences and should be passed from the activity, during any method of the Activity life cycle or when the user interacts with the ui (those listeners are set on the Activity life cycle).
class MyPreferences {
static void save(String toSave, Contex context) {
//TODO your operation here
}
}
And your activity:
public class MainActivity extends AppCompatActivity {
//Below is pseudo code, be careful on doing this precisely in the activity
#Override
onCreate() {
//TODO call super and setContentView
MyPreferences.save("foo", this);
}
}
It seems your problem is you are trying to make the other class to use the Activity, but in Android is the Activity that uses other classes
I have a class like this :
public class ExpandableListAdapter extends BaseExpandableListAdapter {
I want to run a service from this class. But as I know, services can only be run from Activitys . So what is the solution?
How can I start a service and control it from another class?
But as I know, services can only be runned from Activitys
That's not true. In order to run the service you just need a context, that is usually a reference to your activity.
So, inside ExpandableListAdapter you just make sure that the constructor receives an instance of your activity:
public ExpandableListAdapter(Context context){
mContext = context;
}
// somewhere else
mContext.startService(theIntent);
Most adapters have a context so you can make a call to getContext() which will give you a context back. This adapter does not have a context so you should have a custom constructor that takes a context and calls its super. Using the context you passed in you can call startService(Intent intent) just like you would in an activity.
I handle login for my application in a class that extends application. The application then maintains an object of this class at all times. This means that I can access that specific object from any class that extends activity or service by calling
LoginModeller lm = ((LoginModeller)getApplicationContext());
However, I now need to access the object from a class that does not extend activity or service (It extends nothing). Is there some way to access the application context from a class like this, or I do have to re-factor my LoginModeller as a singleton or something?
Who creates this object? In your constructor you can pass in a Context and store it as an instance variable:
private final Context context;
public MyObject(Context context) {
this.context = context;
...
I don't know if you are using DI with roboguice but I am :)
From my point of view, the cleanest way to do this is using a staticInjection. Here's how.
I have a class that needs to obtain a reference to it's application's AssetManager. This class does not extend any sort of android UI class, so it doesn't have a getContext() method, or anything similar. Is there some sort of static Context.getCurrentApplicationContext() type of method?
To clarify: my class is intended to be used like a library, for other applications. It has no associated AndroidManifest.xml or control over the context which is calling it.
Create a subclass of Application, for instance public class App extends Application {
Set the android:name attribute of your <application> tag in the AndroidManifest.xml to point to your new class, e.g. android:name=".App"
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp():
This is how it should look:
public class App extends Application{
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Now you can use: App.getContext() whenever you want to get a context, and then getAssetManager() (or App.getContext().getAssetManager()).
I am not sure of the best answer to the OP question. However, I do know that you have to be very careful when using a static context as suggested in Android developer resources:
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp():
Using static contexts can leak to leaked memory issues, especially if the static context is used for references to views.
I'm defining a class that sets a Drawable attribute in an object. The problem is that I can't access the getResource().getDrawable(int resourceId) method unless I have some Context.
What I did was to send to that class an activity instance (let's call it "act") and then I did:
act.getResources().getDrawable(R.drawable.whellchair)
but, when executing that line it throws a NullPointerException.
When idea how to accomplish this?
I found the problem!
I'm using a singleton and I put the line accessing the "act" in a static method... how fool of me ...
Sorry and thank you Juhani for the comment :)
Pass that the application context to the constructor of your class. In the main application class you just get the context by invoking the getApplication() method if you need the a lifetime aware context or getApplicationContext() if you need a the context which is tied to the current process.
Example:
private Context ctx = getApplication();
... some code ...
MyClass myClass = new MyClass(ctx);
Your classes' constructor of course has to handle the context accordingly (i.e. setting a private member of type Context to the passed value) like this.
private Context ctx = null;
public MyClass(ctx) {
this.ctx = ctx;
}
Then you can use the context for whatever you need.