205

I'm having trouble offloading tasks from the main Activities OnCreate method onto another class to do the heavy lifting.

When I try to call getSystemService from the non-Activity class an exception is thrown.

Any help would be greatly appreciated :)

lmt.java:

package com.atClass.lmt;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.location.Location;

public class lmt extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        fyl lfyl = new fyl();
        Location location = lfyl.getLocation();
        String latLongString = lfyl.updateWithNewLocation(location);

        TextView myLocationText = (TextView)findViewById(R.id.myLocationText);
        myLocationText.setText("Your current position is:\n" + latLongString);
    }
}

fyl.java

package com.atClass.lmt;

import android.app.Activity;
import android.os.Bundle;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
import android.content.Context;

public class fyl {
    public Location getLocation(){
        LocationManager locationManager;
        String context = Context.LOCATION_SERVICE;
        locationManager = (LocationManager)getSystemService(context);

        String provider = LocationManager.GPS_PROVIDER;
        Location location = locationManager.getLastKnownLocation(provider);

        return location;
    }

    public String updateWithNewLocation(Location location) {
        String latLongString;

        if (location != null){
            double lat = location.getLatitude();
            double lng = location.getLongitude();
            latLongString = "Lat:" + lat + "\nLong:" + lng;
        }else{
            latLongString = "No Location";
        }

        return latLongString;
    }
}
Bert F
  • 82,001
  • 11
  • 103
  • 123
Kevin Parker
  • 16,541
  • 19
  • 75
  • 103
  • 2
    Adding the exception and stack trace to the question may help potential answerers – Bert F Feb 02 '11 at 04:07
  • Hi, Sorry for the mistake. The exception is thrown if I try to extend the Activity class with this one. I do not want to extend the Activity class for this class and simply want to be able to call getSystemService from within my getLocation method. Exception: java.lang.IllegalStateException: System services not available to Activities before onCreate() – Kevin Parker Feb 02 '11 at 04:14

7 Answers7

307

You need to pass your context to your fyl class..
One solution is make a constructor like this for your fyl class:

public class fyl {
 Context mContext;
 public fyl(Context mContext) {
       this.mContext = mContext;
 }

 public Location getLocation() {
       --
       locationManager = (LocationManager)mContext.getSystemService(context);

       --
 }
}

So in your activity class create the object of fyl in onCreate function like this:

package com.atClass.lmt;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.location.Location;

public class lmt extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        fyl lfyl = new fyl(this); //Here the context is passing 

        Location location = lfyl.getLocation();
        String latLongString = lfyl.updateWithNewLocation(location);

        TextView myLocationText = (TextView)findViewById(R.id.myLocationText);
        myLocationText.setText("Your current position is:\n" + latLongString);
    }
}
Krzysiek
  • 6,660
  • 5
  • 33
  • 37
