2017-12-08 18:35:59 +01:00
/ *
* This is the source code of Telegram for Android v . 3 . x . x .
* It is licensed under GNU GPL v . 2 or later .
* You should have received a copy of the license in this archive ( see LICENSE ) .
*
* Copyright Nikolai Kudashov , 2013 - 2017 .
* /
package org.telegram.messenger ;
import android.content.Context ;
import android.content.Intent ;
import android.location.Location ;
import android.location.LocationListener ;
import android.location.LocationManager ;
import android.os.Bundle ;
import android.text.TextUtils ;
import android.util.LongSparseArray ;
import android.util.SparseIntArray ;
import org.telegram.SQLite.SQLiteCursor ;
import org.telegram.SQLite.SQLitePreparedStatement ;
import org.telegram.tgnet.ConnectionsManager ;
import org.telegram.tgnet.NativeByteBuffer ;
import org.telegram.tgnet.RequestDelegate ;
import org.telegram.tgnet.TLObject ;
import org.telegram.tgnet.TLRPC ;
import java.util.ArrayList ;
public class LocationController implements NotificationCenter . NotificationCenterDelegate {
2018-07-30 04:07:02 +02:00
private LongSparseArray < SharingLocationInfo > sharingLocationsMap = new LongSparseArray < > ( ) ;
2017-12-08 18:35:59 +01:00
private ArrayList < SharingLocationInfo > sharingLocations = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
public LongSparseArray < ArrayList < TLRPC . Message > > locationsCache = new LongSparseArray < > ( ) ;
2017-12-08 18:35:59 +01:00
private LocationManager locationManager ;
private GpsLocationListener gpsLocationListener = new GpsLocationListener ( ) ;
private GpsLocationListener networkLocationListener = new GpsLocationListener ( ) ;
private GpsLocationListener passiveLocationListener = new GpsLocationListener ( ) ;
private Location lastKnownLocation ;
private long lastLocationSendTime ;
private boolean locationSentSinceLastGoogleMapUpdate = true ;
private long lastLocationStartTime ;
private boolean started ;
private boolean lastLocationByGoogleMaps ;
private SparseIntArray requests = new SparseIntArray ( ) ;
private LongSparseArray < Boolean > cacheRequests = new LongSparseArray < > ( ) ;
public ArrayList < SharingLocationInfo > sharingLocationsUI = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
private LongSparseArray < SharingLocationInfo > sharingLocationsMapUI = new LongSparseArray < > ( ) ;
2017-12-08 18:35:59 +01:00
private final static int BACKGROUD_UPDATE_TIME = 90 * 1000 ;
private final static int LOCATION_ACQUIRE_TIME = 10 * 1000 ;
private final static int FOREGROUND_UPDATE_TIME = 20 * 1000 ;
private final static double eps = 0 . 0001 ;
2018-07-30 04:07:02 +02:00
private int currentAccount ;
private static volatile LocationController Instance [ ] = new LocationController [ UserConfig . MAX_ACCOUNT_COUNT ] ;
2017-12-08 18:35:59 +01:00
2018-07-30 04:07:02 +02:00
public static LocationController getInstance ( int num ) {
LocationController localInstance = Instance [ num ] ;
2017-12-08 18:35:59 +01:00
if ( localInstance = = null ) {
synchronized ( LocationController . class ) {
2018-07-30 04:07:02 +02:00
localInstance = Instance [ num ] ;
2017-12-08 18:35:59 +01:00
if ( localInstance = = null ) {
2018-07-30 04:07:02 +02:00
Instance [ num ] = localInstance = new LocationController ( num ) ;
2017-12-08 18:35:59 +01:00
}
}
}
return localInstance ;
}
public static class SharingLocationInfo {
public long did ;
public int mid ;
public int stopTime ;
public int period ;
public MessageObject messageObject ;
}
private class GpsLocationListener implements LocationListener {
@Override
public void onLocationChanged ( Location location ) {
if ( location = = null ) {
return ;
}
if ( lastKnownLocation ! = null & & ( this = = networkLocationListener | | this = = passiveLocationListener ) ) {
if ( ! started & & location . distanceTo ( lastKnownLocation ) > 20 ) {
lastKnownLocation = location ;
lastLocationSendTime = System . currentTimeMillis ( ) - BACKGROUD_UPDATE_TIME + 5000 ;
}
} else {
lastKnownLocation = location ;
}
}
@Override
public void onStatusChanged ( String provider , int status , Bundle extras ) {
}
@Override
public void onProviderEnabled ( String provider ) {
}
@Override
public void onProviderDisabled ( String provider ) {
}
}
2018-07-30 04:07:02 +02:00
public LocationController ( final int instance ) {
currentAccount = instance ;
2017-12-08 18:35:59 +01:00
locationManager = ( LocationManager ) ApplicationLoader . applicationContext . getSystemService ( Context . LOCATION_SERVICE ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
2018-07-30 04:07:02 +02:00
LocationController locationController = getInstance ( currentAccount ) ;
NotificationCenter . getInstance ( currentAccount ) . addObserver ( locationController , NotificationCenter . didReceivedNewMessages ) ;
NotificationCenter . getInstance ( currentAccount ) . addObserver ( locationController , NotificationCenter . messagesDeleted ) ;
NotificationCenter . getInstance ( currentAccount ) . addObserver ( locationController , NotificationCenter . replaceMessagesObjects ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
loadSharingLocations ( ) ;
}
@SuppressWarnings ( " unchecked " )
@Override
2018-07-30 04:07:02 +02:00
public void didReceivedNotification ( int id , int account , Object . . . args ) {
2017-12-08 18:35:59 +01:00
if ( id = = NotificationCenter . didReceivedNewMessages ) {
long did = ( Long ) args [ 0 ] ;
if ( ! isSharingLocation ( did ) ) {
return ;
}
ArrayList < TLRPC . Message > messages = locationsCache . get ( did ) ;
if ( messages = = null ) {
return ;
}
ArrayList < MessageObject > arr = ( ArrayList < MessageObject > ) args [ 1 ] ;
boolean added = false ;
for ( int a = 0 ; a < arr . size ( ) ; a + + ) {
MessageObject messageObject = arr . get ( a ) ;
if ( messageObject . isLiveLocation ( ) ) {
added = true ;
boolean replaced = false ;
for ( int b = 0 ; b < messages . size ( ) ; b + + ) {
if ( messages . get ( b ) . from_id = = messageObject . messageOwner . from_id ) {
replaced = true ;
messages . set ( b , messageObject . messageOwner ) ;
break ;
}
}
if ( ! replaced ) {
messages . add ( messageObject . messageOwner ) ;
}
}
}
if ( added ) {
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsCacheChanged , did , currentAccount ) ;
2017-12-08 18:35:59 +01:00
}
} else if ( id = = NotificationCenter . messagesDeleted ) {
if ( ! sharingLocationsUI . isEmpty ( ) ) {
ArrayList < Integer > markAsDeletedMessages = ( ArrayList < Integer > ) args [ 0 ] ;
int channelId = ( Integer ) args [ 1 ] ;
ArrayList < Long > toRemove = null ;
for ( int a = 0 ; a < sharingLocationsUI . size ( ) ; a + + ) {
SharingLocationInfo info = sharingLocationsUI . get ( a ) ;
int messageChannelId = info . messageObject ! = null ? info . messageObject . getChannelId ( ) : 0 ;
if ( channelId ! = messageChannelId ) {
continue ;
}
if ( markAsDeletedMessages . contains ( info . mid ) ) {
if ( toRemove = = null ) {
toRemove = new ArrayList < > ( ) ;
}
toRemove . add ( info . did ) ;
}
}
if ( toRemove ! = null ) {
for ( int a = 0 ; a < toRemove . size ( ) ; a + + ) {
removeSharingLocation ( toRemove . get ( a ) ) ;
}
}
}
} else if ( id = = NotificationCenter . replaceMessagesObjects ) {
long did = ( long ) args [ 0 ] ;
if ( ! isSharingLocation ( did ) ) {
return ;
}
ArrayList < TLRPC . Message > messages = locationsCache . get ( did ) ;
if ( messages = = null ) {
return ;
}
boolean updated = false ;
ArrayList < MessageObject > messageObjects = ( ArrayList < MessageObject > ) args [ 1 ] ;
for ( int a = 0 ; a < messageObjects . size ( ) ; a + + ) {
MessageObject messageObject = messageObjects . get ( a ) ;
for ( int b = 0 ; b < messages . size ( ) ; b + + ) {
if ( messages . get ( b ) . from_id = = messageObject . messageOwner . from_id ) {
if ( ! messageObject . isLiveLocation ( ) ) {
messages . remove ( b ) ;
} else {
messages . set ( b , messageObject . messageOwner ) ;
}
updated = true ;
break ;
}
}
}
if ( updated ) {
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsCacheChanged , did , currentAccount ) ;
2017-12-08 18:35:59 +01:00
}
}
}
private void broadcastLastKnownLocation ( ) {
if ( lastKnownLocation = = null ) {
return ;
}
if ( requests . size ( ) ! = 0 ) {
for ( int a = 0 ; a < requests . size ( ) ; a + + ) {
2018-07-30 04:07:02 +02:00
ConnectionsManager . getInstance ( currentAccount ) . cancelRequest ( requests . keyAt ( a ) , false ) ;
2017-12-08 18:35:59 +01:00
}
requests . clear ( ) ;
}
2018-07-30 04:07:02 +02:00
int date = ConnectionsManager . getInstance ( currentAccount ) . getCurrentTime ( ) ;
2017-12-08 18:35:59 +01:00
for ( int a = 0 ; a < sharingLocations . size ( ) ; a + + ) {
final SharingLocationInfo info = sharingLocations . get ( a ) ;
if ( info . messageObject . messageOwner . media ! = null & & info . messageObject . messageOwner . media . geo ! = null ) {
int messageDate = info . messageObject . messageOwner . edit_date ! = 0 ? info . messageObject . messageOwner . edit_date : info . messageObject . messageOwner . date ;
TLRPC . GeoPoint point = info . messageObject . messageOwner . media . geo ;
if ( Math . abs ( date - messageDate ) < 30 & & Math . abs ( point . lat - lastKnownLocation . getLatitude ( ) ) < = eps & & Math . abs ( point . _long - lastKnownLocation . getLongitude ( ) ) < = eps ) {
continue ;
}
}
TLRPC . TL_messages_editMessage req = new TLRPC . TL_messages_editMessage ( ) ;
2018-07-30 04:07:02 +02:00
req . peer = MessagesController . getInstance ( currentAccount ) . getInputPeer ( ( int ) info . did ) ;
2017-12-08 18:35:59 +01:00
req . id = info . mid ;
req . stop_geo_live = false ;
req . flags | = 8192 ;
req . geo_point = new TLRPC . TL_inputGeoPoint ( ) ;
2018-07-30 04:07:02 +02:00
req . geo_point . lat = AndroidUtilities . fixLocationCoord ( lastKnownLocation . getLatitude ( ) ) ;
req . geo_point . _long = AndroidUtilities . fixLocationCoord ( lastKnownLocation . getLongitude ( ) ) ;
2017-12-08 18:35:59 +01:00
final int [ ] reqId = new int [ 1 ] ;
2018-07-30 04:07:02 +02:00
reqId [ 0 ] = ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , new RequestDelegate ( ) {
2017-12-08 18:35:59 +01:00
@Override
public void run ( TLObject response , TLRPC . TL_error error ) {
if ( error ! = null ) {
if ( error . text . equals ( " MESSAGE_ID_INVALID " ) ) {
sharingLocations . remove ( info ) ;
sharingLocationsMap . remove ( info . did ) ;
saveSharingLocation ( info , 1 ) ;
requests . delete ( reqId [ 0 ] ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
sharingLocationsUI . remove ( info ) ;
sharingLocationsMapUI . remove ( info . did ) ;
if ( sharingLocationsUI . isEmpty ( ) ) {
stopService ( ) ;
}
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsChanged ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
}
return ;
}
TLRPC . Updates updates = ( TLRPC . Updates ) response ;
boolean updated = false ;
for ( int a = 0 ; a < updates . updates . size ( ) ; a + + ) {
TLRPC . Update update = updates . updates . get ( a ) ;
if ( update instanceof TLRPC . TL_updateEditMessage ) {
updated = true ;
info . messageObject . messageOwner = ( ( TLRPC . TL_updateEditMessage ) update ) . message ;
} else if ( update instanceof TLRPC . TL_updateEditChannelMessage ) {
updated = true ;
info . messageObject . messageOwner = ( ( TLRPC . TL_updateEditChannelMessage ) update ) . message ;
}
}
if ( updated ) {
saveSharingLocation ( info , 0 ) ;
}
2018-07-30 04:07:02 +02:00
MessagesController . getInstance ( currentAccount ) . processUpdates ( updates , false ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
requests . put ( reqId [ 0 ] , 0 ) ;
}
2018-07-30 04:07:02 +02:00
ConnectionsManager . getInstance ( currentAccount ) . resumeNetworkMaybe ( ) ;
2017-12-08 18:35:59 +01:00
stop ( false ) ;
}
protected void update ( ) {
2018-07-30 04:07:02 +02:00
if ( sharingLocations . isEmpty ( ) ) {
return ;
}
for ( int a = 0 ; a < sharingLocations . size ( ) ; a + + ) {
final SharingLocationInfo info = sharingLocations . get ( a ) ;
int currentTime = ConnectionsManager . getInstance ( currentAccount ) . getCurrentTime ( ) ;
if ( info . stopTime < = currentTime ) {
sharingLocations . remove ( a ) ;
sharingLocationsMap . remove ( info . did ) ;
saveSharingLocation ( info , 1 ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
sharingLocationsUI . remove ( info ) ;
sharingLocationsMapUI . remove ( info . did ) ;
if ( sharingLocationsUI . isEmpty ( ) ) {
stopService ( ) ;
2017-12-08 18:35:59 +01:00
}
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsChanged ) ;
}
} ) ;
a - - ;
2017-12-08 18:35:59 +01:00
}
2018-07-30 04:07:02 +02:00
}
if ( ! started ) {
if ( Math . abs ( lastLocationSendTime - System . currentTimeMillis ( ) ) > BACKGROUD_UPDATE_TIME ) {
lastLocationStartTime = System . currentTimeMillis ( ) ;
start ( ) ;
}
} else {
if ( lastLocationByGoogleMaps | | Math . abs ( lastLocationStartTime - System . currentTimeMillis ( ) ) > LOCATION_ACQUIRE_TIME ) {
lastLocationByGoogleMaps = false ;
locationSentSinceLastGoogleMapUpdate = true ;
lastLocationSendTime = System . currentTimeMillis ( ) ;
broadcastLastKnownLocation ( ) ;
2017-12-08 18:35:59 +01:00
}
}
}
public void cleanup ( ) {
sharingLocationsUI . clear ( ) ;
sharingLocationsMapUI . clear ( ) ;
locationsCache . clear ( ) ;
cacheRequests . clear ( ) ;
stopService ( ) ;
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
requests . clear ( ) ;
sharingLocationsMap . clear ( ) ;
sharingLocations . clear ( ) ;
lastKnownLocation = null ;
stop ( true ) ;
}
} ) ;
}
protected void addSharingLocation ( long did , int mid , int period , TLRPC . Message message ) {
final SharingLocationInfo info = new SharingLocationInfo ( ) ;
info . did = did ;
info . mid = mid ;
info . period = period ;
2018-07-30 04:07:02 +02:00
info . messageObject = new MessageObject ( currentAccount , message , false ) ;
info . stopTime = ConnectionsManager . getInstance ( currentAccount ) . getCurrentTime ( ) + period ;
final SharingLocationInfo old = sharingLocationsMap . get ( did ) ;
sharingLocationsMap . put ( did , info ) ;
2017-12-08 18:35:59 +01:00
if ( old ! = null ) {
sharingLocations . remove ( old ) ;
}
sharingLocations . add ( info ) ;
saveSharingLocation ( info , 0 ) ;
lastLocationSendTime = System . currentTimeMillis ( ) - BACKGROUD_UPDATE_TIME + 5000 ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
if ( old ! = null ) {
sharingLocationsUI . remove ( old ) ;
}
sharingLocationsUI . add ( info ) ;
sharingLocationsMapUI . put ( info . did , info ) ;
startService ( ) ;
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsChanged ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
}
public boolean isSharingLocation ( long did ) {
2018-07-30 04:07:02 +02:00
return sharingLocationsMapUI . indexOfKey ( did ) > = 0 ;
2017-12-08 18:35:59 +01:00
}
public SharingLocationInfo getSharingLocationInfo ( long did ) {
return sharingLocationsMapUI . get ( did ) ;
}
private void loadSharingLocations ( ) {
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
2017-12-08 18:35:59 +01:00
@Override
public void run ( ) {
final ArrayList < SharingLocationInfo > result = new ArrayList < > ( ) ;
final ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
final ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
try {
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
SQLiteCursor cursor = MessagesStorage . getInstance ( currentAccount ) . getDatabase ( ) . queryFinalized ( " SELECT uid, mid, date, period, message FROM sharing_locations WHERE 1 " ) ;
2017-12-08 18:35:59 +01:00
while ( cursor . next ( ) ) {
SharingLocationInfo info = new SharingLocationInfo ( ) ;
info . did = cursor . longValue ( 0 ) ;
info . mid = cursor . intValue ( 1 ) ;
info . stopTime = cursor . intValue ( 2 ) ;
info . period = cursor . intValue ( 3 ) ;
NativeByteBuffer data = cursor . byteBufferValue ( 4 ) ;
if ( data ! = null ) {
2018-07-30 04:07:02 +02:00
info . messageObject = new MessageObject ( currentAccount , TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) , false ) ;
2017-12-08 18:35:59 +01:00
MessagesStorage . addUsersAndChatsFromMessage ( info . messageObject . messageOwner , usersToLoad , chatsToLoad ) ;
data . reuse ( ) ;
}
result . add ( info ) ;
int lower_id = ( int ) info . did ;
int high_id = ( int ) ( info . did > > 32 ) ;
if ( lower_id ! = 0 ) {
if ( lower_id < 0 ) {
if ( ! chatsToLoad . contains ( - lower_id ) ) {
chatsToLoad . add ( - lower_id ) ;
}
} else {
if ( ! usersToLoad . contains ( lower_id ) ) {
usersToLoad . add ( lower_id ) ;
}
}
} else {
/ * if ( ! encryptedChatIds . contains ( high_id ) ) {
encryptedChatIds . add ( high_id ) ;
} * /
}
}
cursor . dispose ( ) ;
if ( ! chatsToLoad . isEmpty ( ) ) {
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , chats ) ;
2017-12-08 18:35:59 +01:00
}
if ( ! usersToLoad . isEmpty ( ) ) {
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
2017-12-08 18:35:59 +01:00
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
if ( ! result . isEmpty ( ) ) {
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
2018-07-30 04:07:02 +02:00
MessagesController . getInstance ( currentAccount ) . putUsers ( users , true ) ;
MessagesController . getInstance ( currentAccount ) . putChats ( chats , true ) ;
2017-12-08 18:35:59 +01:00
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
sharingLocations . addAll ( result ) ;
for ( int a = 0 ; a < sharingLocations . size ( ) ; a + + ) {
SharingLocationInfo info = sharingLocations . get ( a ) ;
sharingLocationsMap . put ( info . did , info ) ;
}
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
sharingLocationsUI . addAll ( result ) ;
for ( int a = 0 ; a < result . size ( ) ; a + + ) {
SharingLocationInfo info = result . get ( a ) ;
sharingLocationsMapUI . put ( info . did , info ) ;
}
startService ( ) ;
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsChanged ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
}
} ) ;
}
} ) ;
}
}
} ) ;
}
private void saveSharingLocation ( final SharingLocationInfo info , final int remove ) {
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
2017-12-08 18:35:59 +01:00
@Override
public void run ( ) {
try {
if ( remove = = 2 ) {
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . getDatabase ( ) . executeFast ( " DELETE FROM sharing_locations WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
2017-12-08 18:35:59 +01:00
} else if ( remove = = 1 ) {
if ( info = = null ) {
return ;
}
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . getDatabase ( ) . executeFast ( " DELETE FROM sharing_locations WHERE uid = " + info . did ) . stepThis ( ) . dispose ( ) ;
2017-12-08 18:35:59 +01:00
} else {
if ( info = = null ) {
return ;
}
2018-07-30 04:07:02 +02:00
SQLitePreparedStatement state = MessagesStorage . getInstance ( currentAccount ) . getDatabase ( ) . executeFast ( " REPLACE INTO sharing_locations VALUES(?, ?, ?, ?, ?) " ) ;
2017-12-08 18:35:59 +01:00
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( info . messageObject . messageOwner . getObjectSize ( ) ) ;
info . messageObject . messageOwner . serializeToStream ( data ) ;
state . bindLong ( 1 , info . did ) ;
state . bindInteger ( 2 , info . mid ) ;
state . bindInteger ( 3 , info . stopTime ) ;
state . bindInteger ( 4 , info . period ) ;
state . bindByteBuffer ( 5 , data ) ;
state . step ( ) ;
state . dispose ( ) ;
data . reuse ( ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
} ) ;
}
public void removeSharingLocation ( final long did ) {
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2018-07-30 04:07:02 +02:00
final SharingLocationInfo info = sharingLocationsMap . get ( did ) ;
sharingLocationsMap . remove ( did ) ;
2017-12-08 18:35:59 +01:00
if ( info ! = null ) {
TLRPC . TL_messages_editMessage req = new TLRPC . TL_messages_editMessage ( ) ;
2018-07-30 04:07:02 +02:00
req . peer = MessagesController . getInstance ( currentAccount ) . getInputPeer ( ( int ) info . did ) ;
2017-12-08 18:35:59 +01:00
req . id = info . mid ;
req . stop_geo_live = true ;
2018-07-30 04:07:02 +02:00
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , new RequestDelegate ( ) {
2017-12-08 18:35:59 +01:00
@Override
public void run ( TLObject response , TLRPC . TL_error error ) {
if ( error ! = null ) {
return ;
}
2018-07-30 04:07:02 +02:00
MessagesController . getInstance ( currentAccount ) . processUpdates ( ( TLRPC . Updates ) response , false ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
sharingLocations . remove ( info ) ;
saveSharingLocation ( info , 1 ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
sharingLocationsUI . remove ( info ) ;
sharingLocationsMapUI . remove ( info . did ) ;
if ( sharingLocationsUI . isEmpty ( ) ) {
stopService ( ) ;
}
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsChanged ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
if ( sharingLocations . isEmpty ( ) ) {
stop ( true ) ;
}
}
}
} ) ;
}
private void startService ( ) {
2018-07-30 04:07:02 +02:00
try {
/ * if ( Build . VERSION . SDK_INT > = 26 ) {
ApplicationLoader . applicationContext . startForegroundService ( new Intent ( ApplicationLoader . applicationContext , LocationSharingService . class ) ) ;
} else { * /
ApplicationLoader . applicationContext . startService ( new Intent ( ApplicationLoader . applicationContext , LocationSharingService . class ) ) ;
//}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
}
2017-12-08 18:35:59 +01:00
}
private void stopService ( ) {
ApplicationLoader . applicationContext . stopService ( new Intent ( ApplicationLoader . applicationContext , LocationSharingService . class ) ) ;
}
public void removeAllLocationSharings ( ) {
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
for ( int a = 0 ; a < sharingLocations . size ( ) ; a + + ) {
SharingLocationInfo info = sharingLocations . get ( a ) ;
TLRPC . TL_messages_editMessage req = new TLRPC . TL_messages_editMessage ( ) ;
2018-07-30 04:07:02 +02:00
req . peer = MessagesController . getInstance ( currentAccount ) . getInputPeer ( ( int ) info . did ) ;
2017-12-08 18:35:59 +01:00
req . id = info . mid ;
req . stop_geo_live = true ;
2018-07-30 04:07:02 +02:00
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , new RequestDelegate ( ) {
2017-12-08 18:35:59 +01:00
@Override
public void run ( TLObject response , TLRPC . TL_error error ) {
if ( error ! = null ) {
return ;
}
2018-07-30 04:07:02 +02:00
MessagesController . getInstance ( currentAccount ) . processUpdates ( ( TLRPC . Updates ) response , false ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
}
sharingLocations . clear ( ) ;
sharingLocationsMap . clear ( ) ;
saveSharingLocation ( null , 2 ) ;
stop ( true ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
sharingLocationsUI . clear ( ) ;
sharingLocationsMapUI . clear ( ) ;
stopService ( ) ;
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsChanged ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
}
} ) ;
}
public void setGoogleMapLocation ( Location location , boolean first ) {
if ( location = = null ) {
return ;
}
lastLocationByGoogleMaps = true ;
if ( first | | lastKnownLocation ! = null & & lastKnownLocation . distanceTo ( location ) > = 20 ) {
lastLocationSendTime = System . currentTimeMillis ( ) - BACKGROUD_UPDATE_TIME ;
locationSentSinceLastGoogleMapUpdate = false ;
} else if ( locationSentSinceLastGoogleMapUpdate ) {
lastLocationSendTime = System . currentTimeMillis ( ) - BACKGROUD_UPDATE_TIME + FOREGROUND_UPDATE_TIME ;
locationSentSinceLastGoogleMapUpdate = false ;
}
lastKnownLocation = location ;
}
private void start ( ) {
if ( started ) {
return ;
}
lastLocationStartTime = System . currentTimeMillis ( ) ;
started = true ;
try {
locationManager . requestLocationUpdates ( LocationManager . GPS_PROVIDER , 1 , 0 , gpsLocationListener ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
try {
locationManager . requestLocationUpdates ( LocationManager . NETWORK_PROVIDER , 1 , 0 , networkLocationListener ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
try {
locationManager . requestLocationUpdates ( LocationManager . PASSIVE_PROVIDER , 1 , 0 , passiveLocationListener ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
if ( lastKnownLocation = = null ) {
try {
lastKnownLocation = locationManager . getLastKnownLocation ( LocationManager . GPS_PROVIDER ) ;
if ( lastKnownLocation = = null ) {
lastKnownLocation = locationManager . getLastKnownLocation ( LocationManager . NETWORK_PROVIDER ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
}
private void stop ( boolean empty ) {
started = false ;
locationManager . removeUpdates ( gpsLocationListener ) ;
if ( empty ) {
locationManager . removeUpdates ( networkLocationListener ) ;
locationManager . removeUpdates ( passiveLocationListener ) ;
}
}
public void loadLiveLocations ( final long did ) {
if ( cacheRequests . indexOfKey ( did ) > = 0 ) {
return ;
}
cacheRequests . put ( did , true ) ;
TLRPC . TL_messages_getRecentLocations req = new TLRPC . TL_messages_getRecentLocations ( ) ;
2018-07-30 04:07:02 +02:00
req . peer = MessagesController . getInstance ( currentAccount ) . getInputPeer ( ( int ) did ) ;
2017-12-08 18:35:59 +01:00
req . limit = 100 ;
2018-07-30 04:07:02 +02:00
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , new RequestDelegate ( ) {
2017-12-08 18:35:59 +01:00
@Override
public void run ( final TLObject response , TLRPC . TL_error error ) {
if ( error ! = null ) {
return ;
}
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
cacheRequests . delete ( did ) ;
TLRPC . messages_Messages res = ( TLRPC . messages_Messages ) response ;
for ( int a = 0 ; a < res . messages . size ( ) ; a + + ) {
if ( ! ( res . messages . get ( a ) . media instanceof TLRPC . TL_messageMediaGeoLive ) ) {
res . messages . remove ( a ) ;
a - - ;
}
}
2018-07-30 04:07:02 +02:00
MessagesStorage . getInstance ( currentAccount ) . putUsersAndChats ( res . users , res . chats , true , true ) ;
MessagesController . getInstance ( currentAccount ) . putUsers ( res . users , false ) ;
MessagesController . getInstance ( currentAccount ) . putChats ( res . chats , false ) ;
2017-12-08 18:35:59 +01:00
locationsCache . put ( did , res . messages ) ;
2018-07-30 04:07:02 +02:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . liveLocationsCacheChanged , did , currentAccount ) ;
2017-12-08 18:35:59 +01:00
}
} ) ;
}
} ) ;
}
2018-07-30 04:07:02 +02:00
public static int getLocationsCount ( ) {
int count = 0 ;
for ( int a = 0 ; a < UserConfig . MAX_ACCOUNT_COUNT ; a + + ) {
count + = LocationController . getInstance ( a ) . sharingLocationsUI . size ( ) ;
}
return count ;
}
2017-12-08 18:35:59 +01:00
}