Start app on system launch, NotificationsService that will keep app running in background, special connection to receive update only about new messages, option to disable NotificationsService

This commit is contained in:
DrKLO 2014-05-21 00:22:44 +04:00
parent ee38ecec56
commit f68ace0fd6
25 changed files with 379 additions and 156 deletions

View File

@ -43,8 +43,6 @@
<uses-library android:name="com.google.android.maps" android:required="false"/>
<service android:name=".AwakeService"/>
</application>
</manifest>

View File

@ -43,8 +43,6 @@
<uses-library android:name="com.google.android.maps" android:required="false"/>
<service android:name=".AwakeService"/>
</application>
</manifest>

View File

@ -38,6 +38,7 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="false"
@ -144,6 +145,15 @@
android:resource="@xml/contacts" />
</service>
<service android:name="org.telegram.messenger.NotificationsService" android:enabled="true"/>
<receiver android:name="org.telegram.messenger.AppStartReceiver" android:enabled="true">
<intent-filter>
<action android:name="org.telegram.start" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@ -0,0 +1,26 @@
/*
* This is the source code of Telegram for Android v. 1.4.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-2014.
*/
package org.telegram.messenger;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.telegram.ui.ApplicationLoader;
public class AppStartReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
ApplicationLoader.startPushService();
}
});
}
}

View File

@ -1,68 +0,0 @@
/*
* This is the source code of Telegram for Android v. 1.3.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-2014.
*/
package org.telegram.messenger;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import org.telegram.ui.ApplicationLoader;
public class AwakeService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
public static volatile int timeout = 10000;
public static boolean isStarted = false;
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void onCreate() {
super.onCreate();
FileLog.e("tmessages", "service started");
check();
isStarted = true;
}
public static void startService() {
try {
if (ApplicationLoader.isScreenOn && ApplicationLoader.lastPauseTime == 0) {
return;
}
timeout = 10000;
if (!isStarted) {
ApplicationLoader.applicationContext.startService(new Intent(ApplicationLoader.applicationContext, AwakeService.class));
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
private void check() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
ApplicationLoader.postInitApplication();
timeout -= 1000;
if (timeout <= 0) {
stopSelf();
isStarted = false;
FileLog.e("tmessages", "service stoped");
} else {
check();
}
}
}, 1000);
}
}

View File

@ -40,6 +40,10 @@ public class ConnectionContext extends PyroClientAdapter {
sessionId = isDebugSession ? (0xabcd000000000000L | (newSessionId & 0x0000ffffffffffffL)) : newSessionId;
}
public void setSessionId(long id) {
sessionId = id;
}
public long getSissionId() {
return sessionId;
}

View File