Labeeb Panampullan
  • 33,641
  • 28
  • 92
  • 112
  • Sorry I don't get it, code would be more helpful. If anything I should be passing a LocationManager object to the getLocation method... I don't really see how me passing the context to the method will help when I cannot even call getSystemService without writing this class as an extended class to Activity. – Kevin Parker Feb 02 '11 at 04:23
  • did you tried this. In the onCreate if you are passing access the context by 'this' – Labeeb Panampullan Feb 02 '11 at 04:27
  • but if the `lmt` class wont get executed then `fly` wont be having context – Hunt May 14 '13 at 16:01
  • BTW `getSysytemService()`only accepts `String` as a parameter. Therefore you **cannot** pass a context to it. _How do I get around this?_ @Hunt – Parth Sane Sep 01 '14 at 19:43
  • You don't need to pass context into that class. [See my answer](http://stackoverflow.com/a/39065445/1074799) – S.M.Mousavi Aug 21 '16 at 14:47
  • 2
    Just to mention, Android managers (`BluetoothManager`, `ActivityManager` etc.) are also [constructed](https://android.googlesource.com/platform/frameworks/base/+/742a67127366c376fdf188ff99ba30b27d3bf90c/core/java/android/app/ActivityManager.java#62) that way (not necessarily passing an `Activity` context to their constructor) and this is why they can access components in application scope. – Eido95 Nov 09 '16 at 12:51
  • Instead pass context to `getLocation` and make it static. `public static Location getLocation(Context context) { locationManager = (LocationManager)context.getSystemService(context); }` – Prabs Feb 13 '17 at 12:33
  • this is now outdated – SlowLearnah May 06 '22 at 21:38
52

You can go for this :

getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
Maddy
  • 4,652
  • 2
  • 31
  • 39
  • 8
    getActivity() method is undefined for the class. This error shows up. – Darpan Aug 04 '14 at 14:44
  • What is the class type in which you are using it? i.e. it is a receiver class, fragment, simple java class or any other. – Maddy Aug 04 '14 at 17:58
  • You need to extend your Activity with FreagmentActivity instead of an Activity. I hope it'll work for you...? – Maddy Jun 08 '15 at 07:57
  • It doesn't work for a simple class where I want to extend `ArrayAdapter`. – David Silva-Barrera Sep 04 '16 at 23:26
  • Dear, what do you mean by a class.? Do you mean a fragment..? What is the problem you facing. – Maddy Sep 05 '16 at 04:53
  • @MrAsterisco: 2017 This method works for me in fragment – esQmo_ Mar 27 '17 at 04:11
  • Dear @MrAsterisco , It will work in any of the non-activity class, in fragment as well as in simple java classes too. In simple java classes, you just need to pass the Context reference(this) from the activity from which you are calling java class. Feel free to ask if some clarification? – Maddy Apr 08 '17 at 20:22
  • 4
    MIne worked by using getContext() instead of getActivity()! – Amir Aug 27 '17 at 06:23
17

One way I have gotten around this is by create a static class for instances. I used it a lot in AS3 I has worked great for me in android development too.

Config.java

public final class Config {
    public static MyApp context = null;
}

MyApp.java

public class MyApp extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Config.context = this;
    }
    ...
}

You can then access the context or by using Config.context

LocationManager locationManager;
String context = Context.LOCATION_SERVICE;
locationManager = Config.context.getSystemService(context);
brenjt
  • 15,581
  • 13
  • 78
  • 116
  • 4
    The problem I see with this method is it leaves something unprotected that, if someone were to assign null to it, would probably produce a catastrophic failure? – Rob Dec 25 '13 at 19:38
  • 2
    A variation on this is to put a private static in MyApp, and then add getters. `private static MyApp _context;` `public static MyApp getContext() { return _context; }` ... in onCreate: `_context = this;` in onStop: `_context = null;` ... Usage: `MyApp.getContext()`. – ToolmakerSteve Sep 20 '15 at 16:22
  • 2
    It maybe lead to memory leak – Yat3s Dec 29 '16 at 13:17
  • 3
    This will absolutely lead to memory leak. Ideally you should not use this process . – beginner Jul 18 '17 at 06:12
1

Use this in Activity:

private Context context = this;

........
if(Utils.isInternetAvailable(context){
Utils.showToast(context, "toast");
}
..........

in Utils:

public class Utils {

    public static boolean isInternetAvailable(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected();
    }

}
dimvolk
  • 188
  • 2
  • 8
0

I don't know if this will help, but I did this:

LocationManager locationManager  = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);
Melquiades
  • 8,466
  • 1
  • 29
  • 43
Ruchir Baronia
  • 7,125
  • 5
  • 46
  • 78
0

For some non-activity classes, like Worker, you're already given a Context object in the public constructor.

Worker(Context context, WorkerParameters workerParams)

You can just use that, e.g., save it to a private Context variable in the class (say, mContext), and then, for example

mContext.getSystenService(Context.ACTIVITY_SERVICE)
auspicious99
  • 3,350
  • 1
  • 35
  • 51
0

If you want to get it in a fragment this would work in kotlin:

requireActivity().getSystemService(LOCATION_SERVICE) as LocationManager
Ivan Lopes
  • 118
  • 2
  • 11