I have tried using androidhive's standard tutorial for finding location,but it fails at certain times.So i found another tutorial on this link:
http://gabesechansoftware.com/location-tracking/
He uses two classes which implement an interface:
The first class:
package com.example.marinamapseg;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
public class FallbackLocationTracker implements LocationTracker, LocationTracker.LocationUpdateListener {
private boolean isRunning;
private ProviderLocationTracker gps;
private ProviderLocationTracker net;
private LocationUpdateListener listener;
Location lastLoc;
long lastTime;
public FallbackLocationTracker(Context context) {
gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
}
public void start(){
if(isRunning){
//Already running, do nothing
return;
}
//Start both
gps.start(this);
net.start(this);
isRunning = true;
}
public void start(LocationUpdateListener update) {
start();
listener = update;
}
public void stop(){
if(isRunning){
gps.stop();
net.stop();
isRunning = false;
listener = null;
}
}
public boolean hasLocation(){
//If either has a location, use it
return gps.hasLocation() || net.hasLocation();
}
public boolean hasPossiblyStaleLocation(){
//If either has a location, use it
return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
}
public Location getLocation(){
Location ret = gps.getLocation();
if(ret == null){
ret = net.getLocation();
}
return ret;
}
public Location getPossiblyStaleLocation(){
Location ret = gps.getPossiblyStaleLocation();
if(ret == null){
ret = net.getPossiblyStaleLocation();
}
return ret;
}
public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
boolean update = false;
//We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
if(lastLoc == null){
update = true;
}
else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
update = true;
}
else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
update = true;
}
else if (newTime - lastTime > 5 * 60 * 1000){
update = true;
}
if(update){
lastLoc = newLoc;
lastTime = newTime;
if(listener != null){
listener.onUpdate(lastLoc, lastTime, newLoc, newTime);
}
}
}
}
The second class:
package com.example.marinamapseg;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
public class ProviderLocationTracker implements LocationListener, LocationTracker {
// The minimum distance to change Updates in meters
private static final long MIN_UPDATE_DISTANCE = 0;
// The minimum time between updates in milliseconds
private static final long MIN_UPDATE_TIME = 0;
private LocationManager lm;
public enum ProviderType{
NETWORK,
GPS
};
private String provider;
private Location lastLocation;
private long lastTime;
private boolean isRunning;
private LocationUpdateListener listener;
public ProviderLocationTracker(Context context, ProviderType type) {
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
if(type == ProviderType.NETWORK){
provider = LocationManager.NETWORK_PROVIDER;
}
else{
provider = LocationManager.GPS_PROVIDER;
}
}
public void start(){
if(isRunning){
//Already running, do nothing
return;
}
//The provider is on, so start getting updates. Update current location
isRunning = true;
lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
lastLocation = null;
lastTime = 0;
return;
}
public void start(LocationUpdateListener update) {
start();
listener = update;
}
public void stop(){
if(isRunning){
lm.removeUpdates(this);
isRunning = false;
listener = null;
}
}
public boolean hasLocation(){
if(lastLocation == null){
return false;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return false; //stale
}
return true;
}
public boolean hasPossiblyStaleLocation(){
if(lastLocation != null){
return true;
}
return lm.getLastKnownLocation(provider)!= null;
}
public Location getLocation(){
if(lastLocation == null){
return null;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return null; //stale
}
return lastLocation;
}
public Location getPossiblyStaleLocation(){
if(lastLocation != null){
return lastLocation;
}
return lm.getLastKnownLocation(provider);
}
public void onLocationChanged(Location newLoc) {
long now = System.currentTimeMillis();
if(listener != null){
listener.onUpdate(lastLocation, lastTime, newLoc, now);
}
lastLocation = newLoc;
lastTime = now;
}
public void onProviderDisabled(String arg0) {
}
public void onProviderEnabled(String arg0) {
}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
But the issue is that he has not mentioned as how to use the following two classes in the android app.So i tried the following:
FallbackLocationTracker fobj;
fobj=new FallbackLocationTracker(MainActivity.this);
fobj.start();
if(fobj.hasLocation())
{
Location locobj=fobj.getLocation();
current_latitude=locobj.getLatitude();
current_longitude=locobj.getLongitude();
Toast.makeText(getApplicationContext(),current_latitude+" "+current_longitude,Toast.LENGTH_LONG).show();
placemarkersonmap();
}
When i debug the code the hasLocation method returns false, Because the onLocationChanged method in the first class is getting called only after the haslocation method is called.So the lastlocation object will be null and false would be returned.
But why doesnt onlocationchanged get called as soon as the following line runs:
lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
Or is there any way somenone can tell me as how to use the code.Please help!!
onLocationChanged is a callback, meaning that it is event driven and does not run until the device detects a change of location. If you are taking location only from GPS, then it can take several minutes before you get a fix. If you are indoors without a clear view of the sky, then it may never run.
You may add the following in your actitvity's onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewHeading = (TextView) this.findViewById(R.id.text_heading);
textViewLong = (TextView) this.findViewById(R.id.text_long);
textViewLat = (TextView) this.findViewById(R.id.text_lat);
textViewHeight = (TextView) this.findViewById(R.id.text_height);
textViewAccuracy = (TextView) this.findViewById(R.id.text_accuracy);
counter = (long) 0;
gps = new ProviderLocationTracker(this,
ProviderLocationTracker.ProviderType.GPS);
listener = new LocationUpdateListener() {
#Override
public void onUpdate(Location oldLoc, long oldTime, Location newLoc,
long newTime) {
// TODO Auto-generated method stub
counter = counter + (long) 1;
if (gps.hasLocation()) {
text1="GPS has location ( " + counter.toString() + " )";
} else {
text1="GPS has no location ( " + counter.toString() + " )";
}
if (gps.hasPossiblyStaleLocation()) {
text1 = text1 + " plus stale location";
}
Double longitude = newLoc.getLongitude();
Double latitude = newLoc.getLatitude();
Double height = newLoc.getAltitude();
Float accuracy = newLoc.getAccuracy();
text2 = "Longitude = " + longitude.toString();
text3 = "Latitude = " + latitude.toString();
text4 = "Altitude = " + height.toString();
text5 = "Accuracy = " + accuracy.toString();
textViewHeading.setText(text1);
textViewLong.setText(text2);
textViewLat.setText(text3);
textViewHeight.setText(text4);
textViewAccuracy.setText(text5);
}
};
gps.start(listener);
} // end method onCreate
It seems that this post already has an answer that shows how to use the ProviderLocationTracker. I am putting in my answer just to show how easy it get's with the FallbackLocationTracker.
I do not remember making any significant changes to the FallbackLocationTracker so I am not going to post the whole code.
public class MainActivity extends AppCompatActivity {
private FallbackLocationTracker tracker;
private Location location;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tracker = new FallbackLocationTracker(MainActivity.this);
}
#Override
protected void onResume() {
super.onResume();
// Check for permission to access location and start location
// tracking if permissions are granted and location services
// are enabled
if (locationPermissionGranted && locationServicesEnabled) {
startLocationUpdates();
} else {
// Handle accordingly
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
private void startLocationUpdates() {
tracker.start(new LocationTracker.LocationUpdateListener() {
#Override
public void onUpdate(Location oldLocation, long oldTime,
Location newLocation, long newTime) {
// You will receive updated changes to your location here
location = newLocation;
}
});
}
private void stopLocationUpdates() {
tracker.stop();
}
}
That's it.
Related
I'm building video chat application using webrtc. when i started video call some error is coming. how to resolve that issue.
E/RoomRTCClient: Room connection error: HTTP POST to https://appr.tc/join/E52U8KA error: Unacceptable certificate: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB.
E/WSRTCClient: HTTP POST to https://appr.tc/join/E52U8KA error: Unacceptable certificate: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.UiThread;
import com.skillatwill.skillatwill.R;
import org.appspot.apprtc.AppRTCClient;
import org.appspot.apprtc.PeerConnectionClient;
import org.appspot.apprtc.WebSocketRTCClient;
import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.IceCandidate;
import org.webrtc.Logging;
import org.webrtc.RendererCommon.ScalingType;
import org.webrtc.SessionDescription;
import org.webrtc.StatsReport;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoFrame;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoSink;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
/**
* Activity for peer connection call setup, call waiting
* and call view.
*/
public class CallActivity extends Activity implements AppRTCClient.SignalingEvents,
PeerConnectionClient.PeerConnectionEvents {
private static final String TAG = "CallActivity";
private static final String APPRTC_URL = "https://appr.tc";
private static final String UPPER_ALPHA_DIGITS = "ACEFGHJKLMNPQRUVWXY123456789";
// Peer connection statistics callback period in ms.
private static final int STAT_CALLBACK_PERIOD = 1000;
private final ProxyRenderer remoteProxyRenderer = new ProxyRenderer();
private final ProxyVideoSink localProxyVideoSink = new ProxyVideoSink();
private final List<VideoRenderer.Callbacks> remoteRenderers = new ArrayList<>();
private PeerConnectionClient peerConnectionClient = null;
private AppRTCClient appRtcClient;
private AppRTCClient.SignalingParameters signalingParameters;
private SurfaceViewRenderer pipRenderer;
private SurfaceViewRenderer fullscreenRenderer;
private Toast logToast;
private boolean activityRunning;
private AppRTCClient.RoomConnectionParameters roomConnectionParameters;
private PeerConnectionClient.PeerConnectionParameters peerConnectionParameters;
private boolean iceConnected;
private boolean isError;
private long callStartedTimeMs = 0;
private boolean micEnabled = true;
private boolean isSwappedFeeds;
// Control buttons for limited UI
private ImageButton disconnectButton;
private ImageButton cameraSwitchButton;
private ImageButton toggleMuteButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
iceConnected = false;
signalingParameters = null;
// Create UI controls.
pipRenderer = findViewById(R.id.pip_video_view);
fullscreenRenderer = findViewById(R.id.fullscreen_video_view);
disconnectButton = findViewById(R.id.button_call_disconnect);
cameraSwitchButton = findViewById(R.id.button_call_switch_camera);
toggleMuteButton = findViewById(R.id.button_call_toggle_mic);
// Add buttons click events.
disconnectButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
onCallHangUp();
}
});
cameraSwitchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onCameraSwitch();
}
});
toggleMuteButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
boolean enabled = onToggleMic();
toggleMuteButton.setAlpha(enabled ? 1.0f : 0.3f);
}
});
// Swap feeds on pip view click.
pipRenderer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setSwappedFeeds(!isSwappedFeeds);
}
});
remoteRenderers.add(remoteProxyRenderer);
// Create peer connection client.
peerConnectionClient = new PeerConnectionClient();
// Create video renderers.
pipRenderer.init(peerConnectionClient.getRenderContext(), null);
pipRenderer.setScalingType(ScalingType.SCALE_ASPECT_FIT);
fullscreenRenderer.init(peerConnectionClient.getRenderContext(), null);
fullscreenRenderer.setScalingType(ScalingType.SCALE_ASPECT_FILL);
pipRenderer.setZOrderMediaOverlay(true);
pipRenderer.setEnableHardwareScaler(true /* enabled */);
fullscreenRenderer.setEnableHardwareScaler(true /* enabled */);
// Start with local feed in fullscreen and swap it to the pip when the call is connected.
setSwappedFeeds(true /* isSwappedFeeds */);
// Generate a random room ID with 7 uppercase letters and digits
String randomRoomID = randomString(7, UPPER_ALPHA_DIGITS);
// Show the random room ID so that another client can join from https://appr.tc
TextView roomIdTextView = findViewById(R.id.roomID);
roomIdTextView.setText(getString(R.string.room_id_caption) + randomRoomID);
Log.d(TAG, getString(R.string.room_id_caption) + randomRoomID);
// Connect video call to the random room
connectVideoCall(randomRoomID);
}
// Create a random string
private String randomString(int length, String characterSet) {
StringBuilder sb = new StringBuilder(); //consider using StringBuffer if needed
for (int i = 0; i < length; i++) {
int randomInt = new SecureRandom().nextInt(characterSet.length());
sb.append(characterSet.substring(randomInt, randomInt + 1));
}
return sb.toString();
}
// Join video call with randomly generated roomId
private void connectVideoCall(String roomId) {
Uri roomUri = Uri.parse(APPRTC_URL);
int videoWidth = 0;
int videoHeight = 0;
peerConnectionParameters =
new PeerConnectionClient.PeerConnectionParameters(true,
false,
false,
videoWidth,
videoHeight,
0,
Integer.parseInt(getString(R.string.pref_maxvideobitratevalue_default)),
getString(R.string.pref_videocodec_default),
true,
false,
Integer.parseInt(getString(R.string.pref_startaudiobitratevalue_default)),
getString(R.string.pref_audiocodec_default),
false,
false,
false,
false,
false,
false,
false,
false,
null);
// Create connection client. Use the standard WebSocketRTCClient.
// DirectRTCClient could be used for point-to-point connection
appRtcClient = new WebSocketRTCClient(this);
// Create connection parameters.
roomConnectionParameters =
new AppRTCClient.RoomConnectionParameters(
roomUri.toString(),
roomId,
false,
null);
peerConnectionClient.createPeerConnectionFactory(
getApplicationContext(), peerConnectionParameters, CallActivity.this);
startCall();
}
public void onCallHangUp() {
disconnect();
}
public void onCameraSwitch() {
if (peerConnectionClient != null) {
peerConnectionClient.switchCamera();
}
}
public boolean onToggleMic() {
if (peerConnectionClient != null) {
micEnabled = !micEnabled;
peerConnectionClient.setAudioEnabled(micEnabled);
}
return micEnabled;
}
private void startCall() {
if (appRtcClient == null) {
Log.e(TAG, "AppRTC client is not allocated for a call.");
return;
}
callStartedTimeMs = System.currentTimeMillis();
// Start room connection.
logAndToast(getString(R.string.connecting_to, roomConnectionParameters.roomUrl));
appRtcClient.connectToRoom(roomConnectionParameters);
}
#UiThread
private void callConnected() {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
Log.i(TAG, "Call connected: delay=" + delta + "ms");
if (peerConnectionClient == null || isError) {
Log.w(TAG, "Call is connected in closed or error state");
return;
}
// Enable statistics callback.
peerConnectionClient.enableStatsEvents(true, STAT_CALLBACK_PERIOD);
setSwappedFeeds(false /* isSwappedFeeds */);
}
// Disconnect from remote resources, dispose of local resources, and exit.
private void disconnect() {
activityRunning = false;
remoteProxyRenderer.setTarget(null);
localProxyVideoSink.setTarget(null);
if (appRtcClient != null) {
appRtcClient.disconnectFromRoom();
appRtcClient = null;
}
if (pipRenderer != null) {
pipRenderer.release();
pipRenderer = null;
}
if (fullscreenRenderer != null) {
fullscreenRenderer.release();
fullscreenRenderer = null;
}
if (peerConnectionClient != null) {
peerConnectionClient.close();
peerConnectionClient = null;
}
if (iceConnected && !isError) {
setResult(RESULT_OK);
} else {
setResult(RESULT_CANCELED);
}
finish();
}
private void disconnectWithErrorMessage(final String errorMessage) {
if (!activityRunning) {
Log.e(TAG, "Critical error: " + errorMessage);
disconnect();
} else {
new AlertDialog.Builder(this)
.setTitle(getText(R.string.channel_error_title))
.setMessage(errorMessage)
.setCancelable(false)
.setNeutralButton(R.string.ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
disconnect();
}
})
.create()
.show();
}
}
// Log |msg| and Toast about it.
private void logAndToast(String msg) {
Log.d(TAG, msg);
if (logToast != null) {
logToast.cancel();
}
logToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
logToast.show();
}
private void reportError(final String description) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!isError) {
isError = true;
disconnectWithErrorMessage(description);
}
}
});
}
// Create VideoCapturer
private VideoCapturer createVideoCapturer() {
final VideoCapturer videoCapturer;
Logging.d(TAG, "Creating capturer using camera2 API.");
videoCapturer = createCameraCapturer(new Camera2Enumerator(this));
if (videoCapturer == null) {
reportError("Failed to open camera");
return null;
}
return videoCapturer;
}
// Create VideoCapturer from camera
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
final String[] deviceNames = enumerator.getDeviceNames();
// First, try to find front facing camera
Logging.d(TAG, "Looking for front facing cameras.");
for (String deviceName : deviceNames) {
if (enumerator.isFrontFacing(deviceName)) {
Logging.d(TAG, "Creating front facing camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
// Front facing camera not found, try something else
Logging.d(TAG, "Looking for other cameras.");
for (String deviceName : deviceNames) {
if (!enumerator.isFrontFacing(deviceName)) {
Logging.d(TAG, "Creating other camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
return null;
}
private void setSwappedFeeds(boolean isSwappedFeeds) {
Logging.d(TAG, "setSwappedFeeds: " + isSwappedFeeds);
this.isSwappedFeeds = isSwappedFeeds;
localProxyVideoSink.setTarget(isSwappedFeeds ? fullscreenRenderer : pipRenderer);
remoteProxyRenderer.setTarget(isSwappedFeeds ? pipRenderer : fullscreenRenderer);
fullscreenRenderer.setMirror(isSwappedFeeds);
pipRenderer.setMirror(!isSwappedFeeds);
}
// -----Implementation of AppRTCClient.AppRTCSignalingEvents ---------------
// All callbacks are invoked from websocket signaling looper thread and
// are routed to UI thread.
private void onConnectedToRoomInternal(final AppRTCClient.SignalingParameters params) {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
signalingParameters = params;
logAndToast("Creating peer connection, delay=" + delta + "ms");
VideoCapturer videoCapturer = null;
if (peerConnectionParameters.videoCallEnabled) {
videoCapturer = createVideoCapturer();
}
peerConnectionClient.createPeerConnection(
localProxyVideoSink, remoteRenderers, videoCapturer, signalingParameters);
if (signalingParameters.initiator) {
logAndToast("Creating OFFER...");
// Create offer. Offer SDP will be sent to answering client in
// PeerConnectionEvents.onLocalDescription event.
peerConnectionClient.createOffer();
} else {
if (params.offerSdp != null) {
peerConnectionClient.setRemoteDescription(params.offerSdp);
logAndToast("Creating ANSWER...");
// Create answer. Answer SDP will be sent to offering client in
// PeerConnectionEvents.onLocalDescription event.
peerConnectionClient.createAnswer();
}
if (params.iceCandidates != null) {
// Add remote ICE candidates from room.
for (IceCandidate iceCandidate : params.iceCandidates) {
peerConnectionClient.addRemoteIceCandidate(iceCandidate);
}
}
}
}
#Override
public void onConnectedToRoom(final AppRTCClient.SignalingParameters params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
onConnectedToRoomInternal(params);
}
});
}
#Override
public void onRemoteDescription(final SessionDescription sdp) {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (peerConnectionClient == null) {
Log.e(TAG, "Received remote SDP for non-initilized peer connection.");
return;
}
logAndToast("Received remote " + sdp.type + ", delay=" + delta + "ms");
peerConnectionClient.setRemoteDescription(sdp);
if (!signalingParameters.initiator) {
logAndToast("Creating ANSWER...");
// Create answer. Answer SDP will be sent to offering client in
// PeerConnectionEvents.onLocalDescription event.
peerConnectionClient.createAnswer();
}
}
});
}
#Override
public void onRemoteIceCandidate(final IceCandidate candidate) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (peerConnectionClient == null) {
Log.e(TAG, "Received ICE candidate for a non-initialized peer connection.");
return;
}
peerConnectionClient.addRemoteIceCandidate(candidate);
}
});
}
#Override
public void onRemoteIceCandidatesRemoved(final IceCandidate[] candidates) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (peerConnectionClient == null) {
Log.e(TAG, "Received ICE candidate removals for a non-initialized peer connection.");
return;
}
peerConnectionClient.removeRemoteIceCandidates(candidates);
}
});
}
#Override
public void onChannelClose() {
runOnUiThread(new Runnable() {
#Override
public void run() {
logAndToast("Remote end hung up; dropping PeerConnection");
disconnect();
}
});
}
#Override
public void onChannelError(final String description) {
reportError(description);
}
// -----Implementation of PeerConnectionClient.PeerConnectionEvents.---------
// Send local peer connection SDP and ICE candidates to remote party.
// All callbacks are invoked from peer connection client looper thread and
// are routed to UI thread.
#Override
public void onLocalDescription(final SessionDescription sdp) {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (appRtcClient != null) {
logAndToast("Sending " + sdp.type + ", delay=" + delta + "ms");
if (signalingParameters.initiator) {
appRtcClient.sendOfferSdp(sdp);
} else {
appRtcClient.sendAnswerSdp(sdp);
}
}
if (peerConnectionParameters.videoMaxBitrate > 0) {
Log.d(TAG, "Set video maximum bitrate: " + peerConnectionParameters.videoMaxBitrate);
peerConnectionClient.setVideoMaxBitrate(peerConnectionParameters.videoMaxBitrate);
}
}
});
}
#Override
public void onIceCandidate(final IceCandidate candidate) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (appRtcClient != null) {
appRtcClient.sendLocalIceCandidate(candidate);
}
}
});
}
#Override
public void onIceCandidatesRemoved(final IceCandidate[] candidates) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (appRtcClient != null) {
appRtcClient.sendLocalIceCandidateRemovals(candidates);
}
}
});
}
#Override
public void onIceConnected() {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
#Override
public void run() {
logAndToast("ICE connected, delay=" + delta + "ms");
iceConnected = true;
callConnected();
}
});
}
#Override
public void onIceDisconnected() {
runOnUiThread(new Runnable() {
#Override
public void run() {
logAndToast("ICE disconnected");
iceConnected = false;
disconnect();
}
});
}
#Override
public void onPeerConnectionClosed() {
}
#Override
public void onPeerConnectionStatsReady(final StatsReport[] reports) {
}
#Override
public void onPeerConnectionError(final String description) {
reportError(description);
}
// Activity interfaces
#Override
public void onStop() {
super.onStop();
activityRunning = false;
if (peerConnectionClient != null) {
peerConnectionClient.stopVideoSource();
}
}
#Override
public void onStart() {
super.onStart();
activityRunning = true;
// Video is not paused for screencapture. See onPause.
if (peerConnectionClient != null) {
peerConnectionClient.startVideoSource();
}
}
#Override
protected void onDestroy() {
Thread.setDefaultUncaughtExceptionHandler(null);
disconnect();
if (logToast != null) {
logToast.cancel();
}
activityRunning = false;
super.onDestroy();
}
private static class ProxyRenderer implements VideoRenderer.Callbacks {
private VideoRenderer.Callbacks target;
#Override
synchronized public void renderFrame(VideoRenderer.I420Frame frame) {
if (target == null) {
Logging.d(TAG, "Dropping frame in proxy because target is null.");
VideoRenderer.renderFrameDone(frame);
return;
}
target.renderFrame(frame);
}
synchronized public void setTarget(VideoRenderer.Callbacks target) {
this.target = target;
}
}
private static class ProxyVideoSink implements VideoSink {
private VideoSink target;
#Override
synchronized public void onFrame(VideoFrame frame) {
if (target == null) {
Logging.d(TAG, "Dropping frame in proxy because target is null.");
return;
}
target.onFrame(frame);
}
synchronized public void setTarget(VideoSink target) {
this.target = target;
}
}
}
You are using a demo signaling server operated by an entity (Google) that does not consider this demo signaling server a production system. The certificate expired a week ago.
Run your own server, instructions can be found here: https://github.com/webrtc/apprtc
I have an activity that calls a service on its onCreate , however when I try yo run the project I keep getting an error saying the service has leaked and longer bound on the activity that called/registered it .
"Activity com.xera.deviceinsight.home.DataUsageActivity has leaked ServiceConnection com.xera.deviceinsight.home.DataUsageActivity$3#42676a48 that was originally bound here" I am assuming this might have something to do with the lifecycle of the activity . I have both the activity and the service in question below
myActivity
public class DataUsageActivity extends AppCompatActivity implements MonitorService.ServiceCallback
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TinyDB settings = new TinyDB(this);
if (settings.getBoolean(AppPreferences.HAS_LOGGED_IN))
{
this.bindService(
new Intent(this, MonitorService.class),
serviceConnection,
Context.BIND_AUTO_CREATE);
return;
}
}
public void sendResults(int resultCode, Bundle b)
{
// adapter.notifyDataSetChanged();
}
private ServiceConnection serviceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName className, IBinder service)
{
MonitorService.LocalBinder binder = (MonitorService.LocalBinder)service;
backgroundService = binder.getService();
backgroundService.setCallback(DataUsageActivity.this);
backgroundService.start();
}
#Override
public void onServiceDisconnected(ComponentName className)
{
backgroundService = null;
}
};
#Override
public void onResume()
{
super.onResume();
if(backgroundService != null)
{
backgroundService.setCallback(this);
}
}
#Override
public void onPause()
{
super.onPause();
if(backgroundService != null)
{
backgroundService.setCallback(null);
}
}
}
**myService**
public class MonitorService extends Service
{
private boolean initialized = false;
private final IBinder mBinder = new LocalBinder();
private ServiceCallback callback = null;
private Timer timer = null;
private final Handler mHandler = new Handler();
private String foreground = null;
private ArrayList<HashMap<String,Object>> processList;
private ArrayList<String> packages;
private Date split = null;
// private Date startTime = null;
public int timeCheckVariable = 0 ;
public static int SERVICE_PERIOD = 5000; // TODO: customize (this is for scan every 5 seconds)
private final ProcessList pl = new ProcessList(this)
{
#Override
protected boolean isFilteredByName(String pack)
{
// TODO: filter processes by names, return true to skip the process
// always return false (by default) to monitor all processes
return false;
}
};
public interface ServiceCallback
{
void sendResults(int resultCode, Bundle b);
}
public class LocalBinder extends Binder
{
MonitorService getService()
{
// Return this instance of the service so clients can call public methods
return MonitorService.this;
}
}
#Override
public void onCreate()
{
super.onCreate();
initialized = true;
processList = ((DeviceInsightApp)getApplication()).getProcessList();
packages = ((DeviceInsightApp)getApplication()).getPackages();
}
#Override
public IBinder onBind(Intent intent)
{
if(initialized)
{
return mBinder;
}
return null;
}
public void setCallback(ServiceCallback callback)
{
this.callback = callback;
}
// private boolean addToStatistics(String target , Long startTime)
private boolean addToStatistics(String target )
{
boolean changed = false;
Date now = new Date();
if(!TextUtils.isEmpty(target))
{
if(!target.equals(foreground))
{
int i;
// timeCheckVariable = i ;
if(foreground != null && split != null)
{
// TODO: calculate time difference from current moment
// to the moment when previous foreground process was activated
i = packages.indexOf(foreground);
timeCheckVariable = i ;
long delta = (now.getTime() - split.getTime()) / 1000;
Long time = (Long)processList.get(i).get(ProcessList.COLUMN_PROCESS_TIME);
if(time != null)
{
// TODO: add the delta to statistics of 'foreground'
time += delta;
}
else
{
time = new Long(delta);
}
processList.get(i).put(ProcessList.COLUMN_PROCESS_TIME, time);
//String applicationName = (String)processList.get(i).get(ProcessList.COLUMN_PROCESS_NAME);
// DatabaseHandler db = new DatabaseHandler(this);
// int x = time.intValue( );
// db.addAppRecord(new AppUsageClass(applicationName , x));
// db.getApplicationCount();
// List<AppUsageClass> appUsageClass = db.getAllApplications();
// db.getApplicationCount();
// for (AppUsageClass cn : appUsageClass) {
//String log = "Id: " + cn.getID() + " ,ApplicationName : " + cn.getName() + " ,TimeSpent: " + cn.getTimeSpent();
// Log.d("Name: ", log);
//}
}
//update count of process activation for new 'target'
i = packages.indexOf(target);
Integer count = (Integer)processList.get(i).get(ProcessList.COLUMN_PROCESS_COUNT);
if(count != null) count++;
else
{
count = new Integer(1);
}
processList.get(i).put(ProcessList.COLUMN_PROCESS_COUNT, count);
foreground = target;
split = now;
changed = true;
}
}
//Long checkTimeNow = (Long)processList.get(timeCheckVariable).get(ProcessList.COLUMN_PROCESS_TIME);
return changed;
}
public void start()
{
if(timer == null)
{
timer = new Timer();
timer.schedule(new MonitoringTimerTask(), 500, SERVICE_PERIOD);
}
// TODO: startForeground(srvcid, createNotification(null));
}
public void stop()
{
timer.cancel();
timer.purge();
timer = null;
}
private class MonitoringTimerTask extends TimerTask
{
#Override
public void run()
{
fillProcessList();
ActivityManager activityManager = (ActivityManager)MonitorService.this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
String current = taskInfo.get(0).topActivity.getPackageName(); // gets the application which is in the foreground
int i = packages.indexOf(current);
Long timecheck = (Long)processList.get(i).get(ProcessList.COLUMN_PROCESS_TIME);
if(addToStatistics(current)&& callback != null)
{
final Bundle b = new Bundle();
// TODO: pass necessary info to UI via bundle
mHandler.post(new Runnable()
{
public void run()
{
callback.sendResults(1, b);
}
});
}
}
}
private void fillProcessList()
{
pl.fillProcessList(processList, packages);
}
The problem is that you don't unbind from you service in .onPause() or in .onDestroy(), so if you Activity is destroyed, connection still last, so there is leaked connection. If you want you service to run all the time, you should start it by .startService() and then bind to it. In .onStop() or .onDestroy() unbind from that service
I am trying to get the current latitude and longitude using an example i found on the following link: http://gabesechansoftware.com/location-tracking/
There are two classes :The first class:
package com.example.marinamapseg;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
public class FallbackLocationTracker implements LocationTracker, LocationTracker.LocationUpdateListener {
private boolean isRunning;
private ProviderLocationTracker gps;
private ProviderLocationTracker net;
private LocationUpdateListener listener;
Location lastLoc;
long lastTime;
public FallbackLocationTracker(Context context) {
gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
}
public void start(){
if(isRunning){
//Already running, do nothing
return;
}
//Start both
gps.start(this);
net.start(this);
isRunning = true;
}
public void start(LocationUpdateListener update) {
start();
listener = update;
}
public void stop(){
if(isRunning){
gps.stop();
net.stop();
isRunning = false;
listener = null;
}
}
public boolean hasLocation(){
//If either has a location, use it
return gps.hasLocation() || net.hasLocation();
}
public boolean hasPossiblyStaleLocation(){
//If either has a location, use it
return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
}
public Location getLocation(){
Location ret = gps.getLocation();
if(ret == null){
ret = net.getLocation();
}
return ret;
}
public Location getPossiblyStaleLocation(){
Location ret = gps.getPossiblyStaleLocation();
if(ret == null){
ret = net.getPossiblyStaleLocation();
}
return ret;
}
public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
boolean update = false;
//We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
if(lastLoc == null){
update = true;
}
else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
update = true;
}
else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
update = true;
}
else if (newTime - lastTime > 5 * 60 * 1000){
update = true;
}
if(update){
lastLoc = newLoc;
lastTime = newTime;
if(listener != null){
listener.onUpdate(lastLoc, lastTime, newLoc, newTime);
}
}
}
}
The second class:
package com.example.marinamapseg;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
public class ProviderLocationTracker implements LocationListener, LocationTracker {
// The minimum distance to change Updates in meters
private static final long MIN_UPDATE_DISTANCE = 0;
// The minimum time between updates in milliseconds
private static final long MIN_UPDATE_TIME = 0;
private LocationManager lm;
public enum ProviderType{
NETWORK,
GPS
};
private String provider;
private Location lastLocation;
private long lastTime;
private boolean isRunning;
private LocationUpdateListener listener;
public ProviderLocationTracker(Context context, ProviderType type) {
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
if(type == ProviderType.NETWORK){
provider = LocationManager.NETWORK_PROVIDER;
}
else{
provider = LocationManager.GPS_PROVIDER;
}
}
public void start(){
if(isRunning){
//Already running, do nothing
return;
}
//The provider is on, so start getting updates. Update current location
isRunning = true;
lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE,this);
lastLocation = null;
lastTime = 0;
//lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE,this);
//return;
}
public void start(LocationUpdateListener update) {
start();
listener = update;
}
public void stop(){
if(isRunning){
lm.removeUpdates(this);
isRunning = false;
listener = null;
}
}
public boolean hasLocation(){
if(lastLocation == null){
return false;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return false; //stale
}
return true;
}
public boolean hasPossiblyStaleLocation(){
if(lastLocation != null){
return true;
}
return lm.getLastKnownLocation(provider)!= null;
}
public Location getLocation(){
if(lastLocation == null){
return null;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return null; //stale
}
return lastLocation;
}
public Location getPossiblyStaleLocation(){
if(lastLocation != null){
return lastLocation;
}
return lm.getLastKnownLocation(provider);
}
public void onLocationChanged(Location newLoc) {
long now = System.currentTimeMillis();
if(listener != null){
listener.onUpdate(lastLocation, lastTime, newLoc, now);
}
lastLocation = newLoc;
lastTime = now;
}
public void onProviderDisabled(String arg0) {
}
public void onProviderEnabled(String arg0) {
}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
What i tried doing was to create an object of the first class and check whether the location can be found as follows:
fobj=new FallbackLocationTracker(MainActivity.this);
fobj.start();
if(fobj.hasLocation())
{
Location locobj=fobj.getLocation();
current_latitude=locobj.getLatitude();
current_longitude=locobj.getLongitude();
Toast.makeText(getApplicationContext(),current_latitude+" "+current_longitude,Toast.LENGTH_LONG).show();
placemarkersonmap();
}
The issue is as follows:
The haslocation() method will return false as the lastlocation object is null.But the lastlocation object gets a value only in the onlocationchanged method.So how do i ensure that the onlocationchanged method runs before i call my haslocation method?
So how do i ensure that the onlocationchanged method runs before i call my haslocation method?
onLocationChanged() may never be called. Just because you want a location does not mean that the user has to allow you to get one (e.g., user has both providers disabled). And, just because you want a location does not mean that it is physically possible to get one (e.g., user has GPS disabled and has airplane mode enabled). And, just because you want a location does not mean one will be ready yet.
Hence, your application already needs to deal with not having a location, so add that logic to your app.
You are certainly welcome to also do something more event-driven, starting up some application logic from onLocationChanged(), once you have demonstrated you are at least temporarily able to get location fixes.
i have class implements Serializable :
public class LocationUtilGPSNetwork implements Serializable
{
private Context mContext;
private LocationManager mLocationManager;
// private LocationListener mListenerPassive;
private LocationListener mListenerNetwork;
private LocationListener mListenerGPS;
private Location mLocation;
private long mTimeLimit;
public LocationUtilGPSNetwork(Context context)
{
mContext = context;
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
mListenerNetwork = new LocationListener()
{
#Override
public void onLocationChanged(Location location)
{
updateLocation(location);
Log.i("Location", "Network:" + location);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle)
{
}
#Override
public void onProviderEnabled(String s)
{
}
#Override
public void onProviderDisabled(String s)
{
}
};
mListenerGPS = new LocationListener()
{
#Override
public void onLocationChanged(Location location)
{
updateLocation(location);
Log.i("Location", "GPS:" + location);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle)
{
}
#Override
public void onProviderEnabled(String s)
{
}
#Override
public void onProviderDisabled(String s)
{
}
};
}
public void startLocationListeners(long minTimeUpdate, float minDistanceUpdate, long timeLimit)
{
mTimeLimit = timeLimit;
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, minTimeUpdate,
minDistanceUpdate, mListenerNetwork);
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTimeUpdate,
minDistanceUpdate, mListenerGPS);
}
private void updateLocation(Location location)
{
if (location != null && isBetterLocation(location, mLocation))
{
mLocation = location;
}
}
private boolean isBetterLocation(Location location, Location currentBestLocation)
{
if (currentBestLocation == null)
{
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > mTimeLimit;
boolean isSignificantlyOlder = timeDelta < -mTimeLimit;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer)
{
return true;
}
// If the new location is more than two minutes older, it must be worse
else if (isSignificantlyOlder)
{
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate)
{
return true;
}
else if (isNewer && !isLessAccurate)
{
return true;
}
else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
{
return true;
}
return false;
}
private boolean isSameProvider(String provider1, String provider2)
{
if (provider1 == null)
{
return provider2 == null;
}
return provider1.equals(provider2);
}
public Location getLocation()
{
return mLocation;
}
public void stopLocationListeners()
{
mLocationManager.removeUpdates(mListenerNetwork);
mLocationManager.removeUpdates(mListenerGPS);
}
}
And when i put it into bundle :
bundle.putSerializable(MenuActivity.locationID, mLocationUtil);
i have this error
10-10 12:27:42.970: E/AndroidRuntime(20130): Caused by:
java.io.NotSerializableException:
com.pattindo.tilangapp.activity.MenuActivity
Why??
Because some members are not serializable!
You have other options,
Write your own serialize methods. see here
Create a class that includes only members that can be serializable and you really use as data, then instantiate and put it to bundle.
It is not serializable. Please, read more about serializable objects. It must have a non parameter public constructor. Must use serializable properties. Must follow java bean notation.
In no way you can serialize such a monster with, even, the context within!!!
I have literally been searching for this for weeks. I am a novice java programmer but I have been able to piece together an app that can use a double latitude and longitude hard coded in the same class. It will show a list of current places surrounding those points. I have another separate class with a method that is able to get the current location based on the gps/network but I can't pass the variables created from this second class to the PlaceRequest class. I have looked through all of the tutorials on the above subjects but there isn't anything combining current location and place search results. I have two getters declared but can't call the variables in these. Again sort of a rookie so may be an easy fix. Any ideas?
Update - Here is my code so far:
GooglePlaceActivity.java
public class GooglePlaceActivity extends Activity {
/** Called when the activity is first created. */
Button btn1;
TextView txt1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
btn1 = (Button)findViewById(R.id.button1);
txt1 = (TextView)findViewById(R.id.textView1);
btn1.setOnClickListener(l);
}
private class SearchSrv extends AsyncTask<Void, Void, PlacesList>{
#Override
protected PlacesList doInBackground(Void... params) {
PlacesList pl = null;
try {
pl = new PlaceRequest().performSearch();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return pl;
}
#Override
protected void onPostExecute(PlacesList result) {
String text = "Result \n";
if (result!=null){
for(Place place: result.results){
text = text + place.name +"\n";
}
txt1.setText(text);
}
setProgressBarIndeterminateVisibility(false);
}
}
View.OnClickListener l = new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
SearchSrv srv = new SearchSrv();
setProgressBarIndeterminateVisibility(true);
srv.execute();
}
};
}
//////////////////////
PlaceRequest.java
public class PlaceRequest {
private static final HttpTransport transport = new ApacheHttpTransport();
private static final String API_KEY = "keyhere";
private static final String LOG_KEY = "GGPlace";
// The different Places API endpoints.
private static final String PLACES_SEARCH_URL = "https://maps.googleapis.com/maps/api/place/search/json?";
private static final String PLACES_AUTOCOMPLETE_URL = "https://maps.googleapis.com/maps/api/place/autocomplete/json?";
private static final String PLACES_DETAILS_URL = "https://maps.googleapis.com/maps/api/place/details/json?";
private static final boolean PRINT_AS_STRING = true;
//double latitude;
//double longitude;
CurrentLocation clo = new CurrentLocation(null);
//clo.onLocationChanged(latitude);
//double longitude = CurrentLocation.getLongitude();
//double latitude = CurrentLocation.getLatitude();
double longi = clo.getLongitude();
double lat = clo.getLatitude();
public PlacesList performSearch() throws Exception {
try {
//CurrentLocation currlo = new CurrentLocation();
//double lat = currlo.getLatitude();
//double longi = currlo.getLongitude();
Log.v(LOG_KEY, "Start Search");
GenericUrl reqUrl = new GenericUrl(PLACES_SEARCH_URL);
reqUrl.put("key", API_KEY);
//reqUrl.put("location", latitude + "," + longitude);
//reqUrl.put("location", getLatitude(latitude) + "," + getLongitude());
reqUrl.put("location", lat + "," + longi);
reqUrl.put("radius", 1600);
reqUrl.put("types", "food");
reqUrl.put("sensor", "false");
Log.v(LOG_KEY, "url= " + reqUrl);
HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
HttpRequest request = httpRequestFactory.buildGetRequest(reqUrl);
Log.v(LOG_KEY, request.execute().parseAsString());
PlacesList places = request.execute().parseAs(PlacesList.class);
Log.v(LOG_KEY, "STATUS = " + places.status);
for (Place place : places.results) {
Log.v(LOG_KEY, place.name);
}
return places;
} catch (HttpResponseException e) {
Log.v(LOG_KEY, e.getResponse().parseAsString());
throw e;
}
catch (IOException e) {
// TODO: handle exception
throw e;
}
}
public static HttpRequestFactory createRequestFactory(final HttpTransport transport) {
return transport.createRequestFactory(new HttpRequestInitializer() {
public void initialize(HttpRequest request) {
GoogleHeaders headers = new GoogleHeaders();
headers.setApplicationName("Google-Places-DemoApp");
request.setHeaders(headers);
JsonHttpParser parser = new JsonHttpParser(new JacksonFactory()) ;
//JsonHttpParser.builder(new JacksonFactory());
//parser.jsonFactory = new JacksonFactory();
request.addParser(parser);
}
});
}
}
/////////////
CurrentLocation.java
public class CurrentLocation {
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1; // in Meters
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 1000; // in Milliseconds
LocationManager locationManager ;
double latitude=0;
double longitude=0;
public CurrentLocation(Context ctxt) {
super();
locationManager = (LocationManager) ctxt.getSystemService(Context.LOCATION_SERVICE);
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MINIMUM_TIME_BETWEEN_UPDATES,
MINIMUM_DISTANCE_CHANGE_FOR_UPDATES,
new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onLocationChanged(Location location) {
longitude = location.getLongitude();
latitude = location.getLatitude();
}
});
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
}
Edit: After looking your complete code, I see a few fundamental design flaws so I'm going to show you how I did it and you can adapt it to your program flow. Please keep in mind that this example is vastly simplified from my original, but it should be enough to get you going.
First, the CurrentLocation.java file. My design decision for wrapping this in a Future was so that I can re-use it in multiple activities with the added bonus of killing it when necessary.
public class CurrentLocation implements Callable<Location> {
private static final String TAG = "CurrentLocation";
private Context context;
private LocationManager lm;
private Criteria criteria;
private Location bestResult;
private boolean locationListenerWorking;
public CurrentLocation(Context context) {
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
this.context = context;
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
bestResult = null;
locationListenerWorking = false;
}
public Location call() {
return getLoc();
}
private Location getLoc() {
String provider = lm.getBestProvider(criteria, true);
if (provider != null) {
Log.d(TAG, "Using provider: " +provider);
locationListenerWorking = true;
lm.requestLocationUpdates(provider,
0,
0,
singeUpdateListener,
context.getMainLooper());
} else {
Log.w(TAG, "Couldn't find a location provider");
return null;
}
while (locationListenerWorking) {
// Check for the interrupt signal - terminate if necessary
if (Thread.currentThread().isInterrupted()) {
Log.i(TAG, "User initiated interrupt (cancel signal)");
cleanup();
break;
}
try {
// ghetto implementation of a busy wait...
Thread.sleep(500); // Sleep for half a second
} catch (Exception e) {
Log.d(TAG, "Thread interrupted..");
cleanup();
break;
}
}
return bestResult;
}
private void cleanup() {
if (lm != null) {
Log.d(TAG, "Location manager not null - cleaning up");
lm.removeUpdates(singeUpdateListener);
} else {
Log.d(TAG, "Location manager was NULL - no cleanup necessary");
}
}
/**
* This one-off {#link LocationListener} simply listens for a single location
* update before unregistering itself. The one-off location update is
* returned via the {#link LocationListener} specified in {#link
* setChangedLocationListener}.
*/
private LocationListener singeUpdateListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.d(TAG, "Got a location update");
if (location == null) {
Log.d(TAG, "Seems as if we got a null location");
} else {
bestResult = location;
}
cleanup();
locationListenerWorking = false;
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
}
Then in your calling class (i.e. where you need the lat/lon coordinates - you want to do this from an Activity):
private class GetLocationTask extends AsyncTask <Void, Void, Location> {
private Future<Location> future;
private ExecutorService executor = new ScheduledThreadPoolExecutor(5);
private boolean cancelTriggered = false;
protected void onPreExecute() {
Log.d(TAG, "Starting location get...");
}
public Location doInBackground(Void... arg) {
CurrentLocation currLoc = new CurrentLocation(getApplicationContext());
future = executor.submit(currLoc);
long LOCATION_TIMEOUT = 20000; // ms = 20 sec
try {
// return future.get(Constants.LOCATION_TIMEOUT, TimeUnit.MILLISECONDS);
return future.get(LOCATION_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Log.w(TAG, "Location get timed out");
future.cancel(true);
return null;
}
}
public boolean killTask() {
cancelTriggered = true;
boolean futureCancelRes = future.cancel(true);
this.cancel(true);
Log.d(TAG, "Result of cancelling task: " +futureCancelRes);
return futureCancelRes;
}
protected void onPostExecute(Location res) {
if (cancelTriggered) {
Log.d(TAG, "User initiated cancel - this is okay");
cancelTriggered = false;
} else if (res == null) {
Log.d(TAG, "Could not get a location result");
} else {
double lat = res.getLatitude();
double lon = res.getLongitude();
Log.d(TAG, "Latitude: " +lat);
Log.d(TAG, "Longitude: " +lon);
}
}
}
Finally to wrap things up, here's how you call it:
GetLocationTask t = new GetLocationTask();
t.execute();
And if you need to kill the location update for whatever reason (if your user switches out of your activity, etc), this will kill the AsyncTask as well as the associated Future task.
t.killTask();
P.S. You may want to get your API keys changed and edit it out of your post.