@ -60,13 +60,15 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
private int updatingDcStartTime = 0;
private int lastDcUpdateTime = 0;
private int currentAppVersion = 0;
private long pushSessionId;
private boolean registeringForPush = false;
private boolean paused = false;
private Runnable stageRunnable;
private Runnable pingRunnable;
private long lastPingTime = System.currentTimeMillis();
private int nextWakeUpTimeout = 60000;
private int nextSleepTimeout = 60000;
private long lastPushPingTime = System.currentTimeMillis();
private int nextSleepTimeout = 30000;
private static volatile ConnectionsManager Instance = null;
public static ConnectionsManager getInstance() {
@ -99,6 +101,16 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (datacenters != null) {
if (lastPushPingTime < System.currentTimeMillis() - 29000) {
lastPushPingTime = System.currentTimeMillis();
Datacenter datacenter = datacenterWithId(currentDatacenterId);
if (datacenter != null) {
generatePing(datacenter, true);
}
}
}
long currentTime = System.currentTimeMillis();
if (ApplicationLoader.lastPauseTime != 0 && ApplicationLoader.lastPauseTime < currentTime - nextSleepTimeout) {
boolean dontSleep = false;
@ -133,17 +145,8 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
}
try {
paused = true;
if (ApplicationLoader.lastPauseTime < currentTime - nextSleepTimeout - nextWakeUpTimeout) {
ApplicationLoader.lastPauseTime = currentTime;
nextSleepTimeout = 30000;
FileLog.e("tmessages", "wakeup network in background by wakeup time = " + nextWakeUpTimeout);
if (nextWakeUpTimeout < 30 * 60 * 1000) {
nextWakeUpTimeout *= 2;
}
} else {
Thread.sleep(500);
return;
}
Thread.sleep(500);
return;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
@ -182,7 +185,6 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
public void run() {
if (paused) {
ApplicationLoader.lastPauseTime = System.currentTimeMillis();
nextWakeUpTimeout = 60000;
nextSleepTimeout = 30000;
FileLog.e("tmessages", "wakeup network in background by recieved push");
} else if (ApplicationLoader.lastPauseTime != 0) {
@ -198,8 +200,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
@Override
public void run() {
if (paused) {
nextSleepTimeout = 60000;
nextWakeUpTimeout = 60000;
nextSleepTimeout = 30000;
FileLog.e("tmessages", "reset timers by application moved to foreground");
}
}
@ -279,6 +280,8 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
currentDatacenterId = preferences.getInt("currentDatacenterId", 0);
timeDifference = preferences.getInt("timeDifference", 0);
lastDcUpdateTime = preferences.getInt("lastDcUpdateTime", 0);
pushSessionId = preferences.getLong("pushSessionId", 0);
try {
sessionsToDestroy.clear();
String sessionsString = preferences.getString("sessionsToDestroy", null);
@ -325,8 +328,13 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
fillDatacenters();
if (datacenters.size() != 0 && currentDatacenterId == 0) {
currentDatacenterId = 1;
if (datacenters.size() != 0 && currentDatacenterId == 0 || pushSessionId == 0) {
if (pushSessionId == 0) {
pushSessionId = Utilities.random.nextLong();
}
if (currentDatacenterId == 0) {
currentDatacenterId = 1;
}
saveSession();
}
movingToDatacenterId = DEFAULT_DATACENTER_ID;
@ -413,6 +421,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
editor.putInt("currentDatacenterId", currentDatacenterId);
editor.putInt("timeDifference", timeDifference);
editor.putInt("lastDcUpdateTime", lastDcUpdateTime);
editor.putLong("pushSessionId", pushSessionId);
ArrayList<Long> sessions = new ArrayList<Long>();
if (currentDatacenter.connection != null) {
@ -592,6 +601,29 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
});
}
public void initPushConnection() {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
Datacenter datacenter = datacenterWithId(currentDatacenterId);
if (datacenter != null) {
if (datacenter.pushConnection == null) {
datacenter.pushConnection = new TcpConnection(datacenter.datacenterId);
datacenter.pushConnection.setSessionId(pushSessionId);
datacenter.pushConnection.delegate = ConnectionsManager.this;
datacenter.pushConnection.transportRequestClass = RPCRequest.RPCRequestClassPush;
datacenter.pushConnection.connect();
generatePing(datacenter, true);
} else {
if (UserConfig.clientActivated && !UserConfig.registeredForInternalPush) {
registerForPush();
}
}
}
}
});
}
public void applyCountryPortNumber(final String phone) {
if (phone == null || phone.length() == 0) {
return;
@ -1097,12 +1129,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
request.transportChannelToken = datacenterDownloadTransportToken;
ArrayList<NetworkMessage> arr = new ArrayList<NetworkMessage>();
arr.add(networkMessage);
proceedToSendingMessages(arr, connection, false, false);
proceedToSendingMessages(arr, connection, false);
} else if ((request.flags & RPCRequest.RPCRequestClassUploadMedia) != 0) {
request.transportChannelToken = datacenterUploadTransportToken;
ArrayList<NetworkMessage> arr = new ArrayList<NetworkMessage>();
arr.add(networkMessage);
proceedToSendingMessages(arr, connection, false, false);
proceedToSendingMessages(arr, connection, false);
}
}
}
@ -1299,11 +1331,11 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
} else if ((request.flags & RPCRequest.RPCRequestClassDownloadMedia) != 0) {
ArrayList<NetworkMessage> arr = new ArrayList<NetworkMessage>();
arr.add(networkMessage);
proceedToSendingMessages(arr, requestDatacenter.downloadConnection, false, false);
proceedToSendingMessages(arr, requestDatacenter.downloadConnection, false);
} else if ((request.flags & RPCRequest.RPCRequestClassUploadMedia) != 0) {
ArrayList<NetworkMessage> arr = new ArrayList<NetworkMessage>();
arr.add(networkMessage);
proceedToSendingMessages(arr, requestDatacenter.uploadConnection, false, false);
proceedToSendingMessages(arr, requestDatacenter.uploadConnection, false);
} else {
FileLog.e("tmessages", "***** Error: request " + request.rawRequest + " has undefined session");
}
@ -1394,7 +1426,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
datacenter.connection.transportRequestClass = RPCRequest.RPCRequestClassGeneric;
}
proceedToSendingMessages(arr, datacenter.connection, hasSendMessage, arr.size() != 0);
proceedToSendingMessages(arr, datacenter.connection, hasSendMessage);
}
}
@ -1403,7 +1435,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
for (Datacenter datacenter : datacenters.values()) {
ArrayList<NetworkMessage> messagesIt = genericMessagesToDatacenters.get(datacenter.datacenterId);
if (messagesIt == null || messagesIt.size() == 0) {
generatePing(datacenter);
generatePing(datacenter, false);
}
}
} else {
@ -1485,7 +1517,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
}
}
void proceedToSendingMessages(ArrayList<NetworkMessage> messageList, TcpConnection connection, boolean reportAck, boolean requestShortTimeout) {
void proceedToSendingMessages(ArrayList<NetworkMessage> messageList, TcpConnection connection, boolean reportAck) {
if (connection.getSissionId() == 0) {
return;
}
@ -1500,10 +1532,10 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
messages.add(message);
}
sendMessagesToTransport(messages, connection, reportAck, requestShortTimeout);
sendMessagesToTransport(messages, connection, reportAck);
}
void sendMessagesToTransport(ArrayList<NetworkMessage> messagesToSend, TcpConnection connection, boolean reportAck, boolean requestShortTimeout) {
void sendMessagesToTransport(ArrayList<NetworkMessage> messagesToSend, TcpConnection connection, boolean reportAck) {
if (messagesToSend.size() == 0) {
return;
}
@ -1548,7 +1580,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
}
}
connection.sendData(null, transportData, reportAck, requestShortTimeout);
connection.sendData(null, transportData, reportAck);
} else {
FileLog.e("tmessages", "***** Transport data is nil");
}
@ -1750,6 +1782,67 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
});
}
private void registerForPush() {
if (registeringForPush) {
return;
}
UserConfig.registeredForInternalPush = false;
UserConfig.saveConfig(false);
registeringForPush = true;
TLRPC.TL_account_registerDevice req = new TLRPC.TL_account_registerDevice();
req.token_type = 7;
req.token = "" + pushSessionId;
req.app_sandbox = false;
try {
req.lang_code = Locale.getDefault().getCountry();
req.device_model = Build.MANUFACTURER + Build.MODEL;
if (req.device_model == null) {
req.device_model = "Android unknown";
}
req.system_version = "SDK " + Build.VERSION.SDK_INT;
PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0);
req.app_version = pInfo.versionName;
if (req.app_version == null) {
req.app_version = "App version unknown";
}
} catch (Exception e) {
FileLog.e("tmessages", e);
req.lang_code = "en";
req.device_model = "Android unknown";
req.system_version = "SDK " + Build.VERSION.SDK_INT;
req.app_version = "App version unknown";
}
if (req.lang_code == null || req.lang_code.length() == 0) {
req.lang_code = "en";
}
if (req.device_model == null || req.device_model.length() == 0) {
req.device_model = "Android unknown";
}
if (req.app_version == null || req.app_version.length() == 0) {
req.app_version = "App version unknown";
}
if (req.system_version == null || req.system_version.length() == 0) {
req.system_version = "SDK Unknown";
}
if (req.app_version != null) {
ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
UserConfig.registeredForInternalPush = true;
UserConfig.saveConfig(false);
saveSession();
FileLog.e("tmessages", "registered for internal push");
}
registeringForPush = false;
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
}
void processMessage(TLObject message, long messageId, int messageSeqNo, long messageSalt, TcpConnection connection, long innerMsgId, long containerMessageId) {
if (message == null) {
FileLog.e("tmessages", "message is null");
@ -1787,8 +1880,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
saveSession();
if ((connection.transportRequestClass & RPCRequest.RPCRequestClassGeneric) != 0 && datacenter.datacenterId == currentDatacenterId && UserConfig.clientActivated) {
MessagesController.getInstance().getDifference();
if (datacenter.datacenterId == currentDatacenterId && UserConfig.clientActivated) {
if ((connection.transportRequestClass & RPCRequest.RPCRequestClassGeneric) != 0) {
MessagesController.getInstance().getDifference();
} else if ((connection.transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
registerForPush();
}
}
connection.addProcessedSession(newSession.unique_id);
}
@ -1812,6 +1909,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
connection.addProcessedMessageId(innerMessageId);
}
} else if (message instanceof TLRPC.TL_pong) {
if (UserConfig.clientActivated && !UserConfig.registeredForInternalPush && (connection.transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
registerForPush();
}
TLRPC.TL_pong pong = (TLRPC.TL_pong)message;
long pingId = pong.ping_id;
@ -2168,7 +2268,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
ArrayList<NetworkMessage> arr = new ArrayList<NetworkMessage>();
arr.add(networkMessage);
sendMessagesToTransport(arr, connection, false, true);
sendMessagesToTransport(arr, connection, false);
} else {
connection.addMessageToConfirm(detailedInfo.answer_msg_id);
}
@ -2177,52 +2277,55 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
TLObject result = Utilities.decompress(packet.packed_data, getRequestWithMessageId(messageId));
processMessage(result, messageId, messageSeqNo, messageSalt, connection, innerMsgId, containerMessageId);
} else if (message instanceof TLRPC.Updates) {
MessagesController.getInstance().processUpdates((TLRPC.Updates)message, false);
if ((connection.transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
FileLog.e("tmessages", "received internal push");
resumeNetworkMaybe();
} else {
MessagesController.getInstance().processUpdates((TLRPC.Updates) message, false);
}
} else {
FileLog.e("tmessages", "***** Error: unknown message class " + message);
}
}
void generatePing() {
for (Datacenter datacenter : datacenters.values()) {
if (datacenter.datacenterId == currentDatacenterId) {
generatePing(datacenter);
}
Datacenter datacenter = datacenterWithId(currentDatacenterId);
if (datacenter != null) {
generatePing(datacenter, false);
}
}
static long nextPingId = 0;
ByteBufferDesc generatePingData(Datacenter datacenter, boolean recordTime) {
if (datacenter.connection == null) {
datacenter.connection = new TcpConnection(datacenter.datacenterId);
datacenter.connection.delegate = this;
datacenter.connection.transportRequestClass = RPCRequest.RPCRequestClassGeneric;
private ByteBufferDesc generatePingData(TcpConnection connection) {
if (connection == null) {
return null;
}
TLRPC.TL_ping_delay_disconnect ping = new TLRPC.TL_ping_delay_disconnect();
ping.ping_id = nextPingId++;
ping.disconnect_delay = 35;
if (recordTime) {
pingIdToDate.put(ping.ping_id, (int)(System.currentTimeMillis() / 1000));
}
pingIdToDate.put(ping.ping_id, (int)(System.currentTimeMillis() / 1000));
NetworkMessage networkMessage = new NetworkMessage();
networkMessage.protoMessage = wrapMessage(ping, datacenter.connection, false);
networkMessage.protoMessage = wrapMessage(ping, connection, false);
ArrayList<NetworkMessage> arr = new ArrayList<NetworkMessage>();
arr.add(networkMessage);
return createConnectionData(arr, null, datacenter.connection);
return createConnectionData(arr, null, connection);
}
void generatePing(Datacenter datacenter) {
if (datacenter.connection == null || datacenter.connection.channelToken == 0) {
return;
void generatePing(Datacenter datacenter, boolean push) {
TcpConnection connection = null;
if (push) {
connection = datacenter.pushConnection;
} else {
connection = datacenter.connection;
}
ByteBufferDesc transportData = generatePingData(datacenter, true);
if (transportData != null) {
datacenter.connection.sendData(null, transportData, false, true);
if (connection != null && (push || !push && connection.channelToken != 0)) {
ByteBufferDesc transportData = generatePingData(connection);
if (transportData != null) {
connection.sendData(null, transportData, false);
}
}
}
@ -2539,9 +2642,18 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
} else {
processMessage(message, messageId, messageSeqNo, messageServerSalt, connection, 0, 0);
connection.addProcessedMessageId(messageId);
if ((connection.transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
ArrayList<NetworkMessage> messages = new ArrayList<NetworkMessage>();
NetworkMessage networkMessage = connection.generateConfirmationRequest();
if (networkMessage != null) {
messages.add(networkMessage);
}
sendMessagesToTransport(messages, connection, false);
}
}
} else {
proceedToSendingMessages(null, connection, false, false);
proceedToSendingMessages(null, connection, false);
}
finishUpdatingState(connection);
}

View File

@ -37,6 +37,7 @@ public class Datacenter {
public TcpConnection connection;
public TcpConnection downloadConnection;
public TcpConnection uploadConnection;
public TcpConnection pushConnection;
private ArrayList<ServerSalt> authServerSaltSet = new ArrayList<ServerSalt>();

View File

@ -49,8 +49,6 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
}
}
AwakeService.startService();
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {

View File

@ -179,7 +179,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
byte[] transportData = messageOs.toByteArray();
datacenter.connection.sendData(transportData, null, false, false);
datacenter.connection.sendData(transportData, null, false);
return transportData;
}
@ -576,11 +576,11 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
return;
}
if (reqPQMsgData != null) {
datacenter.connection.sendData(reqPQMsgData, null, false, false);
datacenter.connection.sendData(reqPQMsgData, null, false);
} else if (reqDHMsgData != null) {
datacenter.connection.sendData(reqDHMsgData, null, false, false);
datacenter.connection.sendData(reqDHMsgData, null, false);
} else if (setClientDHParamsMsgData != null) {
datacenter.connection.sendData(setClientDHParamsMsgData, null, false, false);
datacenter.connection.sendData(setClientDHParamsMsgData, null, false);
}
}

View File

@ -60,6 +60,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public SparseArray<MessageObject> dialogMessage = new SparseArray<MessageObject>();
public ConcurrentHashMap<Long, ArrayList<PrintingUser>> printingUsers = new ConcurrentHashMap<Long, ArrayList<PrintingUser>>(100, 1.0f, 2);
public HashMap<Long, CharSequence> printingStrings = new HashMap<Long, CharSequence>();
private int lastPrintingStringCount = 0;
private HashMap<String, ArrayList<DelayedMessage>> delayedMessages = new HashMap<String, ArrayList<DelayedMessage>>();
public SparseArray<MessageObject> sendingMessages = new SparseArray<MessageObject>();
@ -291,6 +292,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
printingUsers.clear();
printingStrings.clear();
totalDialogsCount = 0;
lastPrintingStringCount = 0;
hidenAddToContacts.clear();
updatesQueue.clear();
pendingEncMessagesToDelete.clear();
@ -821,7 +823,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
} else {
scheduleContactsReload = 0;
}
if (!printingUsers.isEmpty()) {
if (!printingUsers.isEmpty() || lastPrintingStringCount != printingUsers.size()) {
boolean updated = false;
ArrayList<Long> keys = new ArrayList<Long>(printingUsers.keySet());
for (int b = 0; b < keys.size(); b++) {
@ -893,6 +895,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
lastPrintingStringCount = newPrintingStrings.size();
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
@ -3667,7 +3671,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
final ArrayList<Integer> markAsReadMessages = new ArrayList<Integer>();
final HashMap<Integer, Integer> markAsReadEncrypted = new HashMap<Integer, Integer>();
final ArrayList<Integer> deletedMessages = new ArrayList<Integer>();
final ArrayList<Long> printChanges = new ArrayList<Long>();
boolean printChanged = false;
final ArrayList<TLRPC.ChatParticipants> chatInfoToUpdate = new ArrayList<TLRPC.ChatParticipants>();
final ArrayList<TLRPC.Update> updatesOnMainThread = new ArrayList<TLRPC.Update>();
final ArrayList<TLRPC.TL_updateEncryptedMessagesRead> tasks = new ArrayList<TLRPC.TL_updateEncryptedMessagesRead>();
@ -3789,9 +3793,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newUser.userId = update.user_id;
newUser.lastTime = currentTime;
arr.add(newUser);
if (!printChanges.contains(uid)) {
printChanges.add(uid);
}
printChanged = true;
}
}
} else if (update instanceof TLRPC.TL_updateChatParticipants) {
@ -3959,9 +3961,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newUser.userId = update.user_id;
newUser.lastTime = currentTime;
arr.add(newUser);
if (!printChanges.contains(uid)) {
printChanges.add(uid);
}
printChanged = true;
}
} else if (update instanceof TLRPC.TL_updateEncryptedMessagesRead) {
markAsReadEncrypted.put(update.chat_id, Math.max(update.max_date, update.date));
@ -4067,19 +4067,19 @@ public class MessagesController implements NotificationCenter.NotificationCenter
for (HashMap.Entry<Long, ArrayList<MessageObject>> pair : messages.entrySet()) {
Long key = pair.getKey();
ArrayList<MessageObject> value = pair.getValue();
boolean printChanged = updatePrintingUsersWithNewMessages(key, value);
if (printChanged && !printChanges.contains(key)) {
printChanges.add(key);
if (updatePrintingUsersWithNewMessages(key, value)) {
printChanged = true;
}
}
}
if (!printChanges.isEmpty()) {
if (printChanged) {
updatePrintingStrings();
}
final MessageObject lastMessageArg = lastMessage;
final int interfaceUpdateMaskFinal = interfaceUpdateMask;
final boolean printChangedArg = printChanged;
processPendingEncMessages();
@ -4091,7 +4091,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
MessagesStorage.getInstance().putMessages(messagesArr, true, true);
}
if (!messages.isEmpty() || !markAsReadMessages.isEmpty() || !deletedMessages.isEmpty() || !printChanges.isEmpty() || !chatInfoToUpdate.isEmpty() || !updatesOnMainThread.isEmpty() || !markAsReadEncrypted.isEmpty() || !contactsIds.isEmpty()) {
if (!messages.isEmpty() || !markAsReadMessages.isEmpty() || !deletedMessages.isEmpty() || printChanged || !chatInfoToUpdate.isEmpty() || !updatesOnMainThread.isEmpty() || !markAsReadEncrypted.isEmpty() || !contactsIds.isEmpty()) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
@ -4179,7 +4179,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
}
if (!printChanges.isEmpty()) {
if (printChangedArg) {
updateMask |= UPDATE_MASK_USER_PRINT;
}
if (!contactsIds.isEmpty()) {
@ -4508,15 +4508,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter
needVibrate = false;
}
String name = Utilities.formatName(user.first_name, user.last_name);
String msgShort = msg.replace(name + ": ", "").replace(name + " ", "");
intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
intent.setFlags(32768);
PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ApplicationLoader.applicationContext)
.setContentTitle(LocaleController.getString("AppName", R.string.AppName))
.setContentTitle(name)
.setSmallIcon(R.drawable.notification)
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setStyle(new NotificationCompat.BigTextStyle().bigText(msgShort))
.setContentText(msgShort)
.setAutoCancel(true)
.setTicker(msg);

View File

@ -0,0 +1,45 @@
/*
* This is the source code of Telegram for Android v. 1.3.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-2014.
*/
package org.telegram.messenger;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import org.telegram.ui.ApplicationLoader;
public class NotificationsService extends Service {
@Override
public void onCreate() {
FileLog.e("tmessages", "service started");
ApplicationLoader.postInitApplication();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
FileLog.e("tmessages", "service destroyed");
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
if (preferences.getBoolean("pushService", true)) {
Intent intent = new Intent("org.telegram.start");
sendBroadcast(intent);
}
}
}

View File

@ -27,6 +27,7 @@ public class RPCRequest {
public static int RPCRequestClassEnableUnauthorized = 8;
public static int RPCRequestClassFailOnServerErrors = 16;
public static int RPCRequestClassCanCompress = 32;
public static int RPCRequestClassPush = 64;
static int RPCRequestClassTransportMask = (RPCRequestClassGeneric | RPCRequestClassDownloadMedia | RPCRequestClassUploadMedia);

View File

@ -127,10 +127,18 @@ public class TcpConnection extends ConnectionContext {
}
client = selector.connect(new InetSocketAddress(hostAddress, hostPort));
client.addListener(TcpConnection.this);
if (isNextPort) {
client.setTimeout(8000);
if ((transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
if (isNextPort) {
client.setTimeout(15000);
} else {
client.setTimeout(30000);
}
} else {
client.setTimeout(15000);
if (isNextPort) {
client.setTimeout(8000);
} else {
client.setTimeout(15000);
}
}
selector.wakeup();
} catch (Exception e) {
@ -270,7 +278,7 @@ public class TcpConnection extends ConnectionContext {
connect();
}
public void sendData(final byte[] data, final ByteBufferDesc buff, final boolean reportAck, final boolean startResponseTimeout) {
public void sendData(final byte[] data, final ByteBufferDesc buff, final boolean reportAck) {
if (data == null && buff == null) {
return;
}
@ -408,7 +416,11 @@ public class TcpConnection extends ConnectionContext {
Datacenter datacenter = ConnectionsManager.getInstance().datacenterWithId(datacenterId);
datacenter.storeCurrentAddressAndPortNum();
isNextPort = false;
client.setTimeout(25000);
if ((transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
client.setTimeout(40000);
} else {
client.setTimeout(25000);
}
}
hasSomeDataSinceLastConnect = true;

View File

@ -21,6 +21,7 @@ public class UserConfig {
public static int clientUserId = 0;
public static boolean clientActivated = false;
public static boolean registeredForPush = false;
public static boolean registeredForInternalPush = false;
public static String pushString = "";
public static int lastSendMessageId = -210000;
public static int lastLocalId = -210000;
@ -56,6 +57,7 @@ public class UserConfig {
editor.putString("importHash", importHash);
editor.putBoolean("saveIncomingPhotos", saveIncomingPhotos);
editor.putInt("contactsVersion", contactsVersion);
editor.putBoolean("registeredForInternalPush", registeredForInternalPush);
if (currentUser != null) {
if (withFile) {
SerializedData data = new SerializedData();
@ -155,6 +157,7 @@ public class UserConfig {
importHash = preferences.getString("importHash", "");
saveIncomingPhotos = preferences.getBoolean("saveIncomingPhotos", false);
contactsVersion = preferences.getInt("contactsVersion", 0);
registeredForInternalPush = preferences.getBoolean("registeredForInternalPush", false);
String user = preferences.getString("user", null);
if (user != null) {
byte[] userBytes = Base64.decode(user, Base64.DEFAULT);
@ -177,6 +180,7 @@ public class UserConfig {
clientUserId = 0;
clientActivated = false;
currentUser = null;
registeredForInternalPush = false;
registeredForPush = false;
contactsHash = "";
importHash = "";

View File

@ -9,7 +9,9 @@
package org.telegram.ui;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -28,6 +30,7 @@ import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.telegram.messenger.NotificationsService;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
@ -41,6 +44,7 @@ import org.telegram.ui.Views.BaseFragment;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;
public class ApplicationLoader extends Application {
@ -125,10 +129,12 @@ public class ApplicationLoader extends Application {
MessagesController.getInstance().users.put(UserConfig.clientUserId, UserConfig.currentUser);
ConnectionsManager.getInstance().applyCountryPortNumber(UserConfig.currentUser.phone);
ConnectionsManager.getInstance().initPushConnection();
}
ApplicationLoader app = (ApplicationLoader)ApplicationLoader.applicationContext;
app.initPlayServices();
FileLog.e("tmessages", "app initied");
}
@Override
@ -152,6 +158,31 @@ public class ApplicationLoader extends Application {
} catch (Exception e) {
e.printStackTrace();
}
startPushService();
}
public static void startPushService() {
SharedPreferences preferences = applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
if (preferences.getBoolean("pushService", true)) {
applicationContext.startService(new Intent(applicationContext, NotificationsService.class));
Calendar cal = Calendar.getInstance();
PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0);
AlarmManager alarm = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30000, pintent);
} else {
stopPushService();
}
}
public static void stopPushService() {
applicationContext.stopService(new Intent(applicationContext, NotificationsService.class));
PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0);
AlarmManager alarm = (AlarmManager)applicationContext.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pintent);
}
@Override

View File

@ -158,6 +158,7 @@ public class LoginActivityRegisterView extends SlideView {
if (delegate != null) {
delegate.needFinishActivity();
}
ConnectionsManager.getInstance().initPushConnection();
}
});
} else {

View File

@ -241,6 +241,7 @@ public class LoginActivitySmsView extends SlideView implements NotificationCente
if (delegate != null) {
delegate.needFinishActivity();
}
ConnectionsManager.getInstance().initPushConnection();
}
});
} else {

View File

@ -9,7 +9,9 @@
package org.telegram.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.Ringtone;
@ -46,6 +48,7 @@ public class SettingsNotificationsActivity extends BaseFragment {
private ListView listView;
private boolean reseting = false;
private int notificationsServiceRow;
private int messageSectionRow;
private int messageAlertRow;
private int messagePreviewRow;
@ -70,6 +73,7 @@ public class SettingsNotificationsActivity extends BaseFragment {
@Override
public boolean onFragmentCreate() {
notificationsServiceRow = rowCount++;
messageSectionRow = rowCount++;
messageAlertRow = rowCount++;
messagePreviewRow = rowCount++;
@ -260,6 +264,32 @@ public class SettingsNotificationsActivity extends BaseFragment {
editor.putBoolean("EnablePebbleNotifications", !enabled);
editor.commit();
listView.invalidateViews();
} else if (i == notificationsServiceRow) {
final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
boolean enabled = preferences.getBoolean("pushService", true);
if (!enabled) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("pushService", !enabled);
editor.commit();
listView.invalidateViews();
ApplicationLoader.startPushService();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity);
builder.setMessage(LocaleController.getString("NotificationsServiceDisableInfo", R.string.NotificationsServiceDisableInfo));
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ApplicationLoader.stopPushService();
final SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("pushService", false);
editor.commit();
listView.invalidateViews();
}
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
builder.show().setCanceledOnTouchOutside(true);
}
}
}
});
@ -492,6 +522,10 @@ public class SettingsNotificationsActivity extends BaseFragment {
enabled = preferences.getBoolean("EnablePebbleNotifications", false);
textView.setText(LocaleController.getString("Alert", R.string.Alert));
divider.setVisibility(View.INVISIBLE);
} else if (i == notificationsServiceRow) {
enabled = preferences.getBoolean("pushService", true);
textView.setText(LocaleController.getString("NotificationsService", R.string.NotificationsService));
divider.setVisibility(View.INVISIBLE);
}
if (enabled) {
checkButton.setImageResource(R.drawable.btn_check_on);
@ -542,7 +576,7 @@ public class SettingsNotificationsActivity extends BaseFragment {
i == groupAlertRow || i == groupPreviewRow || i == groupVibrateRow ||
i == inappSoundRow || i == inappVibrateRow || i == inappPreviewRow ||
i == contactJoinedRow ||
i == pebbleAlertRow) {
i == pebbleAlertRow || i == notificationsServiceRow) {
return 1;
} else {
return 2;

View File

@ -265,6 +265,8 @@
<string name="IncorrectLocalization">Incorrect localization file</string>
<string name="Enabled">Enabled</string>
<string name="Disabled">Disabled</string>
<string name="NotificationsService">Notifications Service</string>
<string name="NotificationsServiceDisableInfo">If google play services are enough for you to receive notifications, you can disable Notifications Service. However we recommend you to leave it enabled to keep app running in background and receive instant notifications.</string>
<!--media view-->
<string name="NoMedia">لا توجد وسائط بعد</string>

View File

@ -265,6 +265,8 @@
<string name="IncorrectLocalization">Falsche Sprachdatei</string>
<string name="Enabled">Enabled</string>
<string name="Disabled">Disabled</string>
<string name="NotificationsService">Notifications Service</string>
<string name="NotificationsServiceDisableInfo">If google play services are enough for you to receive notifications, you can disable Notifications Service. However we recommend you to leave it enabled to keep app running in background and receive instant notifications.</string>
<!--media view-->
<string name="NoMedia">Noch keine geteilten Medien vorhanden</string>

View File

@ -265,6 +265,8 @@
<string name="IncorrectLocalization">Fichero de localización incorrecto</string>
<string name="Enabled">Enabled</string>
<string name="Disabled">Disabled</string>
<string name="NotificationsService">Notifications Service</string>
<string name="NotificationsServiceDisableInfo">If google play services are enough for you to receive notifications, you can disable Notifications Service. However we recommend you to leave it enabled to keep app running in background and receive instant notifications.</string>
<!--media view-->
<string name="NoMedia">No hay fotos ni vídeos compartidos aún</string>

View File

@ -265,6 +265,8 @@
<string name="IncorrectLocalization">File della localizzazione non valido</string>
<string name="Enabled">Enabled</string>
<string name="Disabled">Disabled</string>
<string name="NotificationsService">Notifications Service</string>
<string name="NotificationsServiceDisableInfo">If google play services are enough for you to receive notifications, you can disable Notifications Service. However we recommend you to leave it enabled to keep app running in background and receive instant notifications.</string>
<!--media view-->
<string name="NoMedia">Nessun media condiviso</string>

View File

@ -265,6 +265,8 @@
<string name="IncorrectLocalization">Ongeldig vertalingsbestand</string>
<string name="Enabled">Enabled</string>
<string name="Disabled">Disabled</string>
<string name="NotificationsService">Notifications Service</string>
<string name="NotificationsServiceDisableInfo">If google play services are enough for you to receive notifications, you can disable Notifications Service. However we recommend you to leave it enabled to keep app running in background and receive instant notifications.</string>
<!--media view-->
<string name="NoMedia">Nog geen media gedeeld</string>

View File

@ -265,6 +265,8 @@
<string name="IncorrectLocalization">Incorrect localization file</string>
<string name="Enabled">Enabled</string>
<string name="Disabled">Disabled</string>
<string name="NotificationsService">Notifications Service</string>
<string name="NotificationsServiceDisableInfo">If google play services are enough for you to receive notifications, you can disable Notifications Service. However we recommend you to leave it enabled to keep app running in background and receive instant notifications.</string>
<!--media view-->
<string name="NoMedia">No shared media yet</string>