I'm trying to acquire GPS coordinates on my android application.
Criteria criteria = new Criteria();
criteria.setAltitudeRequired(false);
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setBearingRequired(false);
criteria.setCostAllowed(false);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Intent i = new Intent(context, IntentListener.class);
i.setAction(Actions.ACTION_UPDATE_LOCATION);
PendingIntent pi = PendingIntent.getBroadcast(
context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
String provider = locationManager.getBestProvider(criteria, true);
if (provider == null) return;
locationManager.requestLocationUpdates(provider, 90 * 1000, 30, pi);
and here's receiving code.
Intent service = new Intent(context, WorkerService.class);
service.setAction(Actions.ACTION_UPDATE_LOCATION);
Location location = (Location) intent.getExtras().get(
LocationManager.KEY_LOCATION_CHANGED);
if (location == null) { // <-- Always true
return;
}
service.putExtra("lat", location.getLatitude());
service.putExtra("lon", location.getLongitude());
context.startService(service);
As you can see, I'm unable to obtain Location instance by calling intent.getExtras()... etc. Returned value is always null. I'm testing on my emulator running android 4.1.2 and telnet client, using geo fix longitude latitude. Anyone knows what's wrong? Thanks.
P.S. Manifest contains all required permissions and GPS is enabled in the emulator.
P.P.S. This application is a corporate app, that runs as a service, without UI and should collect GPS coordinates.
You casually mentioned that you're testing on an emulator. The emulator doesn't receive mock locations by itself; you have to specifically send them through the DDMS interface.
Additionally, due to a bug in the emulator, the time offset in incoming locations is set to midnight, so your location criteria will likely not match it.
I strongly suggest you test with a physical device to confirm that the problem is still occurring.
Use the new Location API.
You'd have to include Google Play services into your project.
Add this in onCreate:
mIntentService = new Intent(this,LocationService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resp == ConnectionResult.SUCCESS){
locationclient = new LocationClient(this,this,this);
locationclient.connect();
}
And you'd have to override these methods:
#Override
protected void onDestroy() {
super.onDestroy();
if(locationclient!=null)
locationclient.disconnect();
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "onConnected");
//to get last location
Location loc =locationclient.getLastLocation();
//to get updates via service
locationrequest = LocationRequest.create();
locationrequest.setInterval(100);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
}
#Override
public void onDisconnected() {
Log.i(TAG, "onDisconnected");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "onConnectionFailed");
}
#Override
public void onLocationChanged(Location location) {
if(location!=null){
Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());
}
}
Here's the service where I'm creating a notification for every new location, you can remove that and update location there.
public class LocationService extends IntentService {
private String TAG = this.getClass().getSimpleName();
public LocationService() {
super("Fused Location");
}
public LocationService(String name) {
super("Fused Location");
}
#Override
protected void onHandleIntent(Intent intent) {
Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
if(location !=null){
Log.i(TAG, "onHandleIntent " + location.getLatitude() + "," + location.getLongitude());
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Builder noti = new NotificationCompat.Builder(this);
noti.setContentTitle("Fused Location");
noti.setContentText(location.getLatitude() + "," + location.getLongitude());
noti.setSmallIcon(R.drawable.ic_launcher);
notificationManager.notify(1234, noti.build());
}
}
}
Follow the tutorial to get the location in Android app
You should take your location by implementing LocationListener
#Override
public void onLocationChanged(Location loc) {
}
Take a look at this implementation, works really nice and i have tested it on several devices.
package ro.gebs.captoom.activities;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.bugsense.trace.BugSenseHandler;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import ro.gebs.captoom.R;
import ro.gebs.captoom.database.ReceiptDataSource;
import ro.gebs.captoom.utils.Constants;
import ro.gebs.captoom.utils.Utils;
public class LocationActivity extends FragmentActivity {
private GoogleMap map;
private long rec_id;
private String address;
private Marker selectedLoc;
private boolean isSessionClosed;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
BugSenseHandler.initAndStartSession(this, Constants.BugSenseKEY);
setContentView(R.layout.preview_location);
RelativeLayout cancel_btn = (RelativeLayout) findViewById(R.id.cancel_btn);
LinearLayout save_location_btn = (LinearLayout) findViewById(R.id.delete_btn);
save_location_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (address != null) {
ReceiptDataSource r = new ReceiptDataSource();
r.updateReceiptLocation(rec_id, address);
Intent returnIntent = new Intent(getBaseContext(), EditReceiptActivity.class);
returnIntent.putExtra("result", address);
setResult(RESULT_OK, returnIntent);
finish();
} else {
Utils.showToast(getApplicationContext(), getString(R.string.c_unknownLocation), Toast.LENGTH_SHORT);
}
}
});
cancel_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
if (map == null) {
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
if (isGoogleMapsInstalled()) {
if (map != null) {
retrieveLocation();
}
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Install Google Maps");
builder.setCancelable(false);
builder.setPositiveButton("Install", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.apps.maps"));
startActivity(intent);
finish();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
}
#Override
protected void onResume() {
super.onResume();
if (isSessionClosed) {
BugSenseHandler.startSession(this);
isSessionClosed = false;
}
}
#Override
protected void onPause() {
super.onPause();
BugSenseHandler.closeSession(this);
isSessionClosed = true;
}
#Override
public void onBackPressed() {
map.clear();
super.onBackPressed();
}
private void retrieveLocation() {
Intent intent = getIntent();
address = intent.getStringExtra("location");
assert address != null;
if (address.equalsIgnoreCase("")) {
address = Utils.getCurrentLocation(LocationActivity.this);
}
rec_id = intent.getLongExtra("receipt_to_update_location", 0);
final Geocoder geocoder = new Geocoder(this, Locale.US);
double latitude = 0, longitude = 0;
try {
List<Address> loc = geocoder.getFromLocationName(address, 5);
if (loc.size() > 0) {
latitude = loc.get(0).getLatitude();
longitude = loc.get(0).getLongitude();
} else {
Utils.showToast(LocationActivity.this, getString(R.string.UnableToFindLocation), Toast.LENGTH_SHORT);
}
selectedLoc = map.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title(address).draggable(true));
map.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() {
#Override
public void onMarkerDragStart(Marker marker) {
}
#Override
public void onMarkerDrag(Marker marker) {
}
#Override
public void onMarkerDragEnd(Marker marker) {
try {
List<Address> addresses = geocoder.getFromLocation(selectedLoc.getPosition().latitude, selectedLoc.getPosition().longitude, 1);
StringBuilder sb = new StringBuilder();
if (addresses.size() > 0) {
Address address = addresses.get(0);
if (address.getAddressLine(0) != null)
sb.append(address.getAddressLine(0)).append(", ");
if (address.getLocality() != null)
sb.append(address.getLocality()).append(", ");
if (address.getCountryName() != null)
sb.append(address.getCountryName());
}
address = sb.toString();
} catch (IOException e) {
}
}
});
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 12));
// Zoom in, animating the camera.
map.animateCamera(CameraUpdateFactory.zoomTo(12), 2000, null);
} catch (IOException e) {
Log.e("IOException", e.getMessage());
Utils.showToast(LocationActivity.this, getString(R.string.c_unknownLocation), Toast.LENGTH_LONG);
}
}
public boolean isGoogleMapsInstalled() {
try {
getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
}
I see you implement the intent.putExtra after you get the extra! You should do the put in the activity that receives the location data and when you want to receive the data from the intent.extra you should do this:
Bundle extras = getIntent().getExtras();
if (extras != null) {
latitude= (double)extras.getDouble("lat");
longitude=(double)extras.getDouble("lon");
}
Related
I'm new to android app dev and Java isn't my strongest programming language.
I able to make my user to allow their location to be access or deny to get their location longitude and latitude number. Though, I still can't figure our how to implement the precision changes of the location to either increase or decrease their coordinate number. I read all the documentation for android in this topic and still don't understand it.
Here's the code:
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.google.android.material.snackbar.Snackbar;
public class Locator extends AppCompatActivity {
Button back;
private final String enable = "Enable yout location for the GPS to work";
private final String loading = "GPS is starting";
private final String latAndLong = "Latitude: %s\n Longitude: %s\n";
private LocationManager lm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.location);
back = findViewById(R.id.backbutton);
back.setOnClickListener(view -> {
Intent intent = new Intent(Locator.this, MainActivity.class);
startActivity(intent);
});
}
public void getLocation(View v) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, getResources().getInteger(R.integer.requestCode));
lm = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean isProviderEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isProviderEnabled) {
Snackbar.make(v, enable, Snackbar.LENGTH_LONG).setAction("Action",
null).show();
} else {
userLoca();
}
}
private void userLoca() {
TextView tvLocation = findViewById(R.id.textView_locator);
if (ActivityCompat.checkSelfPermission(Locator.this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
tvLocation.setText(getResources().getString(R.string.location_denied));
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, getResources().getInteger(R.integer.requestCode));
} else if (ActivityCompat.checkSelfPermission(Locator.this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
tvLocation.setText(getResources().getString(R.string.location_denied));
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, getResources().getInteger(R.integer.requestCode));
} else {
tvLocation = findViewById(R.id.textView_locator);
Location current_GPS = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location networkLocation = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Location passiveLocation = lm.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
if (current_GPS != null) {
tvLocation.setText(String.format(latAndLong, current_GPS.getLatitude(),
current_GPS.getLongitude()));
}
if (networkLocation != null) {
tvLocation.setText(String.format(latAndLong, networkLocation.getLatitude(),
networkLocation.getLongitude()));
}
if (passiveLocation != null) {
tvLocation.setText(String.format(latAndLong, passiveLocation.getLatitude(),
passiveLocation.getLongitude()));
} else {
Snackbar.make(tvLocation, loading, Snackbar.LENGTH_LONG).setAction("Action",
null).show();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
getResources().getInteger(R.integer.location_min_time),
getResources().getInteger(R.integer.location_min_dist), v -> {
});
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
getResources().getInteger(R.integer.location_min_time),
getResources().getInteger(R.integer.location_min_dist), v -> {
});
}
}
}
}
You need to implement location updates listener to this. Use the following code:
private LocationCallback locationCallback;
Call this in onCreate() or onResume() depending upon your logic
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
// ...
}
}
};
private void startLocationUpdates() {
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback,
Looper.getMainLooper());
}
I am trying to get location after every 10 second using FusedLocationProviderClient, However when i minimize the app or terminate it the location updates stops. Below is my code. Right now i am using android 9.0. I have no idea why this is happening any help will be grateful
Android Menifest
<service android:enabled="true" android:name=".LocationService">
</service>
LocationService.java
package com.example.locationupdate;
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.example.locationupdate.db.Realm$Helper;
import com.example.locationupdate.shared_pref.SaveInSharedPreference;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.List;
import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
//private LocationRequest mLocationRequest;
private long UPDATE_INTERVAL = 10 * 1000; /* 10 secs */
private long FASTEST_INTERVAL = 2000;
int count = 0;
List<FilterData> datafromDB;
FusedLocationProviderClient mFusedLocationClient;
LocationRequest mLocationRequest;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
LocationCallback mLocationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
//Log.e("MainActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 && SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
}
SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());
count = count + 1;
Log.e("mLocationCallbackLat", String.valueOf(location.getLatitude()));
Log.e("mLocationCallbackLong", String.valueOf(location.getLongitude()));
//LocationMatch(location);
}
/* datafromDB = Realm$Helper.getLocation$Module(LocationService.this).getAllData();
for (FilterData str : datafromDB) {
String name = str.getName();
}*/
};
};
public void onResume() {
Log.e("OnResume", "OnResumeEvent");
if (mFusedLocationClient != null) {
requestLocationUpdates();
}
}
public void requestLocationUpdates() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL); // two minute interval
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
}
public void onPause() {
//super.onPause();
Log.e("ONPause", "OnPauseEvent");
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}
protected void startLocationUpdates() {
// Create the location request to start receiving updates
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest);
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
// do work here
onLocationChanged(locationResult.getLastLocation());
}
},
Looper.myLooper());
}
public void onLocationChanged(Location location) {
if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 && SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
}
SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());
Toast.makeText(this,"onLocationChanged",Toast.LENGTH_LONG);
// New location has now been determined
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Log.e ("onLocationChangedLat", String.valueOf(location.getLatitude()));
Log.e ("onLocationChangedLong", String.valueOf(location.getLongitude()));
// You can now create a LatLng Object for use with maps
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
/*loc1.setLatitude(location.getLatitude());
loc1.setLongitude(location.getLongitude());
loc2.setLatitude(str.getLat());
loc2.setLongitude(str.getlng());
double distanceInMeters = loc1.distanceTo(loc2);
Log.e("Name", name);
Log.e("Distance", "" + distanceInMeters);*/
}
public void getLastLocation() {
// Get last known recent location using new Google Play Services SDK (v11+)
FusedLocationProviderClient locationClient = getFusedLocationProviderClient(this);
locationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// GPS location can be null if GPS is switched off
if (location != null) {
onLocationChanged(location);
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("MapDemoActivity", "Error trying to get last GPS location");
e.printStackTrace();
}
});
}
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
MainActitvity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//locationTv = findViewById(R.id.location);
Intent startIntent = new Intent(this, LocationService.class);
startService(startIntent);
You can achieve this by setting up a handler and adding the required permissions to the android app. Apperantly there is a limit to how many times you can request the location in the background according to Android Location In Background but i have not seen this. Im requesting a new location every second.
First add these to your manifest:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Then you can create a handler like this.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
createLocationHandler();
...
}
The createLocationHandler and isServiceRunning function:
public void createLocationHandler(){
HandlerThread locationHandler = new HandlerThread("LocationHandler"); //Creates a new handler thread
locationHandler.start(); //Starts the thread
Handler handler = new Handler(locationHandler.getLooper()); //Get the looper from the handler thread
handler.postDelayed(new Runnable() {//Run the runnable only after the given time
#Override
public void run() {
//Check if the location service is running, if its not. lets start it!
if(!isMyServiceRunning(LocationService.class)){
getApplicationContext().startService(new Intent(getApplicationContext(), LocationService.class));
}
//Requests a new location from the location service(Feel like it could be done in a less static way)
LocationService.requestNewLocation();
createLocationHandler();//Call the create location handler again, this will not be added to the stack because of the looper.
}
}, 10000);//Set the delay to be 10 seconds, 1 second = 1000 milliseconds
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) this.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Remember to ask for the background_location permission before you want to start the service.
I am a newbie to Codename One and I am trying to invoke Native Interface from StateMachine.java and get some values back from the Native Interface Implementation. How do I do it?
Here are the codes of StateMachine.java and the Native Interface Implementation, NativeAndroidImpl.java
I want to call NativeAndroidImpl.java from StateMachine.java and get the longitude and latitude values from NativeAndroidImpl.java
----------------------------StateMachine.java----------------------------
#Override
protected void onMain_MainHelpButtonAction(Component c, ActionEvent event) {
Vector<String> vec = (Vector<String>)Storage.getInstance().readObject("SavedData");
//Invoke NativeAndroidImpl.java
double lat=//get latitude from NativeAndroidImpl.java
double lng=//get longitude from NativeAndroidImpl.java
try {
Display.getInstance().sendSMS(vec.elementAt(2), "I am in trouble. Send HELP! My location: http://maps.google.com/?q=" + lat + "," + lng, true);
} catch (IOException ex) {
Dialog.show("Error!", "Failed to send SMS.", "OK", null);
ex.printStackTrace();
}
}
}
------------------------NativeAndroidImpl.java--------------------------
package com.anonymous.emergencyhelp;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class NativeAndroidImpl {
LocationManager locationManager;
double longitudeNetwork, latitudeNetwork;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
}
private boolean checkLocation() {
if(!isLocationEnabled())
showAlert();
return isLocationEnabled();
}
private void showAlert() {
final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Enable Location")
.setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to use this app")
.setPositiveButton("Location Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
}
});
dialog.show();
}
private boolean isLocationEnabled() {
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
public void toggleNetworkUpdates(View view) {
if(!checkLocation())
return;
Button button = (Button) view;
if(button.getText().equals("Help"))
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60 * 1000, 10, locationListenerNetwork);
}
private final LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
longitudeNetwork = location.getLongitude();
latitudeNetwork = location.getLatitude();
runOnUiThread(new Runnable() {
#Override
public void run() {
//Send longitude and latitude values to StateMachine.java
Toast.makeText(MainActivity.this, "Network Provider update", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
public boolean isSupported() {
return true;
}
}
Check out this tutorial for using native interfaces.
Notice that you don't need native interfaces for location since a cross platform location API exists in Codename One. I suggest checking out the developer guide and tutorials for Codename One.
Hi am running with an issue. I have a gps checking function on my splash screen where after checking my gps connectivity if its state is null it shows an alert.I want to destroy and restart my application after the button click of alert box. Kindly help. here is my code
Geolocationfinder class
package com.driverapp.inis.zuber;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
public class GeoLocationFinder {
private static final String TAG = "GeoLocationFinder";
Timer locationTimer;
LocationManager locationManager;
private static final int min_update_time = 3000; // in msec
private static final int min_distance_for_update = 10; // in meters
LocationResult locationResult;
boolean gps_enabled = Boolean.FALSE;
boolean network_enabled = Boolean.FALSE;
private AlertDialogManager alert;
Context ctx;
public boolean getLocation(Context ctx, LocationResult result) {
this.ctx = ctx;
locationResult = result;
if (locationManager == null) {
locationManager = (LocationManager) ctx
.getSystemService(Context.LOCATION_SERVICE);
}
try {
gps_enabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception e) {
/* alert = new AlertDialogManager();
alert.showAlertDialog(ctx, "Error", "GPS enabled exception:", false);*/
Log.d(TAG, "GPS enabled exception: " + e.getMessage());
}
try {
network_enabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception e) {
Log.d(TAG, "Network enabled exception: " + e.getMessage());
}
if (!gps_enabled && !network_enabled) {
alert = new AlertDialogManager();
alert.showAlertDialog(ctx, "Error", "Please Check Your GPS Connection and Try Again", false);
return Boolean.FALSE;
}
if (gps_enabled) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, min_update_time,
min_distance_for_update, locationListenerGps);
}
if (network_enabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, min_update_time,
min_distance_for_update, locationListenerNetwork);
}
locationTimer = new Timer();
locationTimer.schedule(new GetLastLocation(), 2000);
return Boolean.TRUE;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
locationTimer.cancel();
locationResult.gotLocation(location);
locationManager.removeUpdates(this);
locationManager.removeUpdates(locationListenerGps);
}
#Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "GPS provider disabled" + provider);
}
#Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "GPS provider enabled" + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "GPS status changed");
}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
locationTimer.cancel();
locationResult.gotLocation(location);
locationManager.removeUpdates(this);
locationManager.removeUpdates(locationListenerNetwork);
}
#Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "Network provider disabled. " + provider);
}
#Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "Network provider enabled. " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "Network status changed.");
}
};
private class GetLastLocation extends TimerTask {
#Override
public void run() {
locationManager.removeUpdates(locationListenerGps);
locationManager.removeUpdates(locationListenerNetwork);
Location net_loc = null, gps_loc = null;
if (gps_enabled) {
gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
if (network_enabled) {
net_loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (gps_loc != null && net_loc != null) {
if (gps_loc.getTime() > net_loc.getTime()) {
locationResult.gotLocation(gps_loc);
} else {
locationResult.gotLocation(net_loc);
}
return;
}
if (gps_loc != null) {
locationResult.gotLocation(gps_loc);
return;
}
if (net_loc != null) {
locationResult.gotLocation(net_loc);
return;
}
else {
locationResult.gotLocation(null);
}
}
}
public static abstract class LocationResult {
public abstract void gotLocation(Location location);
}
}
Splashscreen class
package com.driverapp.inis.zuber;
import android.app.Activity;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import Connectivity_manager.Internet_CheckingActivity;
public class Splashscreen extends Activity {
private static final String TAG = "SplashScreenActivity";
private Location newLocation = null;
private AlertDialogManager alert;
private Internet_CheckingActivity chckInternt;
private GeoLocationFinder geoLocationFinder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
alert = new AlertDialogManager();
chckInternt = new Internet_CheckingActivity(this);
}
#Override
protected void onResume() {
super.onResume();
// setupLocation();
if (chckInternt.isNetworkAvailable() == true) {
setupLocation();
}
else
{
alert.showAlertDialog(Splashscreen.this, "Error", "Please Check Your Internet Connection", false);
}
}
/** Method for checking the current lat log values. */
private void setupLocation() {
GeoLocationFinder.LocationResult locationResult = new GeoLocationFinder.LocationResult() {
#Override
public void gotLocation(Location location) {
if (location != null) {
newLocation = new Location(location);
newLocation.set(location);
Log.d(TAG,
"Got coordinates, congratulations. Longitude = "
+ newLocation.getLongitude() + " Latitude = "
+ newLocation.getLatitude());
Intent i = new Intent(Splashscreen.this, LoginActivity.class);
startActivity(i);
finish();
} else{
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
alert.showAlertDialog(Splashscreen.this, "Check Your GPS", "Restart your Application", false);
}
});
}
}
};
geoLocationFinder = new GeoLocationFinder();
geoLocationFinder.getLocation(this,locationResult);
}
}
AlertDialogManager class
package com.driverapp.inis.zuber;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.ContextThemeWrapper;
public class AlertDialogManager {
/**
* Function to display simple Alert Dialog
* #param context - application context
* #param title - alert dialog title
* #param message - alert message
* #param status - success/failure (used to set icon)
* - pass null if you don't want icon
* */
public int setOk = 0;
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
// AlertDialog alertDialog = new AlertDialog.Builder(context).create();
AlertDialog.Builder alertDialog= new AlertDialog.Builder(new ContextThemeWrapper(context,R.style.AlertDialogCustom));
// Setting Dialog Title
alertDialog.setTitle(title);
// Setting Dialog Message
alertDialog.setMessage(message);
if(status != null)
// Setting alert dialog icon
alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);
// Setting OK Button
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
// Showing Alert Message
alertDialog.setCancelable(Boolean.FALSE);
alertDialog.show();
}
/*Aler used for the delete in sheet details*/
public void showAlertDialogDelete(final Context context, String title, String message,
Boolean status) {
// AlertDialog alertDialog = new AlertDialog.Builder(context).create();
AlertDialog.Builder alertDialog= new AlertDialog.Builder(new ContextThemeWrapper(context,R.style.AlertDialogCustom));
// Setting Dialog Title
alertDialog.setTitle(title);
// Setting Dialog Message
alertDialog.setMessage(message);
if(status != null)
// Setting alert dialog icon
alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);
// Setting OK Button
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent in = new Intent(context, Splashscreen.class);
context.startActivity(in);
}
});
// Showing Alert Message
alertDialog.setCancelable(Boolean.FALSE);
alertDialog.show();
}
}
Add the following code in OnClick() method of the Positive buton:
Intent intent = new Intent(context, Splashscreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
It will clear the activity stack of your application and launch Splashscreen activity.
I'm really sorry ahead of time, but this question is pretty lengthy.
I have a functioning GPSTracker class that contains the means of pinging GPS Location for a device. In my MainActivity, I have a button that uses the GPS tracker to display the location in a toast. I'm trying to convert this button into an automatic action to be repeated every X minutes, let's go with 10.(Right now the alarm receiver is setup for 10 seconds)
Even when the app is in the background. So I set up an AlarmReceiver to try to do this, but I can't quite get it working.
Here's my GPSTracker class:
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
public class GPSTracker extends Service implements LocationListener {
private final Context context;
boolean isGPSEnabled = false;
boolean canGetLocation = false;
boolean isNetworkEnabled = false;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
protected LocationManager locationManager;
public GPSTracker(Context context) {
this.context = context.getApplicationContext();
getLocation();
}
public Location getLocation(){
try {
locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(!isGPSEnabled && !isNetworkEnabled) {
}else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if(locationManager != null){
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location !=null){
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if(isGPSEnabled){
if(location == null){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if(locationManager !=null){
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null){
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
public void stopUsingGPS() {
if(locationManager != null){
locationManager.removeUpdates(GPSTracker.this);
}
}
public double getLatitude() {
if(location!= null){
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude() {
if(location !=null){
longitude = location.getLongitude();
}
return longitude;
}
public boolean canGetLocation(){
return this.canGetLocation;
}
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("GPS is settings");
alertDialog.setMessage("GPS isn't enabled. Do you want to go to settings menu?");
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int i) {
dialog.cancel();
}
});
alertDialog.show();
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
And here's my MainActivity:
package com.example.gwyn.locationnabtest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends ActionBarActivity {
Button btnShowLocation;
Button btnStartService;
Button btnStopService;
GPSTracker gps;
//GoogleMap mMap;
private PendingIntent pendingIntent;
private AlarmManager manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnShowLocation = (Button) findViewById(R.id.show_location);
btnShowLocation.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
FragmentActivity activity = (FragmentActivity)view.getContext();
FragmentManager manager = activity.getSupportFragmentManager();
//MapFragment myMap = (MapFragment) (MainActivity.getFragmentManager()).findFragmentById((R.id.mapFragment));
// Test, remove me.
// mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
gps = new GPSTracker(MainActivity.this);
if(gps.canGetLocation()) {
// Location Achieved.
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
// Draw Marker for Current Location on Fragment
// Currently Crashing App
// mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("Marker"));
// Toast a popup of the location data.
Toast.makeText(getApplicationContext(), "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
} else {
gps.showSettingsAlert();
}
}
});
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
btnStartService = (Button) findViewById(R.id.start_service);
btnStartService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int interval = 10000;
// 10 Second Interval. Good for testing, but turn this off.
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();
//startService(new Intent(getBaseContext(), MyServices.class));
}
});
btnStopService = (Button) findViewById(R.id.stop_service);
btnStopService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Cancel pending intents
manager.cancel(pendingIntent);
Toast.makeText(getApplicationContext(), "Pending Intents Cancelled", Toast.LENGTH_SHORT).show();
}
});
}
}
To highlight specifically, this is the part in MainActivity that works to display the GPS:
public void onClick(View view) {
FragmentActivity activity = (FragmentActivity)view.getContext();
FragmentManager manager = activity.getSupportFragmentManager();
//MapFragment myMap = (MapFragment) (MainActivity.getFragmentManager()).findFragmentById((R.id.mapFragment));
// Test, remove me.
// mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
gps = new GPSTracker(MainActivity.this);
if(gps.canGetLocation()) {
// Location Achieved.
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
// Draw Marker for Current Location on Fragment
// Currently Crashing App
// mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("Marker"));
// Toast a popup of the location data.
Toast.makeText(getApplicationContext(), "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
} else {
gps.showSettingsAlert();
}
}
My AlarmReceiver is as follows, and produces an error when creating the GPSTracker:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
GPSTracker gps;
#Override
public void onReceive(Context arg0, Intent arg1) {
// Here's where we'd grab location and store it into DB.
//gps = new GPSTracker(AlarmReceiver.this);
// if(gps.canGetLocation()) {
// double latitude = gps.getLatitude();
// double longitude = gps.getLongitude();
// Draw Marker for Current Location on Fragment
// Toast a popup of the location data.
// Toast.makeText(arg0, "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
// } else {
// gps.showSettingsAlert();
// }
// Toast that the alarm ran.
Toast.makeText(arg0, "Location Pinged.", Toast.LENGTH_SHORT).show();
}
More specifically, a part of the problem is the way I'm calling for the new gps Tracker object here:
//gps = new GPSTracker(AlarmReceiver.this);
I'm not sure how to achieve the original result while using the alarmreceiver instead of a button, which is the main source of my problem. Does anyone know exactly what I can tinker with here to get the alarm receiver to properly use the GPSTracker Class?
DO not use GPSTracker. Its broken in over a dozen ways. Forget it exists. If you want a better version, you can use http://gabesechansoftware.com/location-tracking/ That link also explains why GPSTracker is broken by design and why it should never be used. It basically kinda works if used in optimal circumstances, and gives you horrible data in all the others.
Secondly, if you're using GPS and not network- you need to give it time to get a location sync. This can take seconds to minutes (or hours, if the user is in a basement or something) so the immediate forms of getting a location won't work- you have to wait for it to actually sync the location.
I suggest you not look for libraries to solve this and actually try to understand how the base APIs work. Until you do, you're going to have troubles with anything you use as there's lots of corner cases here and its not a trivial thing to do.