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.
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'd like to get my string-array without extending Activity in my custom class. Is there a way to do this?
String[] foo_array = getResources().getStringArray(R.array.foo_array); will not work without extending Activity, so I need a work-around.
Pass the context to the constructor of custom class and use the same
new CustomClass(ActivityName.this);
Then
Context mContext;
public CustomClass(Context context)
{
mContext = context;
}
use the context
String[] foo_array = mContext.getResources().getStringArray(R.array.foo_array);
Also keep in mind
Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html
Also check this
android getResources() from non-Activity class
Edit:
Change this
public class CustomClass(Context context)
{
}
To
public class CustomClass
{
Context mContext;
public CustomClass(Context context) // constructor
{
mContext = context;
}
}
try this,
Context context=getApplicationContext();
String[] foo_array = context.getResources().getStringArray(R.array.foo_array);
And, do not use Activity Context as that is tied to the Activity life cycle.
Update,
getApplicationContext() is from Context class. That means any thing extended Context have this method. This also means you will be able to use this from service or from other resources.
But, if you custom class do not extend Activity/context, you have to pass Context as parameter to use getApplicationContext()
if you declare your activity like this
myMethod(Activity activity) //this is bad
Bud if it is like following,
myMethod(Context context) //this is ok
but from above declaration do not pass Activity or Service Context as they have own life cycle. instead you will use getApplicationContext()
You need pass the Activity context to the Custom class.
private Context context;
public CustomClass(Context context)
{
this.context=context;
}
if you use numberpicker and pass String from sring xml then use this
np_Basic_Hight.setMinValue(0);
np_Basic_Hight.setMaxValue(71);
np_Basic_Hight.setDisplayedValues(getContext().getResources().getStringArray(R.array.hieght));
After read this topic avoiding memory leaks some doubts arouse.
If I need to use an activity context (example: inflate a view in a PopupWindow class to show a popup) how can I hold the context of actual activity to do it? If I need to avoid a static context reference the only way to do it is creating an attribute in my class? And all the other classes I'll need the actual activity context I need to do it?
update-
I want to use this actual activity context in many classes that don't inherited Context, like I use with the application Context in my Application class that has a static method called getApplicationContext() declared. This method follows the Singleton Design Pattern and works fine.
Working from the code you linked in the comments, why not do this:
//my main activity
public class ExampleStaticReferenceActivity extends Activity {
//...
public void methodCalledWhenUserPressesButton(){
LinearLayout masterLayout = (LinearLayout) findViewById(R.id.masterLayout);
//now passing a reference to the current activity - elevine
masterLayout.addView(ButtonCreator.createButton(this));
}
}
//this class is in another package
public class ButtonCreator {
//added a Context parameter - elevine
public static Button createButton(Context context) {
Button button;
button = new Button(context);
//... some configurations for button
return button;
}
}
That will crash your Application since Your Activity will be killed by OS when it runs out of Resources thus Context will also be null.. And its meaningless to give A background Activities Instance when you want to show pop up in the Foreground Activity.. What the Blog says is avoid passing activity.this where even getApplicationContext() can do the job..
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
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.