/*******************************************************************************
* Copyright (c) 2015 Aptoide.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
******************************************************************************/
package com.aptoide.amethyst.utils;
import android.accounts.AccountManager;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Service;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import com.aptoide.amethyst.Aptoide;
import com.aptoide.amethyst.BuildConfig;
import com.aptoide.amethyst.R;
import com.aptoide.amethyst.adapters.SpannableRecyclerAdapter;
import com.aptoide.amethyst.configuration.AptoideConfiguration;
import com.aptoide.amethyst.database.AptoideDatabase;
import com.aptoide.amethyst.events.BusProvider;
import com.aptoide.amethyst.events.OttoEvents;
import com.aptoide.amethyst.preferences.AptoidePreferences;
import com.aptoide.amethyst.preferences.EnumPreferences;
import com.aptoide.amethyst.preferences.ManagerPreferences;
import com.aptoide.amethyst.preferences.Preferences;
import com.aptoide.amethyst.preferences.SecurePreferences;
import com.aptoide.amethyst.social.WebViewFacebook;
import com.aptoide.amethyst.social.WebViewTwitter;
import com.aptoide.amethyst.webservices.AddApkFlagRequest;
import com.aptoide.amethyst.webservices.ChangeUserRepoSubscription;
import com.aptoide.amethyst.webservices.ChangeUserSettingsRequest;
import com.aptoide.amethyst.webservices.Errors;
import com.aptoide.amethyst.webservices.GetAppRequest;
import com.aptoide.amethyst.webservices.GetUserRepoSubscriptions;
import com.aptoide.amethyst.webservices.SearchRequest;
import com.aptoide.amethyst.webservices.json.GetUserRepoSubscriptionJson;
import com.aptoide.amethyst.webservices.listeners.CheckSimpleStoreListener;
import com.aptoide.amethyst.webservices.v2.AddApkCommentVoteRequest;
import com.aptoide.amethyst.webservices.v3.RateAppRequest;
import com.aptoide.dataprovider.webservices.GetSimpleStoreRequest;
import com.aptoide.dataprovider.webservices.json.GenericResponseV2;
import com.aptoide.dataprovider.webservices.models.Constants;
import com.aptoide.dataprovider.webservices.models.Defaults;
import com.aptoide.dataprovider.webservices.models.ErrorResponse;
import com.aptoide.dataprovider.webservices.models.v7.GetAppMeta;
import com.aptoide.dataprovider.webservices.v7.CommunityGetstoreRequest;
import com.aptoide.dataprovider.webservices.v7.GetListViewItemsRequestv7;
import com.aptoide.dataprovider.webservices.v7.GetMoreVersionsAppRequest;
import com.aptoide.dataprovider.webservices.v7.GetStoreRequestv7;
import com.aptoide.dataprovider.webservices.v7.GetStoreWidgetRequestv7;
import com.aptoide.models.ApkPermission;
import com.aptoide.models.ApkPermissionGroup;
import com.aptoide.models.stores.Login;
import com.aptoide.models.stores.Store;
import com.crashlytics.android.Crashlytics;
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.octo.android.robospice.SpiceManager;
import com.octo.android.robospice.persistence.exception.SpiceException;
import com.octo.android.robospice.request.listener.RequestListener;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.text.WordUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.DateFormatSymbols;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.UnknownFormatConversionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
/**
* Created with IntelliJ IDEA.
* User: rmateus
* Date: 15-10-2013
* Time: 16:39
* To change this template use File | Settings | File Templates.
*/
public class AptoideUtils {
public static SharedPreferences getSharedPreferences() {
return PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext());
}
public static int getPixels(Context context, int dipValue) {
Resources r = context.getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, r.getDisplayMetrics());
Logger.d("getPixels", "" + px);
return px;
}
public static class UI {
private static final String TAG = UI.class.getSimpleName();
public static int getVerCode(Context context) {
PackageManager manager = context.getPackageManager();
try {
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
return info.versionCode;
} catch (PackageManager.NameNotFoundException e) {
return -1;
}
}
public static void toast(String text) {
Toast.makeText(Aptoide.getContext(), text, Toast.LENGTH_LONG).show();
}
public static int getToolbarHeight(Context context) {
final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
new int[]{R.attr.actionBarSize});
int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
return toolbarHeight;
}
public static int getTabsHeight(Context context) {
return (int) context.getResources().getDimension(R.dimen.tabsHeight);
}
private static char[] c = new char[]{'k', 'm', 'b', 't'};
/**
* Recursive implementation, invokes itself for each factor of a thousand, increasing the class on each invokation.
*
* @param n the number to format
* @param iteration in fact this is the class from the array c
* @return a String representing the number n formatted in a cool looking way.
*/
public static String coolFormat(double n, int iteration) {
double d = ((long) n / 100) / 10.0;
boolean isRound = (d * 10) % 10 == 0;//true if the decimal part is equal to 0 (then it's trimmed anyway)
return (d < 1000 ? //this determines the class, i.e. 'k', 'm' etc
((d > 99.9 || isRound || (!isRound && d > 9.99) ? //this decides whether to trim the decimals
(int) d * 10 / 10 : d + "" // (int) d * 10 / 10 drops the decimal
) + "" + c[iteration])
: coolFormat(d, iteration + 1));
}
/**
* Check if thread calling this method is the UI Thread.
*
* @return true if UI Thread
*/
public static boolean isUiThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
public static String screenshotToThumb(Context context, String imageUrl, String orientation) {
String screen = null;
try {
if (imageUrl.contains("_screen")) {
String sizeString = IconSizeUtils.generateSizeStringScreenshots(context, orientation);
String[] splitUrl = imageUrl.split("\\.(?=[^\\.]+$)");
screen = splitUrl[0] + "_" + sizeString + "." + splitUrl[1];
} else {
String[] splitString = imageUrl.split("/");
StringBuilder db = new StringBuilder();
for (int i = 0; i != splitString.length - 1; i++) {
db.append(splitString[i]);
db.append("/");
}
db.append("thumbs/mobile/");
db.append(splitString[splitString.length - 1]);
screen = db.toString();
}
} catch (Exception e) {
Logger.printException(e);
Crashlytics.setString("imageUrl", imageUrl);
Crashlytics.logException(e);
}
return screen;
}
public static String getScreenshotThumbnail(String imageUrl, String orientation) {
String screen;
String sizeString;
if (imageUrl.contains("_screen")) {
if(orientation != null && orientation.equals("portrait")){
sizeString = "192x320";
}else{
sizeString = "256x160";
}
String[] splittedUrl = imageUrl.split("\\.(?=[^\\.]+$)");
screen = splittedUrl[0] + "_" + sizeString + "." + splittedUrl[1];
} else {
String[] splitedString = imageUrl.split("/");
StringBuilder db = new StringBuilder();
for (int i = 0; i != splitedString.length - 1; i++) {
db.append(splitedString[i]);
db.append("/");
}
db.append("thumbs/mobile/");
db.append(splitedString[splitedString.length - 1]);
screen = db.toString();
}
return screen;
}
/**
* Sets a color to a Drawable
*
* @param drawable
* @param color
*/
public static void setDrawableColor(Drawable drawable, int color) {
// Assuming "color" is your target color
float r = Color.red(color) / 255f;
float g = Color.green(color) / 255f;
float b = Color.blue(color) / 255f;
float a = Color.alpha(color) / 255f;
ColorMatrix cm = new ColorMatrix(new float[]{
r, r, r, r, r, //red
g, g, g, g, g, //green
b, b, b, b, b, //blue
1, 1, 1, 1, 1 //alpha
});
ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
drawable.setColorFilter(cf);
}
public static void toastError(List<ErrorResponse> errors) {
if (errors == null) {
return;
}
for (ErrorResponse error : errors) {
String localizedError = null;
try {
localizedError = Aptoide.getContext().getString(Errors.getErrorsMap().get(error.code));
} catch (NullPointerException ignored) {
}
if (localizedError == null) {
localizedError = error.msg;
}
if (localizedError != null)
Toast.makeText(Aptoide.getContext(), localizedError, Toast.LENGTH_LONG).show();
}
}
public static int getBucketSize() {
int bucket = 1;
float screenWidth = getScreenWidthInDip();
int magicNumber = Aptoide.getContext().getResources().getInteger(R.integer.bucket_size_magic_number);
if (screenWidth > magicNumber) {
bucket = (int) (screenWidth / magicNumber);
}
Logger.d("APTOIDEUTILS", "bucketsize = " + bucket);
return bucket;
}
public static int getEditorChoiceBucketSize() {
int bucket = 1;
float screenWidth = getScreenWidthInDip();
if (screenWidth > 300) {
bucket = (int) (screenWidth / 300);
}
Logger.d("APTOIDEUTILS", "bucketsize = " + bucket);
return bucket;
}
public static int getStoreBucketSize() {
int bucket = 1;
float screenWidth = getScreenWidthInDip();
if (screenWidth > 150) {
bucket = (int) (screenWidth / 150);
}
Logger.d("APTOIDEUTILS", "storeBucketsize = " + bucket);
return bucket;
}
protected static float getScreenWidthInDip() {
WindowManager wm = ((WindowManager) Aptoide.getContext().getSystemService(Context.WINDOW_SERVICE));
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
int screenWidth_in_pixel = dm.widthPixels;
return screenWidth_in_pixel / dm.density;
}
/**
* On v7 webservices there is no attribute of HD icon. <br />Instead,
* the logic is that if the filename ends with <b>_icon</b> it is an HD icon.
*
* @param context Context of the app
* @param iconUrl The String with the URL of the icon
* @return A String with
*/
public static String parseIcon(Context context, String iconUrl) {
try {
if (iconUrl.contains("_icon")) {
String sizeString = IconSizeUtils.generateSizeString(context);
String[] splittedUrl = iconUrl.split("\\.(?=[^\\.]+$)");
iconUrl = splittedUrl[0] + "_" + sizeString + "." + splittedUrl[1];
}
} catch (Exception e) {
Logger.printException(e);
}
return iconUrl;
}
/**
* Parse dp to pixels
*
* @param context Context of the app
* @param dps The int mesuare in dps
* @return An integer with the pixels value
*/
public static int parseDpsToPixels(Context context, int dps) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dps * scale + 0.5f);
}
/**
* Unbind all views
*
*/
public static void unbindDrawables(View view) {
final Drawable background = view.getBackground();
if (background != null) {
background.setCallback(null);
view.setBackgroundDrawable(null);
}
if (view instanceof ImageView) {
((ImageView)view).setImageDrawable(null);
} else if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
/**
* this method ensure that the returned span size is a valid one
* The recyclerView must have a GridLayoutManager and the adapter must be an instance of SpannableRecyclerAdapter.
* @param recyclerView where the item will be placed
* @param position item position
* @return a valid span size for the given item
*/
public static int getSpanSize(RecyclerView recyclerView, int position) {
if (!(recyclerView.getAdapter() instanceof SpannableRecyclerAdapter) || !(recyclerView.getLayoutManager() instanceof GridLayoutManager)) {
String errorMsg = "The recyclerView must have a GridLayoutManager and the adapter must be an instance of SpannableRecyclerAdapter.";
Crashlytics.logException(new ClassCastException(errorMsg));
Logger.e(TAG, errorMsg);
return 1;
}
int spanSize = ((SpannableRecyclerAdapter) recyclerView.getAdapter()).getSpanSize(position);
if (spanSize >= ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount()) {
return ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount();
} else if (spanSize < 1) {
return 1; //min span size
} else {
return spanSize;
}
}
}
/**
* Algorithms Utils
*/
public static class Algorithms {
/**
* method to copy a string to clipboard
* @param text texto to copy to clipBoard
* @return true if it was copied successfully false otherwise
*/
public static boolean copyToClipBoard(Context context, String text) {
if (text==null || text.isEmpty()) {
return false;
} else {
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText(text, text);
clipboard.setPrimaryClip(clip);
}
}
return true;
}
public static String computeSHA1sumFromBytes(byte[] bytes)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(bytes, 0, bytes.length);
byte[] sha1hash = md.digest();
return convToHexWithColon(sha1hash);
}
private static String convToHexWithColon(byte[] data) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while (two_halfs++ < 1);
if (i < data.length - 1) {
buf.append(":");
}
}
return buf.toString();
}
public static String computeSHA1sum(String text)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(text.getBytes("iso-8859-1"), 0, text.length());
byte[] sha1hash = md.digest();
return convToHex(sha1hash);
}
private static String convToHex(byte[] data) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
public static String md5Calc(File f) {
byte[] buffer = new byte[1024];
int read, i;
String md5hash;
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
InputStream is = new FileInputStream(f);
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
md5hash = bigInt.toString(16);
is.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
if (md5hash.length() != 33) {
String tmp = "";
for (i = 1; i < (33 - md5hash.length()); i++) {
tmp = tmp.concat("0");
}
md5hash = tmp.concat(md5hash);
}
return md5hash;
}
public static String computeHmacSha1(String value, String keyString)
throws InvalidKeyException, IllegalStateException,
UnsupportedEncodingException, NoSuchAlgorithmException {
System.out.println(value);
System.out.println(keyString);
SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"),
"HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(key);
byte[] bytes = mac.doFinal(value.getBytes("UTF-8"));
return convToHex(bytes);
}
}
/**
* Network Utils
*/
public static class NetworkUtils {
private static int TIME_OUT = 15000; // 15s
private static String getUserId() {
String user_id;
SharedPreferences sPref = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext());
user_id = sPref.getString("advertisingIdClient", null);
// Fallback para user
if (isNullOrEmpty(user_id)) {
user_id = android.provider.Settings.Secure.getString(Aptoide.getContext().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
}
// Fallback para UUID
if (isNullOrEmpty(user_id)) {
user_id = sPref.getString(EnumPreferences.APTOIDE_CLIENT_UUID.name(), "NoInfo");
}
return user_id;
}
public static String getUserAgentString(Context mctx, boolean update) {
SharedPreferences sPref = PreferenceManager.getDefaultSharedPreferences(mctx);
String myid = getUserId();
String myscr = sPref.getInt(EnumPreferences.SCREEN_WIDTH.name(), 0) + "x" + sPref.getInt(EnumPreferences.SCREEN_HEIGHT.name(), 0);
String verString = null;
try {
verString = mctx.getPackageManager().getPackageInfo(mctx.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
String extraId = Aptoide.getConfiguration().getExtraId();
return "aptoide-" + verString + ";" + HWSpecifications.TERMINAL_INFO + ";" + myscr + ";id:" + myid + ";" + sPref.getString(AptoideConfiguration.LOGIN_USER_LOGIN, "") + ";" + extraId;
}
public static boolean isIconDownloadPermitted(Context context) {
return true;
// return isAvailable(context,
// new DownloadPermissions(
// getSharedPreferences().getBoolean("wifi", true),
// getSharedPreferences().getBoolean("ethernet", true),
// getSharedPreferences().getBoolean("4g", true),
// getSharedPreferences().getBoolean("3g", true)));
}
public static boolean isGeneralDownloadPermitted(Context context) {
final SharedPreferences preferences = getSharedPreferences();
final boolean wifiAllowed = preferences.getBoolean("generalnetworkwifi", true);
final boolean wifiAvailable = isAvailable(context, TYPE_WIFI);
final boolean mobileAllowed = preferences.getBoolean("generalnetworkmobile", true);
final boolean mobileAvailable = isAvailable(context, TYPE_MOBILE);
return !(wifiAvailable && !wifiAllowed) && !(mobileAvailable && !mobileAllowed);
}
public static boolean isAvailable(Context context, int networkType) {
final ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
return Build.VERSION.SDK_INT < 21
? isAvailableSdk1(manager, networkType)
: isAvailableSdk21(manager, networkType);
}
private static boolean isAvailableSdk1(final ConnectivityManager manager,
final int networkType) {
final NetworkInfo info = manager.getActiveNetworkInfo();
return info != null && info.getType() == networkType;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean isAvailableSdk21(final ConnectivityManager manager,
final int networkType) {
for (final Network network : manager.getAllNetworks()) {
final NetworkInfo info = manager.getNetworkInfo(network);
if (info != null && info.isConnected() && info.getType() == networkType) {
return true;
}
}
return false;
}
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public static int checkServerConnection(final String string, final String username, final String password) throws Exception {
HttpURLConnection client = (HttpURLConnection) new URL(string
+ "info.xml").openConnection();
if (username != null && password != null) {
String basicAuth = "Basic "
+ new String(Base64.encode(
(username + ":" + password).getBytes(),
Base64.NO_WRAP));
client.setRequestProperty("Authorization", basicAuth);
}
client.setRequestMethod("HEAD");
client.setConnectTimeout(TIME_OUT);
client.setReadTimeout(TIME_OUT);
String contentType = client.getContentType();
int responseCode = client.getResponseCode();
client.disconnect();
if (Aptoide.DEBUG_MODE)
Logger.i("CheckServerConnection", "Checking on: " + client.getURL().toString());
if (contentType.equals("application/xml")) {
return 0;
} else {
return responseCode;
}
}
public static String getConnectionType() {
final Context context = Aptoide.getContext();
final ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo info = manager.getActiveNetworkInfo();
// Used only for backward compatibility, should be replaced with info.getTypeName()
if (info != null) {
switch (info.getType()) {
case TYPE_ETHERNET:
return "ethernet";
case TYPE_WIFI:
return "mobile";
case TYPE_MOBILE:
return "mobile";
}
}
return "unknown";
}
}
/**
* Repo/Store Utils
*/
public static class RepoUtils {
public static String checkStoreUrl(String uri_str) {
uri_str = uri_str.trim();
if (!uri_str.contains(".")) {
uri_str = uri_str.concat(".store.aptoide.com");
}
uri_str = RepoUtils.formatRepoUri(uri_str);
if (uri_str.contains("bazaarandroid.com")) {
uri_str = uri_str.replaceAll("bazaarandroid\\.com", "store.aptoide.com");
}
return uri_str;
}
public static String split(String repo) {
Logger.d("Aptoide-RepoUtils", "Splitting " + repo);
repo = formatRepoUri(repo);
return repo.split("http://")[1].split("\\.store")[0].split("\\.bazaarandroid.com")[0];
}
public static String formatRepoUri(String uri_str) {
uri_str = uri_str.toLowerCase(Locale.ENGLISH);
if (uri_str.contains("http//")) {
uri_str = uri_str.replaceFirst("http//", "http://");
}
if (uri_str.length() != 0 && uri_str.charAt(uri_str.length() - 1) != '/') {
uri_str = uri_str + '/';
Logger.d("Aptoide-ManageRepo", "repo uri: " + uri_str);
}
if (!uri_str.startsWith("http://")) {
uri_str = "http://" + uri_str;
Logger.d("Aptoide-ManageRepo", "repo uri: " + uri_str);
}
return uri_str;
}
public static void startParse(final String storeName, final Context context, final SpiceManager spiceManager) {
Toast.makeText(context, AptoideUtils.StringUtils.getFormattedString(context, R.string.subscribing, storeName), Toast.LENGTH_SHORT).show();
GetSimpleStoreRequest request = new GetSimpleStoreRequest();
request.store_name = storeName;
CheckSimpleStoreListener checkStoreListener = new CheckSimpleStoreListener();
checkStoreListener.callback = new CheckSimpleStoreListener.Callback() {
@Override
public void onSuccess() {
addStoreOnCloud(storeName, context, spiceManager);
}
};
spiceManager.execute(request, checkStoreListener);
}
/**
* Adds the default store
*/
public static void addDefaultAppsStore(Context context) {
AptoideDatabase database = new AptoideDatabase(Aptoide.getDb());
if (database.existsStore(Defaults.DEFAULT_STORE_ID)) {
return;
}
final Store store = new Store();
store.setId(Defaults.DEFAULT_STORE_ID);
store.setName(Defaults.DEFAULT_STORE_NAME);
store.setDownloads("");
String sizeString = IconSizeUtils.generateSizeStringAvatar(Aptoide.getContext());
String avatar = "http://pool.img.aptoide.com/apps/b62b1c9459964d3a876b04c70036b10a_ravatar.png";
// integrate the icon into a drawable ?
if (avatar != null) {
String[] splittedUrl = avatar.split("\\.(?=[^\\.]+$)");
avatar = splittedUrl[0] + "_" + sizeString + "." + splittedUrl[1];
}
store.setAvatar(avatar);
store.setDescription(context.getResources().getString(R.string.aptoide_description));
store.setTheme("default");
store.setView("list");
store.setBaseUrl("apps");
try {
long l = database.insertStore(store);
database.updateStore(store, l);
} catch (Exception e) {
Logger.printException(e);
}
}
/**
* Try to sync all your repos
*
* @param context
* @param spiceManager
*/
public static void syncRepos(Context context, SpiceManager spiceManager) {
final SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!defaultSharedPreferences.getBoolean(AptoidePreferences.REPOS_SYNCED, false)) {
GetUserRepoSubscriptions subscriptions = new GetUserRepoSubscriptions();
spiceManager.execute(subscriptions, new RequestListener<GetUserRepoSubscriptionJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
}
@Override
public void onRequestSuccess(final GetUserRepoSubscriptionJson getUserRepoSubscriptionJson) {
// Call database operations off the UI Thread
new Thread(new Runnable() {
@Override
public void run() {
boolean storeInserted = false;
for (GetUserRepoSubscriptionJson.RepoInfo subscription : getUserRepoSubscriptionJson.getSubscription()) {
try {
final Store store = new Store();
store.setId(subscription.getId().longValue());
store.setName(subscription.getName());
store.setDownloads(subscription.getDownloads());
String sizeString = IconSizeUtils.generateSizeStringAvatar(Aptoide.getContext());
String avatar = subscription.getAvatar();
if (avatar != null) {
String[] splitUrl = avatar.split("\\.(?=[^\\.]+$)");
avatar = splitUrl[0] + "_" + sizeString + "." + splitUrl[1];
}
store.setAvatar(avatar);
store.setDescription(subscription.getDescription());
store.setTheme(subscription.getTheme());
store.setView(subscription.getView());
store.setBaseUrl(subscription.getName());
AptoideDatabase database = new AptoideDatabase(Aptoide.getDb());
try {
long l = database.insertStore(store);
database.updateStore(store, l);
storeInserted = true;
} catch (Exception e) {
Logger.printException(e);
}
} catch (Exception e) {
Logger.printException(e);
}
}
defaultSharedPreferences.edit().putBoolean(AptoidePreferences.REPOS_SYNCED, true).apply();
if (storeInserted) {
BusProvider.getInstance().post(new OttoEvents.RepoAddedEvent());
}
}
}).start();
}
});
}
}
/**
* If there's a local account created, add the store to its aptoide account
*
* @param storeName
* @param context
* @param spiceManager
*/
private static void addStoreOnCloud(String storeName, Context context, SpiceManager spiceManager) {
if (AccountManager.get(context).getAccountsByType(Aptoide.getConfiguration().getAccountType()).length > 0) {
ChangeUserRepoSubscription changeUserRepoSubscription = new ChangeUserRepoSubscription();
ChangeUserRepoSubscription.RepoSubscription repoSubscription = new ChangeUserRepoSubscription.RepoSubscription(storeName, true);
changeUserRepoSubscription.setRepoSubscription(repoSubscription);
spiceManager.execute(changeUserRepoSubscription, null);
}
}
public static void removeStoreOnCloud(Store store, Context context, SpiceManager spiceManager) {
if (AccountManager.get(context).getAccountsByType(Aptoide.getConfiguration().getAccountType()).length > 0) {
ChangeUserRepoSubscription changeUserRepoSubscription = new ChangeUserRepoSubscription();
ChangeUserRepoSubscription.RepoSubscription repoSubscription = new ChangeUserRepoSubscription.RepoSubscription(store.getName(), false);
changeUserRepoSubscription.setRepoSubscription(repoSubscription);
spiceManager.execute(changeUserRepoSubscription, null);
}
}
public static GetMoreVersionsAppRequest GetMoreAppVersionsRequest(String packageName, int limit, int offset) {
GetMoreVersionsAppRequest request = new GetMoreVersionsAppRequest(AptoideUtils.UI.getBucketSize());
request.filters = Aptoide.filters;
request.mature = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).getBoolean(Constants.MATURE_CHECK_BOX, false);
request.aptoideVercode = AptoideUtils.UI.getVerCode(Aptoide.getContext());
request.lang = AptoideUtils.StringUtils.getMyCountryCode(Aptoide.getContext());
request.packageName = packageName;
request.limit = limit;
request.offset = offset;
return request;
}
public static GetStoreRequestv7 buildStoreRequest(long storeId, String context) {
GetStoreRequestv7 request = buildGenericStoreRequest(AptoideUtils.UI.getBucketSize());
request.storeId = storeId;
request.context = context;
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeId);
if (login != null) {
request.user = login.getUsername();
request.password = login.getPasswordSha1();
}
return request;
}
public static final int NUMBER_OF_LINES = 4;
public static GetStoreRequestv7 buildStoreRequest(long storeId, String context, int bucketSize) {
CommunityGetstoreRequest request = new CommunityGetstoreRequest(bucketSize, UI.getEditorChoiceBucketSize());
request.loggedIn = AccountUtils.isLoggedIn(Aptoide.getContext());
request.nview = "response";
request.filters = Aptoide.filters;
request.mature = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).getBoolean(Constants.MATURE_CHECK_BOX, false);
request.aptoideVercode = AptoideUtils.UI.getVerCode(Aptoide.getContext());
request.lang = AptoideUtils.StringUtils.getMyCountryCode(Aptoide.getContext());
request.storeId = storeId;
request.context = context;
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeId);
if (login != null) {
request.user = login.getUsername();
request.password = login.getPasswordSha1();
}
return request;
}
public static GetStoreRequestv7 buildStoreRequest(String storeName, String context) {
GetStoreRequestv7 request = buildGenericStoreRequest(AptoideUtils.UI.getBucketSize());
request.storeName = storeName;
request.context = context;
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeName);
if (login != null) {
request.user = login.getUsername();
request.password = login.getPasswordSha1();
}
return request;
}
public static GetSimpleStoreRequest buildSimpleStoreRequest(String storeName) {
GetSimpleStoreRequest request = new GetSimpleStoreRequest();
request.store_name = storeName;
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeName);
request.login = login;
return request;
}
private static GetStoreRequestv7 buildGenericStoreRequest(int bucketSize) {
GetStoreRequestv7 request = new GetStoreRequestv7(bucketSize);
request.loggedIn = AccountUtils.isLoggedIn(Aptoide.getContext());
request.nview = "response";
request.filters = Aptoide.filters;
request.mature = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).getBoolean(Constants.MATURE_CHECK_BOX, false);
request.aptoideVercode = AptoideUtils.UI.getVerCode(Aptoide.getContext());
request.lang = AptoideUtils.StringUtils.getMyCountryCode(Aptoide.getContext());
return request;
}
public static GetStoreWidgetRequestv7 buildStoreWidgetRequest(long storeId, String actionUrl) {
GetStoreWidgetRequestv7 request = new GetStoreWidgetRequestv7(actionUrl, AptoideUtils.UI.getBucketSize());
request.loggedIn = AccountUtils.isLoggedIn(Aptoide.getContext());
request.nview = "response";
request.filters = Aptoide.filters;
request.mature = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).getBoolean(Constants.MATURE_CHECK_BOX, false);
request.aptoideVercode = AptoideUtils.UI.getVerCode(Aptoide.getContext());
request.lang = AptoideUtils.StringUtils.getMyCountryCode(Aptoide.getContext());
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeId);
if (login != null) {
request.user = login.getUsername();
request.password = login.getPasswordSha1();
}
return request;
}
public static GetListViewItemsRequestv7 buildViewItemsRequest(String storeName, String actionUrl, String layout, int offset) {
GetListViewItemsRequestv7 request = new GetListViewItemsRequestv7(actionUrl, layout, UI.getBucketSize(), offset);
request.loggedIn = AccountUtils.isLoggedIn(Aptoide.getContext());
request.nview = "response";
request.filters = Aptoide.filters;
request.mature = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).getBoolean(Constants.MATURE_CHECK_BOX, false);
request.aptoideVercode = AptoideUtils.UI.getVerCode(Aptoide.getContext());
request.lang = AptoideUtils.StringUtils.getMyCountryCode(Aptoide.getContext());
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeName);
if (login != null) {
request.user = login.getUsername();
request.password = login.getPasswordSha1();
}
return request;
}
private static GetAppRequest buildGetAppRequest(String storeName) {
GetAppRequest request = new GetAppRequest(UI.getBucketSize());
request.token = SecurePreferences.getInstance().getString("access_token", null);
request.filters = Aptoide.filters;
request.mature = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).getBoolean(Constants.MATURE_CHECK_BOX, false);
request.aptoideVercode = AptoideUtils.UI.getVerCode(Aptoide.getContext());
request.lang = AptoideUtils.StringUtils.getMyCountryCode(Aptoide.getContext());
request.storeName = storeName;
final Login login = new AptoideDatabase(Aptoide.getDb()).getStoreLogin(storeName);
if (login != null) {
request.user = login.getUsername();
request.password = login.getPasswordSha1();
}
return request;
}
public static GetAppRequest buildGetAppRequestFromAppId(long appId, String storeName, String packageName) {
GetAppRequest request = buildGetAppRequest(storeName);
request.appId = appId;
request.packageName = packageName;
return request;
}
public static GetAppRequest buildGetAppRequestFromMd5(String md5, String storeName) {
GetAppRequest request = buildGetAppRequest(storeName);
request.md5 = md5;
return request;
}
public static GetAppRequest buildGetAppRequestFromPackageName(String packageName) {
GetAppRequest request = buildGetAppRequest(null);
request.packageName = packageName;
return request;
}
public static RateAppRequest buildRateRequest(long appId, float rate) {
return new RateAppRequest(appId, rate);
}
public static AddApkFlagRequest buildFlagAppRequest(String storeName, String flag, String md5sum) {
AddApkFlagRequest request = new AddApkFlagRequest();
request.setFlag(flag);
request.setMd5sum(md5sum);
request.setRepo(storeName);
return request;
}
public static SearchRequest buildSearchRequest(String query, int limit, int otherReposLimit, int offset, int otherReposOffset) {
SearchRequest request = new SearchRequest();
request.setSearchQuery(query);
ArrayList<String> strings = new ArrayList<>();
AptoideDatabase db = new AptoideDatabase(Aptoide.getDb());
Cursor servers = db.getStoresCursor();
for (servers.moveToFirst(); !servers.isAfterLast(); servers.moveToNext()) {
String name = servers.getString(servers.getColumnIndex("name"));
strings.add(name);
}
String[] arraysStrings = new String[strings.size()];
strings.toArray(arraysStrings);
request.setRepos(arraysStrings);
request.setLimit(limit);
request.setOtherReposLimit(otherReposLimit);
request.setU_offset(otherReposOffset);
request.setOffset(offset);
return request;
}
public static SearchRequest buildSearchRequest(String query, int searchLimit, int otherReposSearchLimit, int offset, String storeName) {
SearchRequest request = buildSearchRequest(query,searchLimit,otherReposSearchLimit,offset,0);
if (storeName!=null && !TextUtils.isEmpty(storeName)) {
String[] arraysStrings = new String[1];
arraysStrings[0] = storeName;
request.setRepos(arraysStrings);
}
return request;
}
}
public static class HWSpecifications {
public static final String TERMINAL_INFO = getModel() + "(" + getProduct() + ")"
+ ";v" + getRelease() + ";" + System.getProperty("os.arch");
public static String getProduct() {
return android.os.Build.PRODUCT.replace(";", " ");
}
public static String getModel() {
return android.os.Build.MODEL.replaceAll(";", " ");
}
public static String getRelease() {
return android.os.Build.VERSION.RELEASE.replaceAll(";", " ");
}
// private static String cpuAbi2;
//
// public static String getDeviceId(Context context) {
// return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
// }
//
/**
* @return the sdkVer
*/
public static int getSdkVer() {
return Build.VERSION.SDK_INT;
}
/**
* @return the screenSize
*/
public static int getScreenSize(Context context) {
return context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
}
public static int getNumericScreenSize(Context context) {
int size = context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
return (size + 1) * 100;
}
/**
* @return the esglVer
*/
public static String getGlEsVer(Context context) {
return ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getDeviceConfigurationInfo().getGlEsVersion();
}
public static int getDensityDpi(Context context) {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager manager = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
manager.getDefaultDisplay().getMetrics(metrics);
int dpi = metrics.densityDpi;
if (dpi <= 120) {
dpi = 120;
} else if (dpi <= 160) {
dpi = 160;
} else if (dpi <= 213) {
dpi = 213;
} else if (dpi <= 240) {
dpi = 240;
} else if (dpi <= 320) {
dpi = 320;
} else if (dpi <= 480) {
dpi = 480;
} else {
dpi = 640;
}
return dpi;
}
public static String getScreenDensity() {
Context context = Aptoide.getContext();
int density = context.getResources().getDisplayMetrics().densityDpi;
switch (density) {
case DisplayMetrics.DENSITY_LOW:
return "ldpi";
case DisplayMetrics.DENSITY_MEDIUM:
return "mdpi";
case DisplayMetrics.DENSITY_HIGH:
return "hdpi";
case DisplayMetrics.DENSITY_XHIGH:
return "xhdpi";
case DisplayMetrics.DENSITY_XXHIGH:
return "xxhdpi";
case DisplayMetrics.DENSITY_XXXHIGH:
return "xxxhdpi";
default:
return "hdpi";
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@SuppressWarnings("deprecation")
public static String getAbis() {
final String[] abis = getSdkVer() >= 21
? Build.SUPPORTED_ABIS
: new String[]{Build.CPU_ABI, Build.CPU_ABI2};
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < abis.length; i++) {
builder.append(abis[i]);
if (i < abis.length - 1) {
builder.append(",");
}
}
return builder.toString();
}
// public static String getCpuAbi() {
// return Build.CPU_ABI;
// }
//
// public static String getCpuAbi2() {
//
// if (getSdkVer() >= 8 && !Build.CPU_ABI2.equals(Build.UNKNOWN)) {
// return Build.CPU_ABI2;
// } else {
// return "";
// }
// }
@Nullable
public static String filters(Context context) {
final ManagerPreferences managerPreferences = ManagerPreferences.getInstance(context);
if (!managerPreferences.preferences.getBoolean("hwspecsChkBox", true)) {
return null;
}
int minSdk = AptoideUtils.HWSpecifications.getSdkVer();
String minScreen = Filters.Screen.values()
[AptoideUtils.HWSpecifications.getScreenSize(context)]
.name()
.toLowerCase(Locale.ENGLISH);
String minGlEs = AptoideUtils.HWSpecifications.getGlEsVer(context);
final int density = AptoideUtils.HWSpecifications.getDensityDpi(context);
String cpuAbi = AptoideUtils.HWSpecifications.getAbis();
int myversionCode = 0;
PackageManager manager = context.getPackageManager();
try {
myversionCode = manager.getPackageInfo(context.getPackageName(), 0).versionCode;
} catch (PackageManager.NameNotFoundException ignore) {
}
String filters = (Build.DEVICE.equals("alien_jolla_bionic") ? "apkdwn=myapp&" : "") + "maxSdk=" + minSdk + "&maxScreen=" + minScreen + "&maxGles=" + minGlEs + "&myCPU=" + cpuAbi + "&myDensity=" + density + "&myApt=" + myversionCode;
return Base64.encodeToString(filters.getBytes(), 0).replace("=", "").replace("/", "*").replace("+", "_").replace("\n", "");
}
// public static final String TERMINAL_INFO = getModel() + "("+ getProduct() + ")"
// +";v"+getRelease()+";"+System.getProperty("os.arch");
//
// public static String getProduct(){
// return android.os.Build.PRODUCT.replace(";", " ");
// }
//
// public static String getModel(){
// return android.os.Build.MODEL.replaceAll(";", " ");
// }
//
//
// public static String getRelease(){
// return android.os.Build.VERSION.RELEASE.replaceAll(";", " ");
// }
}
public static class StringUtils {
public static String getMyCountryCode(Context context) {
return context.getResources().getConfiguration().locale.getLanguage() + "_" + context.getResources().getConfiguration().locale.getCountry();
}
public static String getMyCountry(Context context) {
return context.getResources().getConfiguration().locale.getLanguage();
}
public static String formatBits(long bytes) {
int unit = 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = ("KMGTPE").charAt(exp - 1) + "";
return String.format(Locale.ENGLISH, "%.1f %sb", bytes / Math.pow(unit, exp), pre);
}
public static String formatEta(long eta, String left) {
if (eta > 0) {
long days = eta / (1000 * 60 * 60 * 24);
eta -= days * 1000 * 60 * 60 * 24;
long hours = eta / (1000 * 60 * 60);
eta -= hours * 1000 * 60 * 60;
long minutes = eta / (1000 * 60);
eta -= minutes * 1000 * 60;
long seconds = eta / 1000;
String etaString = "";
if (days > 0) {
etaString += days + "d ";
}
if (hours > 0) {
etaString += hours + "h ";
}
if (minutes > 0) {
etaString += minutes + "m ";
}
if (seconds > 0) {
etaString += seconds + "s";
}
return etaString + " " + left;
}
return "";
}
public static Map<String, String> splitQuery(URI uri) throws UnsupportedEncodingException {
Map<String, String> query_pairs = new LinkedHashMap<String, String>();
String query = uri.getQuery();
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
return query_pairs;
}
public static String withSuffix(String count) {
long countl = 0;
try {
countl = Long.valueOf(count);
} catch (Exception e) {
Logger.printException(e);
}
return withSuffix(countl);
}
public static String withSuffix(long count) {
if (count < 1000) return String.valueOf(count);
int exp = (int) (Math.log(count) / Math.log(1000));
return String.format("%d %c",
(int) (count / Math.pow(1000, exp)),
"kMGTPE".charAt(exp - 1));
}
public static String withDecimalSuffix(long count) {
double result = (double) count;
if (result < 1000) return "" + (int)result;
int exp = (int) (Math.log(result) / Math.log(1000));
String aux = new DecimalFormat("#.#").format(result / Math.pow(1000, exp));
return String.format("%s %c", aux, "kMGTPE".charAt(exp - 1));
}
/**
* <p>Joins the elements of the provided {@code Iterator} into
* a single String containing the provided elements.</p>
*
* <p>No delimiter is added before or after the list.
* A {@code null} separator is the same as an empty String ("").</p>
*
* @param iterator the {@code Iterator} of values to join together, may be null
* @param separator the separator character to use, null treated as ""
* @return the joined String, {@code null} if null iterator input
*/
public static String join(final Iterator<?> iterator, final String separator) {
// handle null, zero and one elements before building a buffer
if (iterator == null) {
return null;
}
if (!iterator.hasNext()) {
return "";
}
final Object first = iterator.next();
if (!iterator.hasNext()) {
@SuppressWarnings( "deprecation" ) // ObjectUtils.toString(Object) has been deprecated in 3.2
final String result = ObjectUtils.toString(first);
return result;
}
// two or more elements
final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
if (first != null) {
buf.append(first);
}
while (iterator.hasNext()) {
if (separator != null) {
buf.append(separator);
}
final Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
}
return buf.toString();
}
/**
* <p>Joins the elements of the provided {@code Iterable} into
* a single String containing the provided elements.</p>
*
* <p>No delimiter is added before or after the list.
* A {@code null} separator is the same as an empty String ("").</p>
*
* @param iterable the {@code Iterable} providing the values to join together, may be null
* @param separator the separator character to use, null treated as ""
* @return the joined String, {@code null} if null iterator input
* @since 2.3
*/
public static String join(final Iterable<?> iterable, final String separator) {
if (iterable == null) {
return null;
}
return join(iterable.iterator(), separator);
}
public static String parseLocalyticsTag(String str) {
return WordUtils.capitalize(str.replace('-', ' '));
}
public static String getFormattedString(Context context, @StringRes int resId, Object... formatArgs) {
String result;
final Resources resources = context.getResources();
try {
result = resources.getString(resId, formatArgs);
}catch (UnknownFormatConversionException ex){
final String resourceEntryName = resources.getResourceEntryName(resId);
final String displayLanguage = Locale.getDefault().getDisplayLanguage();
Logger.e("UnknownFormatConversion", "String: " + resourceEntryName + " Locale: " + displayLanguage);
Crashlytics.log(3, "UnknownFormatConversion", "String: " + resourceEntryName + " Locale: " + displayLanguage);
result = resources.getString(resId);
}
return result;
}
/**
* get rounded value from the given double and remove the .0 if exact number
*
* @param number number to be rounded
* @return rounded number in string format
*/
public static String getRoundedValueFromDouble(double number) {
if (number == (long) number) {
return String.valueOf((long) number);
} else {
return String.format("%.1f", number);
}
}
public static String commaSeparatedValues(List<?> list) {
String s = new String();
if (list.size() > 0) {
s = list.get(0).toString();
for (int i = 1; i < list.size(); i++) {
s += "," + list.get(i).toString();
}
}
return s;
}
}
public static class AccountUtils {
public static boolean isLoggedIn(Context context) {
AccountManager manager = AccountManager.get(context);
return manager.getAccountsByType(Aptoide.getConfiguration().getAccountType()).length != 0;
}
public static boolean isLoggedInOrAsk(Activity activity) {
final AccountManager manager = AccountManager.get(activity);
if (manager.getAccountsByType(Aptoide.getConfiguration().getAccountType()).length == 0) {
manager.addAccount(Aptoide.getConfiguration().getAccountType(),
AptoideConfiguration.AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, null, activity, null, null);
return false;
}
return true;
}
}
public static class SocialMedia {
public static void showTwitter(Context context) {
if (AppUtils.isAppInstalled(context, "com.twitter.android")) {
String url = "http://www.twitter.com/aptoide";
Intent twitterIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(twitterIntent);
// FlurryAgent.logEvent("Opened_Twitter_App");
} else {
Intent intent = new Intent(context, WebViewTwitter.class);
context.startActivity(intent);
// FlurryAgent.logEvent("Opened_Twitter_Webview");
}
}
public static void showFacebook(Context context) {
if (AppUtils.isAppInstalled(context, "com.facebook.katana")) {
Intent sharingIntent;
try {
context.getPackageManager().getPackageInfo("com.facebook.katana", 0);
sharingIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("fb://page/225295240870860"));
context.startActivity(sharingIntent);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (ActivityNotFoundException notFound) {
Toast.makeText(context, context.getString(R.string.not_found), Toast.LENGTH_SHORT).show();
}
} else {
Intent intent = new Intent(context, WebViewFacebook.class);
context.startActivity(intent);
// FlurryAgent.logEvent("Opened_Facebook_Webview");
}
}
public static void acceptTimeline() {
Preferences.putBooleanAndCommit(Preferences.TIMELINE_ACEPTED_BOOL, true);
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
ChangeUserSettingsRequest request = new ChangeUserSettingsRequest();
request.addTimeLineSetting(ChangeUserSettingsRequest.TIMELINEACTIVE);
try {
request.loadDataFromNetwork();
} catch (Exception e) {
Logger.printException(e);
}
}
});
}
}
public static class AppUtils {
public static boolean isAppInstalled(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
boolean installed;
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
installed = true;
} catch (PackageManager.NameNotFoundException e) {
installed = false;
}
return installed;
}
public static PackageInfo getPackageInfo(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
try {
return pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) {
// Ignore
}
return null;
}
public static boolean isRooted() {
return findBinary("su");
}
private static boolean findBinary(String binaryName) {
boolean found = false;
String[] places = {"/sbin/", "/system/bin/", "/system/xbin/", "/data/local/xbin/",
"/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/"};
for (String where : places) {
if (new File(where + binaryName).exists()) {
found = true;
break;
}
}
return found;
}
@NonNull
private static void iterateExtras(Bundle extras, String tag) {
for (String key : extras.keySet()) {
Object value = extras.get(key);
if (value != null) {
Log.d(tag, String.format("%s %s (%s)", key, value.toString(), value.getClass().getName()));
}
}
}
public static void fillPermissionsForTableLayout(Context context, TableLayout mPermissionsTable, List<ApkPermissionGroup> apkPermissions) {
final int ZERO_DIP = 0;
final float WEIGHT_ONE = 1f;
TableRow tr = new TableRow(context);
tr.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
LinearLayout linearLayout;
int items = 0;
for (int i = 0; i <= apkPermissions.size(); i++) {
if (i >= apkPermissions.size()) {
if (tr.getChildCount() > 0) {
// there's still a TableRow left that needs to be added
tr.setPadding(0, 0, 0, 20);
mPermissionsTable.addView(tr, new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
}
} else {
items ++;
ApkPermissionGroup apkPermission = apkPermissions.get(i);
if (apkPermission != null) {
linearLayout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.row_permission, tr, false);
TextView name = (TextView) linearLayout.findViewById(R.id.permission_name);
name.setText(apkPermission.getName());
for (String s : apkPermission.getDescriptions()) {
TextView description = (TextView) LayoutInflater.from(context).inflate(R.layout.row_description, linearLayout, false);
description.setText(s);
linearLayout.addView(description);
}
tr.addView(linearLayout, new TableRow.LayoutParams(ZERO_DIP, TableRow.LayoutParams.WRAP_CONTENT, WEIGHT_ONE));
if (items % 2 == 0) {
mPermissionsTable.addView(tr, new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
tr = new TableRow(context);
tr.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
}
}
}
}
}
public static List<ApkPermission> parsePermissions(Context context, List<String> permissionArray) {
List<ApkPermission> list = new ArrayList<>();
CharSequence csPermissionGroupLabel;
CharSequence csPermissionLabel;
PackageManager pm = context.getPackageManager();
List<PermissionGroupInfo> lstGroups = pm.getAllPermissionGroups(PackageManager.PERMISSION_GRANTED);
for (String permission : permissionArray) {
for (PermissionGroupInfo pgi : lstGroups) {
try {
List<PermissionInfo> lstPermissions = pm.queryPermissionsByGroup(pgi.name, PackageManager.PERMISSION_GRANTED);
for (PermissionInfo pi : lstPermissions) {
if (pi.name.equals(permission)) {
csPermissionLabel = pi.loadLabel(pm);
csPermissionGroupLabel = pgi.loadLabel(pm);
list.add(new ApkPermission(csPermissionGroupLabel.toString(), csPermissionLabel.toString()));
}
}
} catch (Exception e) {
Logger.printException(e);
}
}
}
Collections.sort(list, new Comparator<ApkPermission>() {
@Override
public int compare(ApkPermission lhs, ApkPermission rhs) {
return lhs.getName().compareTo(rhs.getName());
}
});
return list;
}
public static ArrayList<ApkPermissionGroup> fillPermissionsGroups(List<ApkPermission> permissions) {
ArrayList<ApkPermissionGroup> list = new ArrayList<>();
String prevName = null;
ApkPermissionGroup apkPermission = null;
for (int i = 0; i <= permissions.size(); i++) {
if (i >= permissions.size()) {
if (!list.contains(apkPermission)) {
list.add(apkPermission);
}
} else {
ApkPermission permission = permissions.get(i);
if (!permission.getName().equals(prevName)) {
prevName = permission.getName();
apkPermission = new ApkPermissionGroup(permission.getName(), permission.getDescription());
list.add(apkPermission);
} else {
apkPermission.setDescription(permission.getDescription());
}
}
}
return list;
}
public static void checkPermissions(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (activity.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
activity.requestPermissions(new String[]{Constants.WRITE_EXTERNAL_STORAGE}, 1);
}
}
}
public static long sumFileSizes(long fileSize, GetAppMeta.Obb obb) {
if (obb == null || obb.main == null) {
return fileSize;
} else if (obb.patch == null) {
return fileSize + obb.main.filesize.longValue();
} else {
return fileSize + obb.main.filesize.longValue() + obb.patch.filesize.longValue();
}
}
}
public static class DateTimeUtils extends DateUtils {
private static String mTimestampLabelYesterday;
private static String mTimestampLabelToday;
private static String mTimestampLabelJustNow;
private static String mTimestampLabelMinutesAgo;
private static String mTimestampLabelHoursAgo;
private static String mTimestampLabelHourAgo;
private static String mTimestampLabelDaysAgo;
private static String mTimestampLabelWeekAgo;
private static String mTimestampLabelWeeksAgo;
private static String mTimestampLabelMonthAgo;
private static String mTimestampLabelMonthsAgo;
private static String mTimestampLabelYearAgo;
private static String mTimestampLabelYearsAgo;
private static DateTimeUtils instance;
/**
* Singleton constructor, needed to get access to the application context & strings for i18n
*
* @param context Context
* @return DateTimeUtils singleton instance
* @throws Exception
*/
public static DateTimeUtils getInstance(Context context) {
if (instance == null) {
instance = new DateTimeUtils();
mTimestampLabelYesterday = context.getResources().getString(R.string.WidgetProvider_timestamp_yesterday);
mTimestampLabelToday = context.getResources().getString(R.string.WidgetProvider_timestamp_today);
mTimestampLabelJustNow = context.getResources().getString(R.string.WidgetProvider_timestamp_just_now);
mTimestampLabelMinutesAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_minutes_ago);
mTimestampLabelHoursAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_hours_ago);
mTimestampLabelHourAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_hour_ago);
mTimestampLabelDaysAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_days_ago);
mTimestampLabelWeekAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_week_ago2);
mTimestampLabelWeeksAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_weeks_ago);
mTimestampLabelMonthAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_month_ago);
mTimestampLabelMonthsAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_months_ago);
mTimestampLabelYearAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_year_ago);
mTimestampLabelYearsAgo = context.getResources().getString(R.string.WidgetProvider_timestamp_years_ago);
}
return instance;
}
/**
* Checks if the given date is yesterday.
*
* @param date - Date to check.
* @return TRUE if the date is yesterday, FALSE otherwise.
*/
private static boolean isYesterday(long date) {
final Calendar currentDate = Calendar.getInstance();
currentDate.setTimeInMillis(date);
final Calendar yesterdayDate = Calendar.getInstance();
yesterdayDate.add(Calendar.DATE, -1);
return yesterdayDate.get(Calendar.YEAR) == currentDate.get(Calendar.YEAR) && yesterdayDate.get(Calendar.DAY_OF_YEAR) == currentDate.get(Calendar.DAY_OF_YEAR);
}
private static String[] weekdays = new DateFormatSymbols().getWeekdays(); // get day names
private static final long millisInADay = 1000 * 60 * 60 * 24;
/**
* Displays a user-friendly date difference string
*
* @param timedate Timestamp to format as date difference from now
* @return Friendly-formatted date diff string
*/
public String getTimeDiffString(Context context, long timedate) {
Calendar startDateTime = Calendar.getInstance();
Calendar endDateTime = Calendar.getInstance();
endDateTime.setTimeInMillis(timedate);
long milliseconds1 = startDateTime.getTimeInMillis();
long milliseconds2 = endDateTime.getTimeInMillis();
long diff = milliseconds1 - milliseconds2;
long hours = diff / (60 * 60 * 1000);
long minutes = diff / (60 * 1000);
minutes = minutes - 60 * hours;
long seconds = diff / (1000);
boolean isToday = DateTimeUtils.isToday(timedate);
boolean isYesterday = DateTimeUtils.isYesterday(timedate);
if (hours > 0 && hours < 12) {
return hours == 1 ? AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_hour_ago, hours) : AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_hours_ago, hours);
} else if (hours <= 0) {
if (minutes > 0)
return AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_minutes_ago, minutes);
else {
return mTimestampLabelJustNow;
}
} else if (isToday) {
return mTimestampLabelToday;
} else if (isYesterday) {
return mTimestampLabelYesterday;
} else if (startDateTime.getTimeInMillis() - timedate < millisInADay * 6) {
return weekdays[endDateTime.get(Calendar.DAY_OF_WEEK)];
} else {
return formatDateTime(context, timedate, DateUtils.FORMAT_NUMERIC_DATE);
}
}
public String getTimeDiffAll(Context context, long time) {
long diffTime = new Date().getTime() - time;
if (isYesterday(time) || isToday(time)) {
getTimeDiffString(context, time);
} else {
if (diffTime < DateUtils.WEEK_IN_MILLIS) {
int diffDays = Double.valueOf(Math.ceil(diffTime / millisInADay)).intValue();
return diffDays == 1 ? mTimestampLabelYesterday : AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_days_ago, diffDays);
} else if (diffTime < DateUtils.WEEK_IN_MILLIS * 4) {
int diffDays = Double.valueOf(Math.ceil(diffTime / WEEK_IN_MILLIS)).intValue();
return diffDays == 1 ? mTimestampLabelMonthAgo : AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_months_ago, diffDays);
} else if (diffTime < DateUtils.WEEK_IN_MILLIS * 4 * 12) {
int diffDays = Double.valueOf(Math.ceil(diffTime / (WEEK_IN_MILLIS * 4))).intValue();
return diffDays == 1 ? mTimestampLabelMonthAgo : AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_months_ago, diffDays);
} else {
int diffDays = Double.valueOf(Math.ceil(diffTime / (WEEK_IN_MILLIS * 4 * 12))).intValue();
return diffDays == 1 ? mTimestampLabelYearAgo : AptoideUtils.StringUtils.getFormattedString(context, R.string.WidgetProvider_timestamp_years_ago, diffDays);
}
}
return getTimeDiffString(context, time);
}
}
public static class VoteUtils {
public static void voteComment(SpiceManager spiceManager, int commentId,
String repoName,
String token,
RequestListener<GenericResponseV2> commentRequestListener,
AddApkCommentVoteRequest.CommentVote vote) {
AddApkCommentVoteRequest commentVoteRequest = new AddApkCommentVoteRequest();
commentVoteRequest.setRepo(repoName);
commentVoteRequest.setToken(token);
commentVoteRequest.setCmtid(commentId);
commentVoteRequest.setVote(vote);
spiceManager.execute(commentVoteRequest, commentRequestListener);
Toast.makeText(Aptoide.getContext(), Aptoide.getContext().getString(R.string.casting_vote), Toast.LENGTH_SHORT).show();
}
}
public static class AdNetworks {
public static String parseString(Context context, String clickUrl) throws IOException, GooglePlayServicesNotAvailableException, GooglePlayServicesRepairableException {
String deviceId = android.provider.Settings.Secure.getString(Aptoide.getContext().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
String myid = PreferenceManager.getDefaultSharedPreferences(context).getString(EnumPreferences.APTOIDE_CLIENT_UUID.name(), "NoInfo");
if (deviceId != null) {
clickUrl = clickUrl.replace("[USER_ANDROID_ID]", deviceId);
}
if (myid != null) {
clickUrl = clickUrl.replace("[USER_UDID]", myid);
}
clickUrl = replaceAdvertisementId(clickUrl, context);
clickUrl = clickUrl.replace("[TIME_STAMP]", String.valueOf(new Date().getTime()));
return clickUrl;
}
private static String replaceAdvertisementId(String clickUrl, Context context) throws IOException, GooglePlayServicesNotAvailableException, GooglePlayServicesRepairableException {
String aaId = "";
if (GoogleServices.checkGooglePlayServices(context)) {
if (AptoideUtils.getSharedPreferences().contains("advertisingIdClient")) {
aaId = AptoideUtils.getSharedPreferences().getString("advertisingIdClient", "");
} else {
try {
aaId = AdvertisingIdClient.getAdvertisingIdInfo(context).getId();
} catch (Exception e) {
// In case we try to do this from a Broadcast Receiver, exception will be thrown.
Logger.w("AptoideUtils", e.getMessage());
}
}
} else {
byte[] data = new byte[16];
String deviceId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(deviceId.hashCode());
secureRandom.nextBytes(data);
aaId = UUID.nameUUIDFromBytes(data).toString();
}
clickUrl = clickUrl.replace("[USER_AAID]", aaId);
return clickUrl;
}
/**
* Execute a simple request (knock at the door) to the given URL.
* @param url
*/
public static void knock(String url) {
OkHttpClient client = new OkHttpClient();
Request click = new Request.Builder().url(url).build();
client.newCall(click).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(Response response) throws IOException {
}
});
}
}
public static class GoogleServices {
public static boolean checkGooglePlayServices(Context context) {
return GooglePlayServicesUtil.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}
}
public static class ServerConnectionUtils {
public static String getErrorCodeFromErrorList(Context context, List<ErrorResponse> errors) {
StringBuilder errorMessage = new StringBuilder();
Integer errorCode;
if (errors == null) {
return "";
}
for (ErrorResponse error : errors) {
if (errors.size()>1) {
errorMessage.append("\n");
}
errorCode = Errors.getErrorsMap().get(error.code);
if (errorCode != null) {
errorMessage.append(context.getString(errorCode));
} else {
errorMessage.append(context.getString(R.string.error_occured));
}
}
if (errors.size()>0&& TextUtils.isEmpty(errorMessage.toString())) {
errorMessage.append(context.getString(R.string.error_occured));
}
return errorMessage.toString();
}
}
public static class Concurrency{
private static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
public static void post(final Activity activity, final Runnable runnable, long delayInMillis) {
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
activity.runOnUiThread(runnable);
}
}, delayInMillis, TimeUnit.MILLISECONDS);
}
}
private static boolean isNullOrEmpty(Object o) {
return o == null || "".equals(o);
}
/**
* this class should have all the utils methods related to crashlytics
*/
public static class CrashlyticsUtils{
public static final String SCREEN_HISTORY = "SCREEN_HISTORY";
public static final String NUMBER_OF_SCREENS = "NUMBER_OF_SCREENS";
public static final String NUMBER_OF_SCREENS_ON_BACK_STACK = "NUMBER_OF_SCREENS_ON_BACK_STACK";
/**
* arrayList with all screen names history
*/
private static ArrayList<String> history = new ArrayList<>();
/**
* this var sets the max screens should be added to history
*/
private static int MAX_HISTORY = 10;
/**
* This saves the number of screens showed
*/
private static int totalNumberScreens = 0;
/**
* This saves the number of screens on back stack
*/
private static int numberScreensOnBackStack = 0;
/**
* this method adds a screen name to the history to be reported to crashlytics
* @param screeName screen name that should be reported to crashlytics
*/
public static void addScreenToHistory (String screeName) {
if (BuildConfig.FABRIC_CONFIGURED) {
addScreen(screeName);
Crashlytics.setString(SCREEN_HISTORY, history.toString());
}
}
/**
* Adds the screen to history.
* @param screeName Name of the screen to add to history.f
*/
private static void addScreen(String screeName) {
if (history.size() >= MAX_HISTORY) {
history.remove(0);
}
history.add(screeName);
}
public static void subsctibeActivityLiveCycleEvent() {
BusProvider.getInstance().register(new LifeCycleMonitor());
}
/**
* Updates the total screens showed and the screens on back stack
*
* @param isAdding Indicates if it's to update the number due to a new screen (true) or not (false)
*/
public static void updateNumberOfScreens(boolean isAdding) {
if (isAdding) {
totalNumberScreens++;
numberScreensOnBackStack++;
Crashlytics.setInt(NUMBER_OF_SCREENS, totalNumberScreens);
Crashlytics.setInt(NUMBER_OF_SCREENS_ON_BACK_STACK, numberScreensOnBackStack);
} else {
numberScreensOnBackStack--;
Crashlytics.setInt(NUMBER_OF_SCREENS_ON_BACK_STACK, numberScreensOnBackStack);
}
}
public static void resetScreenHistory() {
if (history != null) {
history.clear();
}
}
}
}