Android - get location from any class - java

I have following code. This is a class where I work with Map fragment, but I need to use these methods in other classes.
public class FragmentMap extends Fragment {
private LocationManager locationManager;
private Location myLocation;
private Location getBestLocation() {
Location gpslocation = getLocationByProvider(LocationManager.GPS_PROVIDER);
Location networkLocation =
getLocationByProvider(LocationManager.NETWORK_PROVIDER);
if (gpslocation == null) {
return networkLocation;
}
if (networkLocation == null) {
return gpslocation;
}
long old = System.currentTimeMillis() - 1000;
boolean gpsIsOld = (gpslocation.getTime() < old);
boolean networkIsOld = (networkLocation.getTime() < old);
if (!gpsIsOld) {
return gpslocation;
}
if (!networkIsOld) {
return networkLocation;
}
if (gpslocation.getTime() > networkLocation.getTime()) {
return gpslocation;
} else {
return networkLocation;
}
}
private Location getLocationByProvider(String provider) {
Location location = null;
locationManager = (LocationManager) getActivity().getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
try {
if ( locationManager.isProviderEnabled(provider) ) {
location = locationManager.getLastKnownLocation(provider);
}
} catch (IllegalArgumentException e) {
Log.d("FragmentMap", "Cannot access Provider " + provider);
}
return location;
}
public String getCity(){
String result = "";
Geocoder gcd = new Geocoder(getActivity(), Locale.getDefault());
try {
List<Address> addresses = gcd.getFromLocation(myLocation.getLatitude(), myLocation.getLongitude(), 1);
if (addresses.size() > 0){
result = addresses.get(0).getLocality();
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
And I need to use it in 3 classes. How can I write it once and use it everywhere, so I don't have to duplicate it in each class. As I understand I should use public static. But java doesn't allow me.
I want to see what is the best practice for implementing such kind of thing.
Thank you.

First, you do not seem to define a class. Even if you only need static methods, you have to create a class :
public class MyClass {
[...]
}
Now, you are using a non-static attribute here :
private Location myLocation;
So you cannot use it in a static method.
Either you define this attribute and the method that uses it as static,
Or you declare both attribute and method as non-static.
Ask yourself if it makes sense to have this attribute as non-static (does it depend of a class instance or should it be shared by all instances?)
If you chose the non-static option, it becomes :
public class MyClass {
//Useless because you are only using a static field of this class.
//private LocationManager locationManager;
//Static attributes must be named with UPPER CASE letters
private static Location MY_LOCATION;
private static Location getBestLocation() {
private static Location getLocationByProvider(String provider) {
...
}
public static String getCity(){
...
}
}

There are several ways:
a) You could use a class to access public static methods. Not sure why you are facing an issue with it
b) You can declare an application class in your manifest and add these methods in the application class. The application class can be accessed from all activities and fragments. More details about application class can be found at http://developer.android.com/reference/android/app/Application.html
c) You can declare a base class which extends Activity class and add your methods here. Later you can create all your new activities by extending this base class and thereby can access these location retrieving methods. This way even the fragments would be able to access these methods.

You're probably missing a base class...
example:
class myLocationClass {
public static Location getBestLocation() {..}
public static Location getLocationProvider() {...}
public static String getCity {...}
}
and then use is via the class directly:
myLocationClass.getBestLocation() or myLocationClass.getLocationProvider() or myLocationClass.getCity

There are several ways of approaching this. The Application class is a singleton, so you could have a public method there and access it from wherever you can get a Context. A better approach would be to use a Bus like Otto and subscribe to it where you want location updates delivered.

Related

Java Array of InnerClass throwing java.lang.NoSuchFieldError

I am trying to brushup java after a long time.
Any help is much appreciated.
For demonstration I have Animal Class that has an array of innerclass of Organs.
public class Animal
{
String nameOfAnimal;
Organs [] vitalOrgans = new Organs[3];
public Animal()
{
}
public String getNameOfAnimal() {
return nameOfAnimal;
}
public void setNameOfAnimal(String nameOfAnimal) {
this.nameOfAnimal = nameOfAnimal;
}
#Override
public String toString() {
return "Animal{" + "nameOfAnimal=" + nameOfAnimal + "}";
}
class Organs{
String nameOfOrgan;
public String getNameOfOrgan() {
return nameOfOrgan;
}
public void setNameOfOrgan(String nameOfOrgan) {
this.nameOfOrgan = nameOfOrgan;
}
#Override
public String toString() {
return "Organs{" + "nameOfOrgan=" + nameOfOrgan + '}';
}
}
}
Now in driver file when I make call there is no syntactical error but I get "Exception in thread "main" java.lang.NoSuchFieldError: vitalOrgans"
Animal mamal = new Animal();
mamal.setNameOfAnimal("Chimp");
mamal.vitalOrgans[0].setNameOfOrgan("Heart");
System.out.println(mamal.vitalOrgans[0].getNameOfOrgan());
What would be the way to make this (or similar idea) to work.
Thanks.
You would need to initialize the vitalOrgrans with new Organs(). Like:
public Animal() {
for (int i = 0; i < vitalOrgans.length; i++) {
vitalOrgans[i] = new Organs();
}
}
Because when you say :
Organs[] vitalOrgans = new Organs[3];
You are creating an array of 3 null Organs. Hence the null pointer exception, when accessing "vitalOrgans[i].".
Taking the relevant bit of code:
public class Animal
{
//...
Organs [] vitalOrgans = new Organs[3];
//...
}
Since your declaration of vitalOrgans was never given an access modifier (i.e. one of private, public, protected) it took on default access, which means only other classes in the same package can see it. Since your other block of code is not in the same package, it cannot see the field.
A minimally viable modification to just make it work would be to set the access to public:
public class Animal
{
//...
public Organs [] vitalOrgans = new Organs[3];
//...
}
While this works, it's not necessarily the best solution, as if you ever change how vitalOrgans is represented, or need to perform any validation, those edits would have to be done throughout the application. Thus, a better solution (and also, a major stylistic convention in Java for those exact reasons) is to make it (and all your fields, in fact) private and access via methods:
public class Animal {
private String nameOfAnimal;
private Organs[] vitalOrgans = new Organs[3];
//...
public Organs[] getVitalOrgans() {
return vitalOrgans;
}
//Alternative accessor that fetches only one organ.
public Organs getVitalOrgan(int index) {
if(index >= 0 && index < vitalOrgans.length)
return vitalOrgans[index];
else
return null;
}
public void setVitalOrgans(Organs[] vitalOrgans) {
this.vitalOrgans = vitalOrgans
}
//...
}
Your caller could then access Organs via either form of the get method (note, you probably want Organs to be public):
Animal.Organs futureMammalHeart = mamal.getVitalOrgan(0); //Animal.Organs due to Organs being an inner class.
if(futureMammalHeart != null) //Demonstration of null check. Safety first!
futureMammalHeart.setNameOfOrgan("Heart");
Animal.Organs[] mammalianVitalOrgans = mamal.getVitalOrgans();
if(mammalianVitalOrgans != null) //Just in case...
System.out.println(mamal.mammalianVitalOrgans[0].getNameOfOrgan());
Also, as Ari mentioned in his answer, don't forget to initialize the organs in your array, otherwise you will get a NullPointerException!

How do I check if an instance of a class has access to a method in another class?

I'm working on a small project where I want to have a list of a class called "DevelopmentEmployee", but only one of them is allowed to manipulate certain methods in another class "Project". The way I have implemented it, the class Project has a field called projectLeader, which is of the type DevelopmentEmployee. When a DevelopmentEmployee attempts to access methods in the class Project, I want to check if the DevelopmentEmployee is equal to the specific instance of Project's projectLeader.
Something like
public class Project {
private DevelopmentEmployee projectLeader;
private List < Activity > activities = new ArrayList < Activity > ();
public Project(DevelopmentEmployee pL) {
this.projectLeader = pL;
}
public void addActivity(String activityName) {
if (projectLeader.equals(DevelopmentEmployee * ) {
activities.add(activity);
}
}
}
But I can't figure out a way to make the access requirement work. How can the instance of the class Project know who is trying to access it?
You should also pass the DevelopementEmployee in addActivity for checking it against the projectLeader.
public void addActivity(String activityName,DevelopmentEmployee employee) {
if (projectLeader.equals(employee) {
activities.add(activity);
}
}
Then you need to override equals method in DevelopmentEmployee class, for proper checking of equality, like the one as shown below :
public boolean equals(DevelopementEmployee e){
if(e!=null && this.employeeId==e.employeeId)
return true;
else
return false;
}
Several possibilities come to mind:
Provide the instance of the one accassing the project method to the method:
public void addActivity(String activityName, DevelpmentEmployee user) {
if (projectLeader.equals(user)) {`
Create some class that holds information about active user and use that inside the methods:
public class Project {
private UserRegistry userRegistry;
private List<Activity> activities = new ArrayList<Activity>();
public Project(UserRegistry userRegistry) {
this.userRegistry = userRegistry;
}
public void addActivity(String activityName) {
if (userRegistry.isActiveUserProjectLeader()) {
activities.add(activity);
}
}
}
public class UserRegistry {
private DevelpmentEmployee projectLeader;
private DevelpmentEmployee activeUser;
private List<DevelpmentEmployee> user;
public void addUser(DevelpmentEmployee user) { ... }
public void makeProjectLeader(DevelpmentEmployee newLeader) { ... }
public void makeActiveUser(DevelpmentEmployee newActiveUser) { ... }
public boolean isActiveUserProjectLeader() { ... }
}`

Singleton returning two instances

I'm trying to use a singleton (PhotoStorage) to provide an arrayList of Photo objects, but it seems that the PhotoStorage instance is not behaving as a singleton (two instances).
I am using dagger to inject this singleton into a class named PhotoInteractor. The objectGraph seems A-OK up to this point.
The same PhotoInteractor instance is used in three fragments in a viewpager. These fragments are all instantiated at runtime:
RecentFragment:
HistoryFragment:
Notice how the instance #4067 of the PhotoInteractor is the same for both fragments.
Also:
mAppContext#4093: same
photoStorage#4094: same
When I click a photo object (grid image) from RecentFragment, the PhotoStorage.addPhoto(url) method is called. This correctly adds the photo object to the photoStorage instance array (4094). That much is OK.
Problem:
When I close the applicaton, it is intended that the PhotoStorage.savePhotosToFile method serialzes this arrayList object into JSON on the filesystem.
The following method is called from the same PhotoInteractor instance:
#Override
public void savePhotos(){
photoStorage.get(mAppContext).savePhotosToFile();
}
When I debug the application, the PhotoStorage.get method already has a singleton instance, but what appears to be a 2nd instance!
//Singleton enforcement
public static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
This means that the ArrayList of photos will always be empty since it is a new instance of PhotoStorage. Iā€™m not sure where it is instantiating itself from.
Edit - Added PhotoStorage.class:
public class PhotoStorage{
private ArrayList<Photo> mPhotos;
private PhotoJSONer mSerializer;
private static PhotoStorage sPhotoStorage;
private static Context mAppContext;
private static final String PHOTOS_DATABASE = "photos.json";
public static final String TAG = PhotoStorage.class.getSimpleName();
public PhotoStorage(Context appContext){
mSerializer = new PhotoJSONer(appContext, PHOTOS_DATABASE);
try{
mPhotos = mSerializer.loadPhotos();
}catch(Exception e){
mPhotos = new ArrayList<Photo>();
}
}
//Singleton enforcement
public static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
public ArrayList<Photo> getPhotos(){
return mPhotos;
}
public Photo getPhoto(String url){
for(Photo p: mPhotos){
if(p.getUrl() == url)
return p;
}
return null;
}
public void deletePhoto(String url){
Log.i(TAG, "deleted photo");
mPhotos.remove(url);
}
public void addPhoto(Photo photo){
Log.i(TAG, "added photo");
mPhotos.add(photo);
}
public boolean savePhotosToFile(){
try{
mSerializer.savePhotos(mPhotos);
return true;
}catch (Exception e){
return false;
}
}
}
You are not executing Singletton pattern in the correct way,
The Singleton design pattern addresses all of these concerns. With the Singleton design pattern you can:
Ensure that only one instance of a class is created
Provide a global point of access to the object
In your case, we don't see PhotoStorage class but this call comes from an instance, what is not allowed by Singletton pattern:
photoStorage.get(mAppContext).savePhotosToFile();
//ā†‘ instance call WRONG!!
This line works, but as your get method is static is not a good practice as Karakuri pointed and also breaks the Singletton pattern definition.
public static PhotoStorage get(Context c){
SOLUTION
To make photoStorage.get() invalid and create a correct Singletton pattern you must:
declare the getInstance() method static in the class (here PhotoStorage)
hide default constructor to avoid instances of the class
create private constructors if necessary
call getInstance() it in a static way:
class PhotoStorage {
// hidding default constructor
private PhotoStorage () {};
// creating your own constructor but private!!!
private PhotoStorage(Context appContext){
mSerializer = new PhotoJSONer(appContext, PHOTOS_DATABASE);
try{
mPhotos = mSerializer.loadPhotos();
}catch(Exception e){
mPhotos = new ArrayList<Photo>();
}
}
//Singleton enforcement
public synchronized static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
}
Then you can make static call from everywhere the class scope allows:
#Override
public void savePhotos(){
PhotoStorage.get(mAppContext).savePhotosToFile();
//ā†‘ static call CORRECT!!
}
UPDATE: if your app have several threads and singleton getInstance requests may overlapp, there is a double check syncronized singletton pattern you can apply:
//Singleton enforcement
public synchronized static PhotoStorage get(Context c){
if(sPhotoStorage == null){
synchronized(PhotoStorage.class) {
if(sPhotoStorage == null) {
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
}
}
}

android: passing variable through classes?

I'm wondering how to pass data/variables through classes?
Class.java
public class AddItem extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mlocListener = new CurrentLocation();
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
}
}
public void sendDataDetail(View v){
// This is where my HTTPPOST goes, need the location here
}
public class CurrentLocation implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
// TODO Auto-generated method stub
loc.getLatitude();
loc.getLongitude();
String Text = "My Current Location is: " + "Lat = " + loc.getLatitude() + "Long = " + loc.getLongitude();
Toast.makeText(getApplicationContext(),Text,Toast.LENGTH_SHORT).show();
}
}
SO basically, I have CurrentLocation() in onCreate, and then I have an HTTPPOST script in sendDataDetail. And then I have a class that gets the location.
How do I get that location and send it to sendDataDetail? What methods should I take?
Please note that I'm still learning android,
Thank you in advance!
In Android, sharedpreferences are used to pass information between classes.
This is the simplest example I know to explain how it works. http://android-er.blogspot.com/2011/01/example-of-using-sharedpreferencesedito.html
One way is to Extend the Application class and get the instance with the data, populate it in one class and use it in another. See this question on StackOverflow.
Basically what you do is that you extend the Application object and add your fields (location in your case) and set it at one place and get it at another. Here is the example code from the link I have mentioned:
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();
...
}
}
There are other ways, but this solution is pretty good!
In some use cases, you can put a static variable somewhere for both classes to reference. That would be easiest, and it would give pedants the shivers, which is always a good thing. Well, except when they're right, of course.

Android global variables, getter, setter, error,

I try this to add some data to "global variables". Class "Conection" without window in void
for (int in = 7; in < arAll.length; in++) {
if (arAll[in].toString().endsWith("/")) {
((MyApplication) this.getApplication()).setPath(arAll[in]
.toString());
} else {
((MyApplication) this.getApplication()).setFile(arAll[in]
.toString());
}
MyApplication getter's and setter's:
private ArrayList<String> file = new ArrayList<String>();
private ArrayList<String> path = new ArrayList<String>();
private ArrayList<String> all = new ArrayList<String>();
public void removeAll() {
this.file.clear();
this.path.clear();
this.all.clear();
}
public int len() {
return this.all.size();
}
public String getStrbyId (int i) {
return this.all.get(i).toString();
}
public ArrayList<String> getFile() {
return this.file;
}
public void setFile(String file) {
this.file.add(file);
setAll(file);
Log.v("",file);
}
public ArrayList<String> getPath() {
return this.path;
}
public void setPath(String path) {
this.path.add(path);
setAll(path);
Log.v("",path);
}
public ArrayList<String> getAll() {
Log.v("",String.valueOf(len()));
return this.all;
}
private void setAll(String all) {
this.all.add(all);
}
In manifest <application android:name="MyApplication"
When I try to execute first void, I have an error.
The fact that you are using global variables via the Application context very likely that there is something improperly designed in your app. You should not need to use global variables like this at all, and it may be a potential source of your error (passing around the context and getting access to these global variables is sometimes necessary, but perhaps not in this situation). Instead what you should do is pass the necessary variables between components and use them within each component. (Activity, Service, ContentProvider.) So perhaps instead of trying to get this hacky thing working, you could rethink why you need global variables.

Categories

Resources