/* * This is the source code of Telegram for Android v. 5.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-2018. */ package org.telegram.messenger; import android.annotation.SuppressLint; 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; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.telephony.TelephonyManager; import android.text.TextUtils; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.firebase.messaging.FirebaseMessaging; import org.telegram.messenger.voip.VideoCapturerDevice; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.ForegroundDetector; import java.io.File; import androidx.multidex.MultiDex; public class ApplicationLoader extends Application { @SuppressLint("StaticFieldLeak") public static volatile Context applicationContext; public static volatile NetworkInfo currentNetworkInfo; public static volatile Handler applicationHandler; private static ConnectivityManager connectivityManager; private static volatile boolean applicationInited = false; public static long startTime; public static volatile boolean isScreenOn = false; public static volatile boolean mainInterfacePaused = true; public static volatile boolean mainInterfaceStopped = true; public static volatile boolean externalInterfacePaused = true; public static volatile boolean mainInterfacePausedStageQueue = true; public static boolean canDrawOverlays; public static volatile long mainInterfacePausedStageQueueTime; public static boolean hasPlayServices; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } public static File getFilesDirFixed() { for (int a = 0; a < 10; a++) { File path = ApplicationLoader.applicationContext.getFilesDir(); if (path != null) { return path; } } try { ApplicationInfo info = applicationContext.getApplicationInfo(); File path = new File(info.dataDir, "files"); path.mkdirs(); return path; } catch (Exception e) { FileLog.e(e); } return new File("/data/data/org.telegram.messenger/files"); } public static void postInitApplication() { if (applicationInited) { return; } applicationInited = true; try { LocaleController.getInstance(); //TODO improve } catch (Exception e) { e.printStackTrace(); } try { connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); BroadcastReceiver networkStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { currentNetworkInfo = connectivityManager.getActiveNetworkInfo(); } catch (Throwable ignore) { } boolean isSlow = isConnectionSlow(); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { ConnectionsManager.getInstance(a).checkConnection(); FileLoader.getInstance(a).onNetworkChanged(isSlow); } } }; IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); ApplicationLoader.applicationContext.registerReceiver(networkStateReceiver, filter); } catch (Exception e) { e.printStackTrace(); } try { final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); final BroadcastReceiver mReceiver = new ScreenReceiver(); applicationContext.registerReceiver(mReceiver, filter); } catch (Exception e) { e.printStackTrace(); } try { PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE); isScreenOn = pm.isScreenOn(); if (BuildVars.LOGS_ENABLED) { FileLog.d("screen state = " + isScreenOn); } } catch (Exception e) { e.printStackTrace(); } SharedConfig.loadConfig(); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { //TODO improve account UserConfig.getInstance(a).loadConfig(); MessagesController.getInstance(a); if (a == 0) { SharedConfig.pushStringStatus = "__FIREBASE_GENERATING_SINCE_" + ConnectionsManager.getInstance(a).getCurrentTime() + "__"; } else { ConnectionsManager.getInstance(a); } TLRPC.User user = UserConfig.getInstance(a).getCurrentUser(); if (user != null) { MessagesController.getInstance(a).putUser(user, true); SendMessagesHelper.getInstance(a).checkUnsentMessages(); } } ApplicationLoader app = (ApplicationLoader) ApplicationLoader.applicationContext; app.initPlayServices(); if (BuildVars.LOGS_ENABLED) { FileLog.d("app initied"); } MediaController.getInstance(); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { //TODO improve account ContactsController.getInstance(a).checkAppAccount(); DownloadController.getInstance(a); } ChatThemeController.init(); } public ApplicationLoader() { super(); } @Override public void onCreate() { try { applicationContext = getApplicationContext(); } catch (Throwable ignore) { } super.onCreate(); if (BuildVars.LOGS_ENABLED) { FileLog.d("app start time = " + (startTime = SystemClock.elapsedRealtime())); } if (applicationContext == null) { applicationContext = getApplicationContext(); } NativeLoader.initNativeLibs(ApplicationLoader.applicationContext); ConnectionsManager.native_setJava(false); new ForegroundDetector(this) { @Override public void onActivityStarted(Activity activity) { boolean wasInBackground = isBackground(); super.onActivityStarted(activity); if (wasInBackground) { ensureCurrentNetworkGet(true); } } }; if (BuildVars.LOGS_ENABLED) { FileLog.d("load libs time = " + (SystemClock.elapsedRealtime() - startTime)); } applicationHandler = new Handler(applicationContext.getMainLooper()); AndroidUtilities.runOnUIThread(ApplicationLoader::startPushService); } public static void startPushService() { SharedPreferences preferences = MessagesController.getGlobalNotificationsSettings(); boolean enabled; if (preferences.contains("pushService")) { enabled = preferences.getBoolean("pushService", true); } else { enabled = MessagesController.getMainSettings(UserConfig.selectedAccount).getBoolean("keepAliveService", false); } if (enabled) { try { applicationContext.startService(new Intent(applicationContext, NotificationsService.class)); } catch (Throwable ignore) { } } else { 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 public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); try { LocaleController.getInstance().onDeviceConfigurationChange(newConfig); AndroidUtilities.checkDisplaySize(applicationContext, newConfig); VideoCapturerDevice.checkScreenCapturerSize(); } catch (Exception e) { e.printStackTrace(); } } private void initPlayServices() { AndroidUtilities.runOnUIThread(() -> { if (hasPlayServices = checkPlayServices()) { final String currentPushString = SharedConfig.pushString; if (!TextUtils.isEmpty(currentPushString)) { if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { FileLog.d("GCM regId = " + currentPushString); } } else { if (BuildVars.LOGS_ENABLED) { FileLog.d("GCM Registration not found."); } } Utilities.globalQueue.postRunnable(() -> { try { SharedConfig.pushStringGetTimeStart = SystemClock.elapsedRealtime(); FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(task -> { SharedConfig.pushStringGetTimeEnd = SystemClock.elapsedRealtime(); if (!task.isSuccessful()) { if (BuildVars.LOGS_ENABLED) { FileLog.d("Failed to get regid"); } SharedConfig.pushStringStatus = "__FIREBASE_FAILED__"; GcmPushListenerService.sendRegistrationToServer(null); return; } String token = task.getResult(); if (!TextUtils.isEmpty(token)) { GcmPushListenerService.sendRegistrationToServer(token); } }); } catch (Throwable e) { FileLog.e(e); } }); } else { if (BuildVars.LOGS_ENABLED) { FileLog.d("No valid Google Play Services APK found."); } SharedConfig.pushStringStatus = "__NO_GOOGLE_PLAY_SERVICES__"; GcmPushListenerService.sendRegistrationToServer(null); } }, 1000); } private boolean checkPlayServices() { try { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); return resultCode == ConnectionResult.SUCCESS; } catch (Exception e) { FileLog.e(e); } return true; } private static void ensureCurrentNetworkGet(boolean force) { if (force || currentNetworkInfo == null) { try { if (connectivityManager == null) { connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); } currentNetworkInfo = connectivityManager.getActiveNetworkInfo(); } catch (Throwable ignore) { } } } public static boolean isRoaming() { try { ensureCurrentNetworkGet(false); return currentNetworkInfo != null && currentNetworkInfo.isRoaming(); } catch (Exception e) { FileLog.e(e); } return false; } public static boolean isConnectedOrConnectingToWiFi() { try { ensureCurrentNetworkGet(false); if (currentNetworkInfo != null && (currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI || currentNetworkInfo.getType() == ConnectivityManager.TYPE_ETHERNET)) { NetworkInfo.State state = currentNetworkInfo.getState(); if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING || state == NetworkInfo.State.SUSPENDED) { return true; } } } catch (Exception e) { FileLog.e(e); } return false; } public static boolean isConnectedToWiFi() { try { ensureCurrentNetworkGet(false); if (currentNetworkInfo != null && (currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI || currentNetworkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) && currentNetworkInfo.getState() == NetworkInfo.State.CONNECTED) { return true; } } catch (Exception e) { FileLog.e(e); } return false; } public static boolean isConnectionSlow() { try { ensureCurrentNetworkGet(false); if (currentNetworkInfo != null && currentNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) { switch (currentNetworkInfo.getSubtype()) { case TelephonyManager.NETWORK_TYPE_1xRTT: case TelephonyManager.NETWORK_TYPE_CDMA: case TelephonyManager.NETWORK_TYPE_EDGE: case TelephonyManager.NETWORK_TYPE_GPRS: case TelephonyManager.NETWORK_TYPE_IDEN: return true; } } } catch (Throwable ignore) { } return false; } public static int getAutodownloadNetworkType() { try { ensureCurrentNetworkGet(false); if (currentNetworkInfo == null) { return StatsController.TYPE_MOBILE; } if (currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI || currentNetworkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) { if (connectivityManager.isActiveNetworkMetered()) { return StatsController.TYPE_MOBILE; } else { return StatsController.TYPE_WIFI; } } if (currentNetworkInfo.isRoaming()) { return StatsController.TYPE_ROAMING; } } catch (Exception e) { FileLog.e(e); } return StatsController.TYPE_MOBILE; } public static int getCurrentNetworkType() { if (isConnectedOrConnectingToWiFi()) { return StatsController.TYPE_WIFI; } else if (isRoaming()) { return StatsController.TYPE_ROAMING; } else { return StatsController.TYPE_MOBILE; } } public static boolean isNetworkOnlineFast() { try { ensureCurrentNetworkGet(false); if (currentNetworkInfo == null) { return true; } if (currentNetworkInfo.isConnectedOrConnecting() || currentNetworkInfo.isAvailable()) { return true; } NetworkInfo netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); if (netInfo != null && netInfo.isConnectedOrConnecting()) { return true; } else { netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (netInfo != null && netInfo.isConnectedOrConnecting()) { return true; } } } catch (Exception e) { FileLog.e(e); return true; } return false; } public static boolean isNetworkOnlineRealtime() { try { ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); if (netInfo != null && (netInfo.isConnectedOrConnecting() || netInfo.isAvailable())) { return true; } netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); if (netInfo != null && netInfo.isConnectedOrConnecting()) { return true; } else { netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (netInfo != null && netInfo.isConnectedOrConnecting()) { return true; } } } catch (Exception e) { FileLog.e(e); return true; } return false; } public static boolean isNetworkOnline() { boolean result = isNetworkOnlineRealtime(); if (BuildVars.DEBUG_PRIVATE_VERSION) { boolean result2 = isNetworkOnlineFast(); if (result != result2) { FileLog.d("network online mismatch"); } } return result; } }