NekoX/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java

1133 lines
44 KiB
Java
Raw Normal View History

/*
2015-10-29 18:10:07 +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-2016.
*/
2015-09-24 22:52:02 +02:00
package org.telegram.messenger;
2015-05-21 23:27:27 +02:00
import android.annotation.SuppressLint;
import android.app.Activity;
2014-10-14 22:36:15 +02:00
import android.app.AlertDialog;
2016-03-16 13:26:32 +01:00
import android.app.PendingIntent;
2015-05-21 23:27:27 +02:00
import android.content.ContentUris;
import android.content.Context;
2014-10-14 22:36:15 +02:00
import android.content.DialogInterface;
2015-05-21 23:27:27 +02:00
import android.content.Intent;
import android.content.pm.ActivityInfo;
2015-10-29 18:10:07 +01:00
import android.content.pm.PackageManager;
import android.content.res.Configuration;
2015-05-21 23:27:27 +02:00
import android.database.Cursor;
2016-03-16 13:26:32 +01:00
import android.graphics.BitmapFactory;
2015-04-09 20:00:14 +02:00
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
2014-11-17 03:44:57 +01:00
import android.graphics.drawable.Drawable;
2015-05-21 23:27:27 +02:00
import android.net.Uri;
import android.os.Build;
2016-03-16 13:26:32 +01:00
import android.os.Bundle;
import android.os.Environment;
2016-03-06 02:49:31 +01:00
import android.os.Parcelable;
import android.provider.Browser;
2015-05-21 23:27:27 +02:00
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
2015-04-09 20:00:14 +02:00
import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
2014-11-17 03:44:57 +01:00
import android.util.StateSet;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
2014-11-11 23:16:17 +01:00
import android.widget.AbsListView;
import android.widget.EdgeEffect;
2014-10-21 22:35:16 +02:00
import android.widget.EditText;
2014-11-11 23:16:17 +01:00
import android.widget.ListView;
import android.widget.ProgressBar;
2014-10-21 22:35:16 +02:00
import android.widget.TextView;
2015-05-21 23:27:27 +02:00
import net.hockeyapp.android.CrashManager;
import net.hockeyapp.android.CrashManagerListener;
import net.hockeyapp.android.UpdateManager;
2015-09-24 22:52:02 +02:00
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy;
import org.telegram.messenger.AnimationCompat.AnimatorSetProxy;
import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy;
import org.telegram.messenger.AnimationCompat.ViewProxy;
import org.telegram.ui.Components.ForegroundDetector;
import org.telegram.ui.Components.NumberPicker;
import org.telegram.ui.Components.TypefaceSpan;
2015-05-21 23:27:27 +02:00
import java.io.ByteArrayOutputStream;
import java.io.File;
2015-05-21 23:27:27 +02:00
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
2014-10-21 22:35:16 +02:00
import java.lang.reflect.Field;
2014-11-07 11:23:17 +01:00
import java.lang.reflect.Method;
2015-05-21 23:27:27 +02:00
import java.text.SimpleDateFormat;
import java.util.ArrayList;
2015-05-21 23:27:27 +02:00
import java.util.Date;
import java.util.Hashtable;
2015-05-21 23:27:27 +02:00
import java.util.Locale;
2015-11-26 22:04:02 +01:00
import java.util.regex.Pattern;
public class AndroidUtilities {
2014-10-11 13:30:32 +02:00
2015-01-02 23:15:07 +01:00
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
private static int prevOrientation = -10;
private static boolean waitingForSms = false;
2016-03-16 13:26:32 +01:00
private static boolean waitingForCall = false;
private static final Object smsLock = new Object();
2016-03-16 13:26:32 +01:00
private static final Object callLock = new Object();
public static int statusBarHeight = 0;
public static float density = 1;
public static Point displaySize = new Point();
public static Integer photoSize = null;
public static DisplayMetrics displayMetrics = new DisplayMetrics();
2015-03-26 18:34:47 +01:00
public static int leftBaseline;
public static boolean usingHardwareInput;
2014-09-24 17:08:25 +02:00
private static Boolean isTablet = null;
2015-09-24 22:52:02 +02:00
private static int adjustOwnerClassGuid = 0;
2015-11-26 22:04:02 +01:00
public static Pattern WEB_URL = null;
static {
try {
final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
final Pattern IP_ADDRESS = Pattern.compile(
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9]))");
final String IRI = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
WEB_URL = Pattern.compile(
"((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "(?:" + DOMAIN_NAME + ")"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ "(?:\\b|$)");
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
static {
density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
2015-03-26 18:34:47 +01:00
leftBaseline = isTablet() ? 80 : 72;
checkDisplaySize();
}
2015-09-24 22:52:02 +02:00
public static void requestAdjustResize(Activity activity, int classGuid) {
if (activity == null || isTablet()) {
return;
}
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
adjustOwnerClassGuid = classGuid;
}
public static void removeAdjustResize(Activity activity, int classGuid) {
if (activity == null || isTablet()) {
return;
}
if (adjustOwnerClassGuid == classGuid) {
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
}
}
public static void lockOrientation(Activity activity) {
if (activity == null || prevOrientation != -10 || Build.VERSION.SDK_INT < 9) {
return;
}
try {
prevOrientation = activity.getRequestedOrientation();
WindowManager manager = (WindowManager)activity.getSystemService(Activity.WINDOW_SERVICE);
if (manager != null && manager.getDefaultDisplay() != null) {
int rotation = manager.getDefaultDisplay().getRotation();
int orientation = activity.getResources().getConfiguration().orientation;
2014-11-17 23:04:31 +01:00
int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;
if (Build.VERSION.SDK_INT < 9) {
SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
if (rotation == Surface.ROTATION_270) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
2014-11-17 23:04:31 +01:00
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
} else if (rotation == Surface.ROTATION_90) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
2014-11-17 23:04:31 +01:00
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
} else if (rotation == Surface.ROTATION_0) {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
} else {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
2014-11-17 23:04:31 +01:00
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
} else {
2014-11-17 23:04:31 +01:00
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
}
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static void unlockOrientation(Activity activity) {
if (activity == null || Build.VERSION.SDK_INT < 9) {
return;
}
try {
if (prevOrientation != -10) {
activity.setRequestedOrientation(prevOrientation);
prevOrientation = -10;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static Typeface getTypeface(String assetPath) {
synchronized (typefaceCache) {
if (!typefaceCache.containsKey(assetPath)) {
try {
Typeface t = Typeface.createFromAsset(ApplicationLoader.applicationContext.getAssets(), assetPath);
typefaceCache.put(assetPath, t);
} catch (Exception e) {
FileLog.e("Typefaces", "Could not get typeface '" + assetPath + "' because " + e.getMessage());
return null;
}
}
return typefaceCache.get(assetPath);
}
}
public static boolean isWaitingForSms() {
2015-05-21 23:27:27 +02:00
boolean value;
synchronized (smsLock) {
value = waitingForSms;
}
return value;
}
public static void setWaitingForSms(boolean value) {
synchronized (smsLock) {
waitingForSms = value;
}
}
2016-03-16 13:26:32 +01:00
public static boolean isWaitingForCall() {
boolean value;
synchronized (callLock) {
value = waitingForCall;
}
return value;
}
public static void setWaitingForCall(boolean value) {
synchronized (callLock) {
waitingForCall = value;
}
}
public static void showKeyboard(View view) {
if (view == null) {
return;
}
InputMethodManager inputManager = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
public static boolean isKeyboardShowed(View view) {
if (view == null) {
return false;
}
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return inputManager.isActive(view);
}
public static void hideKeyboard(View view) {
if (view == null) {
return;
}
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (!imm.isActive()) {
return;
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
public static File getCacheDir() {
2015-01-02 23:15:07 +01:00
String state = null;
try {
state = Environment.getExternalStorageState();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
if (state == null || state.startsWith(Environment.MEDIA_MOUNTED)) {
2014-07-20 01:31:49 +02:00
try {
File file = ApplicationLoader.applicationContext.getExternalCacheDir();
if (file != null) {
return file;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
2014-07-20 01:31:49 +02:00
try {
File file = ApplicationLoader.applicationContext.getCacheDir();
if (file != null) {
return file;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return new File("");
}
public static int dp(float value) {
if (value == 0) {
return 0;
}
2015-10-29 18:10:07 +01:00
return (int) Math.ceil(density * value);
}
public static int compare(int lhs, int rhs) {
if (lhs == rhs) {
return 0;
} else if (lhs > rhs) {
return 1;
}
return -1;
}
2014-10-14 22:36:15 +02:00
public static float dpf2(float value) {
if (value == 0) {
return 0;
}
2014-10-14 22:36:15 +02:00
return density * value;
}
public static void checkDisplaySize() {
try {
Configuration configuration = ApplicationLoader.applicationContext.getResources().getConfiguration();
usingHardwareInput = configuration.keyboard != Configuration.KEYBOARD_NOKEYS && configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
if (manager != null) {
Display display = manager.getDefaultDisplay();
if (display != null) {
display.getMetrics(displayMetrics);
if (android.os.Build.VERSION.SDK_INT < 13) {
displaySize.set(display.getWidth(), display.getHeight());
} else {
display.getSize(displaySize);
}
FileLog.e("tmessages", "display size = " + displaySize.x + " " + displaySize.y + " " + displayMetrics.xdpi + "x" + displayMetrics.ydpi);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static float getPixelsInCM(float cm, boolean isX) {
return (cm / 2.54f) * (isX ? displayMetrics.xdpi : displayMetrics.ydpi);
}
public static long makeBroadcastId(int id) {
return 0x0000000100000000L | ((long)id & 0x00000000FFFFFFFFL);
}
2014-10-14 10:13:16 +02:00
public static int getMyLayerVersion(int layer) {
return layer & 0xffff;
}
public static int getPeerLayerVersion(int layer) {
return (layer >> 16) & 0xffff;
}
public static int setMyLayerVersion(int layer, int version) {
return layer & 0xffff0000 | version;
}
public static int setPeerLayerVersion(int layer, int version) {
return layer & 0x0000ffff | (version << 16);
}
public static void runOnUIThread(Runnable runnable) {
runOnUIThread(runnable, 0);
2014-10-01 21:55:24 +02:00
}
public static void runOnUIThread(Runnable runnable, long delay) {
2014-10-01 21:55:24 +02:00
if (delay == 0) {
ApplicationLoader.applicationHandler.post(runnable);
} else {
ApplicationLoader.applicationHandler.postDelayed(runnable, delay);
}
}
public static void cancelRunOnUIThread(Runnable runnable) {
ApplicationLoader.applicationHandler.removeCallbacks(runnable);
}
public static boolean isTablet() {
2014-09-24 17:08:25 +02:00
if (isTablet == null) {
isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
}
return isTablet;
}
public static boolean isSmallTablet() {
float minSide = Math.min(displaySize.x, displaySize.y) / density;
return minSide <= 700;
}
public static int getMinTabletSide() {
if (!isSmallTablet()) {
int smallSide = Math.min(displaySize.x, displaySize.y);
int leftSide = smallSide * 35 / 100;
if (leftSide < dp(320)) {
leftSide = dp(320);
}
return smallSide - leftSide;
} else {
int smallSide = Math.min(displaySize.x, displaySize.y);
int maxSide = Math.max(displaySize.x, displaySize.y);
int leftSide = maxSide * 35 / 100;
if (leftSide < dp(320)) {
leftSide = dp(320);
}
return Math.min(smallSide, maxSide - leftSide);
}
}
2016-03-06 02:49:31 +01:00
public static void openUrl(Context context, String url) {
if (context == null || url == null) {
return;
}
openUrl(context, Uri.parse(url));
}
public static void openUrl(Context context, Uri uri) {
if (context == null || uri == null) {
return;
}
2016-03-16 13:26:32 +01:00
2016-03-06 02:49:31 +01:00
try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
2016-03-16 13:26:32 +01:00
if (MediaController.getInstance().canCustomTabs()) {
intent.putExtra("android.support.customtabs.extra.SESSION", (Parcelable) null);
intent.putExtra("android.support.customtabs.extra.TOOLBAR_COLOR", 0xff54759e);
intent.putExtra("android.support.customtabs.extra.TITLE_VISIBILITY", 1);
Intent actionIntent = new Intent(Intent.ACTION_SEND);
actionIntent.setType("text/plain");
actionIntent.putExtra(Intent.EXTRA_TEXT, uri.toString());
actionIntent.putExtra(Intent.EXTRA_SUBJECT, "");
PendingIntent pendingIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, actionIntent, PendingIntent.FLAG_ONE_SHOT);
Bundle bundle = new Bundle();
bundle.putInt("android.support.customtabs.customaction.ID", 0);
bundle.putParcelable("android.support.customtabs.customaction.ICON", BitmapFactory.decodeResource(context.getResources(), R.drawable.abc_ic_menu_share_mtrl_alpha));
bundle.putString("android.support.customtabs.customaction.DESCRIPTION", LocaleController.getString("ShareFile", R.string.ShareFile));
bundle.putParcelable("android.support.customtabs.customaction.PENDING_INTENT", pendingIntent);
intent.putExtra("android.support.customtabs.extra.ACTION_BUTTON_BUNDLE", bundle);
intent.putExtra("android.support.customtabs.extra.TINT_ACTION_BUTTON", false);
}
2016-03-06 02:49:31 +01:00
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
context.startActivity(intent);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static int getPhotoSize() {
if (photoSize == null) {
if (Build.VERSION.SDK_INT >= 16) {
photoSize = 1280;
} else {
photoSize = 800;
}
}
return photoSize;
}
2014-10-14 22:36:15 +02:00
public static String formatTTLString(int ttl) {
if (ttl < 60) {
return LocaleController.formatPluralString("Seconds", ttl);
} else if (ttl < 60 * 60) {
return LocaleController.formatPluralString("Minutes", ttl / 60);
} else if (ttl < 60 * 60 * 24) {
return LocaleController.formatPluralString("Hours", ttl / 60 / 60);
} else if (ttl < 60 * 60 * 24 * 7) {
return LocaleController.formatPluralString("Days", ttl / 60 / 60 / 24);
} else {
int days = ttl / 60 / 60 / 24;
if (ttl % 7 == 0) {
return LocaleController.formatPluralString("Weeks", days / 7);
} else {
return String.format("%s %s", LocaleController.formatPluralString("Weeks", days / 7), LocaleController.formatPluralString("Days", days % 7));
}
}
}
2014-10-21 22:35:16 +02:00
public static AlertDialog.Builder buildTTLAlert(final Context context, final TLRPC.EncryptedChat encryptedChat) {
2014-10-14 22:36:15 +02:00
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
final NumberPicker numberPicker = new NumberPicker(context);
numberPicker.setMinValue(0);
numberPicker.setMaxValue(20);
2014-10-22 22:01:07 +02:00
if (encryptedChat.ttl > 0 && encryptedChat.ttl < 16) {
2014-10-14 22:36:15 +02:00
numberPicker.setValue(encryptedChat.ttl);
} else if (encryptedChat.ttl == 30) {
numberPicker.setValue(16);
} else if (encryptedChat.ttl == 60) {
numberPicker.setValue(17);
} else if (encryptedChat.ttl == 60 * 60) {
numberPicker.setValue(18);
} else if (encryptedChat.ttl == 60 * 60 * 24) {
numberPicker.setValue(19);
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
numberPicker.setValue(20);
2014-10-22 22:01:07 +02:00
} else if (encryptedChat.ttl == 0) {
2014-11-21 20:36:21 +01:00
numberPicker.setValue(0);
2014-10-14 22:36:15 +02:00
}
numberPicker.setFormatter(new NumberPicker.Formatter() {
@Override
public String format(int value) {
if (value == 0) {
return LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever);
} else if (value >= 1 && value < 16) {
return AndroidUtilities.formatTTLString(value);
} else if (value == 16) {
return AndroidUtilities.formatTTLString(30);
} else if (value == 17) {
return AndroidUtilities.formatTTLString(60);
} else if (value == 18) {
return AndroidUtilities.formatTTLString(60 * 60);
} else if (value == 19) {
return AndroidUtilities.formatTTLString(60 * 60 * 24);
} else if (value == 20) {
return AndroidUtilities.formatTTLString(60 * 60 * 24 * 7);
}
return "";
}
});
builder.setView(numberPicker);
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int oldValue = encryptedChat.ttl;
which = numberPicker.getValue();
if (which >= 0 && which < 16) {
encryptedChat.ttl = which;
} else if (which == 16) {
encryptedChat.ttl = 30;
} else if (which == 17) {
encryptedChat.ttl = 60;
} else if (which == 18) {
encryptedChat.ttl = 60 * 60;
} else if (which == 19) {
encryptedChat.ttl = 60 * 60 * 24;
} else if (which == 20) {
encryptedChat.ttl = 60 * 60 * 24 * 7;
}
if (oldValue != encryptedChat.ttl) {
SecretChatHelper.getInstance().sendTTLMessage(encryptedChat, null);
2014-10-14 22:36:15 +02:00
MessagesStorage.getInstance().updateEncryptedChatTTL(encryptedChat);
}
}
});
return builder;
}
2014-10-21 22:35:16 +02:00
public static void clearCursorDrawable(EditText editText) {
if (editText == null || Build.VERSION.SDK_INT < 12) {
return;
}
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.setInt(editText, 0);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static void setProgressBarAnimationDuration(ProgressBar progressBar, int duration) {
if (progressBar == null) {
return;
}
try {
Field mCursorDrawableRes = ProgressBar.class.getDeclaredField("mDuration");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.setInt(progressBar, duration);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static int getViewInset(View view) {
2015-12-09 19:27:52 +01:00
if (view == null || Build.VERSION.SDK_INT < 21 || view.getHeight() == AndroidUtilities.displaySize.y || view.getHeight() == AndroidUtilities.displaySize.y - statusBarHeight) {
return 0;
}
try {
Field mAttachInfoField = View.class.getDeclaredField("mAttachInfo");
mAttachInfoField.setAccessible(true);
Object mAttachInfo = mAttachInfoField.get(view);
if (mAttachInfo != null) {
Field mStableInsetsField = mAttachInfo.getClass().getDeclaredField("mStableInsets");
mStableInsetsField.setAccessible(true);
Rect insets = (Rect)mStableInsetsField.get(mAttachInfo);
return insets.bottom;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return 0;
}
2014-11-07 11:23:17 +01:00
public static Point getRealScreenSize() {
Point size = new Point();
try {
WindowManager windowManager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
windowManager.getDefaultDisplay().getRealSize(size);
} else {
try {
Method mGetRawW = Display.class.getMethod("getRawWidth");
Method mGetRawH = Display.class.getMethod("getRawHeight");
size.set((Integer) mGetRawW.invoke(windowManager.getDefaultDisplay()), (Integer) mGetRawH.invoke(windowManager.getDefaultDisplay()));
} catch (Exception e) {
size.set(windowManager.getDefaultDisplay().getWidth(), windowManager.getDefaultDisplay().getHeight());
2014-11-07 11:23:17 +01:00
FileLog.e("tmessages", e);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return size;
}
2014-11-11 23:16:17 +01:00
2014-11-17 23:04:31 +01:00
public static void setListViewEdgeEffectColor(AbsListView listView, int color) {
2014-11-11 23:16:17 +01:00
if (Build.VERSION.SDK_INT >= 21) {
try {
Field field = AbsListView.class.getDeclaredField("mEdgeGlowTop");
field.setAccessible(true);
EdgeEffect mEdgeGlowTop = (EdgeEffect) field.get(listView);
if (mEdgeGlowTop != null) {
mEdgeGlowTop.setColor(color);
}
field = AbsListView.class.getDeclaredField("mEdgeGlowBottom");
field.setAccessible(true);
EdgeEffect mEdgeGlowBottom = (EdgeEffect) field.get(listView);
if (mEdgeGlowBottom != null) {
mEdgeGlowBottom.setColor(color);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
2014-11-17 03:44:57 +01:00
2015-05-21 23:27:27 +02:00
@SuppressLint("NewApi")
2014-11-17 03:44:57 +01:00
public static void clearDrawableAnimation(View view) {
if (Build.VERSION.SDK_INT < 21 || view == null) {
return;
}
2015-05-21 23:27:27 +02:00
Drawable drawable;
2014-11-17 03:44:57 +01:00
if (view instanceof ListView) {
drawable = ((ListView) view).getSelector();
if (drawable != null) {
drawable.setState(StateSet.NOTHING);
}
} else {
drawable = view.getBackground();
if (drawable != null) {
drawable.setState(StateSet.NOTHING);
drawable.jumpToCurrentState();
}
}
}
2015-06-29 19:12:11 +02:00
public static final int FLAG_TAG_BR = 1;
public static final int FLAG_TAG_BOLD = 2;
public static final int FLAG_TAG_COLOR = 4;
public static final int FLAG_TAG_ALL = FLAG_TAG_BR | FLAG_TAG_BOLD | FLAG_TAG_COLOR;
2015-04-09 20:00:14 +02:00
public static Spannable replaceTags(String str) {
2015-06-29 19:12:11 +02:00
return replaceTags(str, FLAG_TAG_ALL);
}
public static Spannable replaceTags(String str, int flag) {
2015-04-09 20:00:14 +02:00
try {
2015-05-21 23:27:27 +02:00
int start;
int end;
2015-04-09 20:00:14 +02:00
StringBuilder stringBuilder = new StringBuilder(str);
2015-06-29 19:12:11 +02:00
if ((flag & FLAG_TAG_BR) != 0) {
while ((start = stringBuilder.indexOf("<br>")) != -1) {
stringBuilder.replace(start, start + 4, "\n");
}
while ((start = stringBuilder.indexOf("<br/>")) != -1) {
stringBuilder.replace(start, start + 5, "\n");
}
2015-04-09 20:00:14 +02:00
}
ArrayList<Integer> bolds = new ArrayList<>();
2015-06-29 19:12:11 +02:00
if ((flag & FLAG_TAG_BOLD) != 0) {
while ((start = stringBuilder.indexOf("<b>")) != -1) {
2015-04-09 20:00:14 +02:00
stringBuilder.replace(start, start + 3, "");
end = stringBuilder.indexOf("</b>");
if (end == -1) {
end = stringBuilder.indexOf("<b>");
}
2015-04-09 20:00:14 +02:00
stringBuilder.replace(end, end + 4, "");
bolds.add(start);
bolds.add(end);
2015-06-29 19:12:11 +02:00
}
}
ArrayList<Integer> colors = new ArrayList<>();
if ((flag & FLAG_TAG_COLOR) != 0) {
while ((start = stringBuilder.indexOf("<c#")) != -1) {
stringBuilder.replace(start, start + 2, "");
end = stringBuilder.indexOf(">", start);
int color = Color.parseColor(stringBuilder.substring(start, end));
stringBuilder.replace(start, end + 1, "");
2015-04-09 20:00:14 +02:00
end = stringBuilder.indexOf("</c>");
stringBuilder.replace(end, end + 4, "");
2015-06-29 19:12:11 +02:00
colors.add(start);
2015-04-09 20:00:14 +02:00
colors.add(end);
colors.add(color);
}
}
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder);
for (int a = 0; a < bolds.size() / 2; a++) {
spannableStringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (int a = 0; a < colors.size() / 3; a++) {
spannableStringBuilder.setSpan(new ForegroundColorSpan(colors.get(a * 3 + 2)), colors.get(a * 3), colors.get(a * 3 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannableStringBuilder;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
2015-04-09 20:00:14 +02:00
return new SpannableStringBuilder(str);
}
public static boolean needShowPasscode(boolean reset) {
boolean wasInBackground;
if (Build.VERSION.SDK_INT >= 14) {
wasInBackground = ForegroundDetector.getInstance().isWasInBackground(reset);
if (reset) {
ForegroundDetector.getInstance().resetBackgroundVar();
}
} else {
wasInBackground = UserConfig.lastPauseTime != 0;
}
return UserConfig.passcodeHash.length() > 0 && wasInBackground &&
(UserConfig.appLocked || UserConfig.autoLockIn != 0 && UserConfig.lastPauseTime != 0 && !UserConfig.appLocked && (UserConfig.lastPauseTime + UserConfig.autoLockIn) <= ConnectionsManager.getInstance().getCurrentTime());
}
2015-02-27 20:57:58 +01:00
2015-09-24 22:52:02 +02:00
public static void shakeView(final View view, final float x, final int num) {
2015-04-09 20:00:14 +02:00
if (num == 6) {
2015-09-24 22:52:02 +02:00
ViewProxy.setTranslationX(view, 0);
view.clearAnimation();
2015-04-09 20:00:14 +02:00
return;
}
AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
2015-09-24 22:52:02 +02:00
animatorSetProxy.playTogether(ObjectAnimatorProxy.ofFloat(view, "translationX", AndroidUtilities.dp(x)));
2015-04-09 20:00:14 +02:00
animatorSetProxy.setDuration(50);
animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() {
@Override
public void onAnimationEnd(Object animation) {
2015-09-24 22:52:02 +02:00
shakeView(view, num == 5 ? 0 : -x, num + 1);
2015-04-09 20:00:14 +02:00
}
});
animatorSetProxy.start();
}
/*public static String ellipsize(String text, int maxLines, int maxWidth, TextPaint paint) {
if (text == null || paint == null) {
return null;
}
int count;
int offset = 0;
StringBuilder result = null;
TextView
for (int a = 0; a < maxLines; a++) {
count = paint.breakText(text, true, maxWidth, null);
if (a != maxLines - 1) {
if (result == null) {
result = new StringBuilder(count * maxLines + 1);
}
boolean foundSpace = false;
for (int c = count - 1; c >= offset; c--) {
if (text.charAt(c) == ' ') {
foundSpace = true;
result.append(text.substring(offset, c - 1));
offset = c - 1;
}
}
if (!foundSpace) {
offset = count;
}
text = text.substring(0, offset);
} else if (maxLines == 1) {
return text.substring(0, count);
} else {
result.append(text.substring(0, count));
}
}
return result.toString();
}*/
2015-02-27 20:57:58 +01:00
/*public static void turnOffHardwareAcceleration(Window window) {
if (window == null || Build.MODEL == null || Build.VERSION.SDK_INT < 11) {
return;
}
if (Build.MODEL.contains("GT-S5301") ||
Build.MODEL.contains("GT-S5303") ||
Build.MODEL.contains("GT-B5330") ||
Build.MODEL.contains("GT-S5302") ||
Build.MODEL.contains("GT-S6012B") ||
Build.MODEL.contains("MegaFon_SP-AI")) {
window.clearFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
}*/
2015-05-21 23:27:27 +02:00
public static void checkForCrashes(Activity context) {
2015-11-26 22:04:02 +01:00
CrashManager.register(context, BuildVars.DEBUG_VERSION ? BuildVars.HOCKEY_APP_HASH_DEBUG : BuildVars.HOCKEY_APP_HASH, new CrashManagerListener() {
2015-05-21 23:27:27 +02:00
@Override
public boolean includeDeviceData() {
return true;
}
});
}
public static void checkForUpdates(Activity context) {
if (BuildVars.DEBUG_VERSION) {
2015-11-26 22:04:02 +01:00
UpdateManager.register(context, BuildVars.DEBUG_VERSION ? BuildVars.HOCKEY_APP_HASH_DEBUG : BuildVars.HOCKEY_APP_HASH);
2015-05-21 23:27:27 +02:00
}
}
public static void unregisterUpdates() {
if (BuildVars.DEBUG_VERSION) {
UpdateManager.unregister();
}
}
public static void addMediaToGallery(String fromPath) {
if (fromPath == null) {
return;
}
File f = new File(fromPath);
Uri contentUri = Uri.fromFile(f);
addMediaToGallery(contentUri);
}
public static void addMediaToGallery(Uri uri) {
if (uri == null) {
return;
}
2015-10-29 18:10:07 +01:00
try {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(uri);
ApplicationLoader.applicationContext.sendBroadcast(mediaScanIntent);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
2015-05-21 23:27:27 +02:00
}
private static File getAlbumDir() {
2015-10-29 18:10:07 +01:00
if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
return FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE);
}
2015-05-21 23:27:27 +02:00
File storageDir = null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Telegram");
if (!storageDir.mkdirs()) {
if (!storageDir.exists()){
FileLog.d("tmessages", "failed to create directory");
return null;
}
}
} else {
FileLog.d("tmessages", "External storage is not mounted READ/WRITE.");
}
return storageDir;
}
@SuppressLint("NewApi")
public static String getPath(final Uri uri) {
try {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
if (isKitKat && DocumentsContract.isDocumentUri(ApplicationLoader.applicationContext, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(ApplicationLoader.applicationContext, contentUri, null, null);
} else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
switch (type) {
case "image":
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
break;
case "video":
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
break;
case "audio":
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
break;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(ApplicationLoader.applicationContext, contentUri, selection, selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(ApplicationLoader.applicationContext, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
2016-03-16 13:26:32 +01:00
String value = cursor.getString(column_index);
if (value.startsWith("content://") || !value.startsWith("/") && !value.startsWith("file://")) {
return null;
}
return value;
2015-05-21 23:27:27 +02:00
}
} catch (Exception e) {
FileLog.e("tmessages", e);
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static File generatePicturePath() {
try {
File storageDir = getAlbumDir();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
return new File(storageDir, "IMG_" + timeStamp + ".jpg");
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return null;
}
public static CharSequence generateSearchName(String name, String name2, String q) {
if (name == null && name2 == null) {
return "";
}
SpannableStringBuilder builder = new SpannableStringBuilder();
String wholeString = name;
if (wholeString == null || wholeString.length() == 0) {
wholeString = name2;
} else if (name2 != null && name2.length() != 0) {
wholeString += " " + name2;
}
wholeString = wholeString.trim();
String lower = " " + wholeString.toLowerCase();
int index;
int lastIndex = 0;
while ((index = lower.indexOf(" " + q, lastIndex)) != -1) {
int idx = index - (index == 0 ? 0 : 1);
int end = q.length() + (index == 0 ? 0 : 1) + idx;
if (lastIndex != 0 && lastIndex != idx + 1) {
builder.append(wholeString.substring(lastIndex, idx));
} else if (lastIndex == 0 && idx != 0) {
builder.append(wholeString.substring(0, idx));
}
String query = wholeString.substring(idx, end);
if (query.startsWith(" ")) {
builder.append(" ");
}
query = query.trim();
builder.append(AndroidUtilities.replaceTags("<c#ff4d83b3>" + query + "</c>"));
lastIndex = end;
}
if (lastIndex != -1 && lastIndex != wholeString.length()) {
builder.append(wholeString.substring(lastIndex, wholeString.length()));
}
return builder;
}
public static File generateVideoPath() {
try {
File storageDir = getAlbumDir();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
return new File(storageDir, "VID_" + timeStamp + ".mp4");
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return null;
}
public static String formatFileSize(long size) {
if (size < 1024) {
return String.format("%d B", size);
} else if (size < 1024 * 1024) {
return String.format("%.1f KB", size / 1024.0f);
} else if (size < 1024 * 1024 * 1024) {
return String.format("%.1f MB", size / 1024.0f / 1024.0f);
} else {
return String.format("%.1f GB", size / 1024.0f / 1024.0f / 1024.0f);
}
}
public static byte[] decodeQuotedPrintable(final byte[] bytes) {
if (bytes == null) {
return null;
}
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < bytes.length; i++) {
final int b = bytes[i];
if (b == '=') {
try {
final int u = Character.digit((char) bytes[++i], 16);
final int l = Character.digit((char) bytes[++i], 16);
buffer.write((char) ((u << 4) + l));
} catch (Exception e) {
FileLog.e("tmessages", e);
return null;
}
} else {
buffer.write(b);
}
}
byte[] array = buffer.toByteArray();
try {
buffer.close();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return array;
}
public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException {
OutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[4096];
int len;
while ((len = sourceFile.read(buf)) > 0) {
Thread.yield();
out.write(buf, 0, len);
}
out.close();
return true;
}
public static boolean copyFile(File sourceFile, File destFile) throws IOException {
if (!destFile.exists()) {
destFile.createNewFile();
}
FileInputStream source = null;
FileOutputStream destination = null;
try {
source = new FileInputStream(sourceFile);
destination = new FileOutputStream(destFile);
destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size());
} catch (Exception e) {
FileLog.e("tmessages", e);
return false;
} finally {
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}
return true;
}
2016-03-06 02:49:31 +01:00
public static byte[] calcAuthKeyHash(byte[] auth_key) {
byte[] sha1 = Utilities.computeSHA1(auth_key);
byte[] key_hash = new byte[16];
System.arraycopy(sha1, 0, key_hash, 0, 16);
return key_hash;
}
}