/*******************************************************************************
* 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;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.aptoide.amethyst.adapters.SpannableRecyclerAdapter;
import com.aptoide.amethyst.analytics.Analytics;
import com.aptoide.amethyst.configuration.AptoideConfiguration;
import com.aptoide.amethyst.database.AptoideDatabase;
import com.aptoide.amethyst.dialogs.AptoideDialog;
import com.aptoide.amethyst.dialogs.DialogPermissions;
import com.aptoide.amethyst.dialogs.FlagApkDialog;
import com.aptoide.amethyst.dialogs.MyAppStoreDialog;
import com.aptoide.amethyst.downloadmanager.model.Download;
import com.aptoide.amethyst.events.BusProvider;
import com.aptoide.amethyst.events.OttoEvents;
import com.aptoide.amethyst.model.json.CheckUserCredentialsJson;
import com.aptoide.amethyst.models.EnumStoreTheme;
import com.aptoide.amethyst.preferences.Preferences;
import com.aptoide.amethyst.preferences.SecurePreferences;
import com.aptoide.amethyst.ui.IMediaObject;
import com.aptoide.amethyst.ui.MyAccountActivity;
import com.aptoide.amethyst.ui.Screenshot;
import com.aptoide.amethyst.ui.Video;
import com.aptoide.amethyst.ui.callbacks.AddCommentCallback;
import com.aptoide.amethyst.utils.AptoideUtils;
import com.aptoide.amethyst.utils.Logger;
import com.aptoide.amethyst.webservices.AddApkFlagRequest;
import com.aptoide.amethyst.webservices.CheckUserCredentialsRequest;
import com.aptoide.amethyst.webservices.json.GetApkInfoJson;
import com.aptoide.amethyst.webservices.v2.AddApkCommentVoteRequest;
import com.aptoide.amethyst.webservices.v2.AddCommentRequest;
import com.aptoide.amethyst.webservices.v2.AlmostGenericResponseV2RequestListener;
import com.aptoide.amethyst.webservices.v2.GetAdsRequest;
import com.aptoide.dataprovider.AptoideSpiceHttpService;
import com.aptoide.dataprovider.webservices.AllCommentsRequest;
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.GetAppModel;
import com.aptoide.dataprovider.webservices.models.v2.GetComments;
import com.aptoide.dataprovider.webservices.models.v3.RateApp;
import com.aptoide.dataprovider.webservices.models.v7.GetApp;
import com.aptoide.dataprovider.webservices.models.v7.GetAppMeta;
import com.aptoide.models.ApkSuggestionJson;
import com.aptoide.models.displayables.Displayable;
import com.aptoide.models.displayables.HeaderRow;
import com.aptoide.models.displayables.MoreVersionsAppViewItem;
import com.aptoide.models.displayables.NoCommentPlaceHolderRow;
import com.aptoide.models.stores.Store;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.crashlytics.android.Crashlytics;
import com.flurry.android.FlurryAgent;
import com.octo.android.robospice.SpiceManager;
import com.octo.android.robospice.exception.NoNetworkException;
import com.octo.android.robospice.persistence.DurationInMillis;
import com.octo.android.robospice.persistence.exception.SpiceException;
import com.octo.android.robospice.request.listener.RequestListener;
import com.octo.android.robospice.retry.RetryPolicy;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.otto.Subscribe;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.aptoide.amethyst.adapter.DividerItemDecoration;
import com.aptoide.amethyst.adapter.ScreenshotsAdapter;
import com.aptoide.amethyst.adapter.store.CommentsStoreAdapter;
import com.aptoide.amethyst.callbacks.AddCommentVoteCallback;
import com.aptoide.amethyst.fragments.store.LatestCommentsFragment;
import com.aptoide.amethyst.openiab.PaidAppPurchaseActivity;
import com.aptoide.amethyst.services.DownloadService;
import com.aptoide.amethyst.ui.MoreCommentsActivity;
import com.aptoide.amethyst.ui.MoreVersionsActivity;
import com.aptoide.amethyst.ui.SearchManager;
import com.aptoide.amethyst.ui.WrappingLinearLayoutManager;
import com.aptoide.amethyst.ui.widget.CircleTransform;
import com.aptoide.amethyst.utils.ReferrerUtils;
import com.aptoide.amethyst.webservices.GetApkInfoRequestFromId;
import lombok.Getter;
import static com.aptoide.dataprovider.webservices.models.v7.GetAppMeta.File.Malware.TRUSTED;
import static com.aptoide.dataprovider.webservices.models.v7.GetAppMeta.File.Malware.UNKNOWN;
import static com.aptoide.dataprovider.webservices.models.v7.GetAppMeta.File.Malware.WARNING;
/**
*
* Created by hsousa
*/
public class AppViewActivity extends AptoideBaseActivity implements AddCommentVoteCallback, FlagApkDialog.ApkFlagCallback {
/**
* True when activity is created.
*/
private boolean lifecycleController = false;
static String TAG = AppViewActivity.class.getSimpleName();
public static final short DOWNGRADE_REQUEST_CODE = 456;
private static final short Purchase_REQUEST_CODE = 30333;
private static final short MAX_VISIBLE_COMMENTS = 3;
private static final short MAX_COMMENTS_REQUEST = 4;
private static final String APP_NOT_AVAILABLE = "410 Gone";
private ResultBundle resultBundle;
private static int getPercentage(Number total, Number quantity) {
if (quantity.intValue() == 0 || total.intValue() == 0) {
return 0;
} else {
return (quantity.intValue() * 100 / total.intValue());
}
}
@Nullable
private static PackageInfo getPackageInfo(Context context, String packageName) {
try {
return context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
static class ResultBundle {
final int requestCode;
final int resultCode;
final Intent data;
public ResultBundle(int requestCode, int resultCode, Intent data) {
this.requestCode = requestCode;
this.resultCode = resultCode;
this.data = data;
}
}
enum BtnInstallState {
INSTALL(0), DOWNGRADE(1), UPDATE(2), OPEN(3), BUY(4);
int state;
BtnInstallState(int state) {
this.state = state;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_view_activity);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.content, AppViewFragment.newInstance(lifecycleController)).commit();
}
}
@Override
protected void onResume() {
super.onResume();
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment != null && resultBundle != null) {
fragment.onActivityResult(resultBundle.requestCode, resultBundle.resultCode, resultBundle.data);
resultBundle = null;
}
lifecycleController = true;
}
@Override
protected void onStop() {
final FragmentManager manager = getSupportFragmentManager();
final Fragment fragment = manager.findFragmentById(R.id.content);
manager.beginTransaction().remove(fragment).commitAllowingStateLoss();
super.onStop();
}
@Override
protected void onRestart() {
super.onRestart();
final AppViewFragment fragment = AppViewFragment.newInstance(lifecycleController);
final FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction()
.replace(R.id.content, fragment)
.commitAllowingStateLoss();
}
@Override
protected String getScreenName() {
return "App View";
}
@Override
public void voteComment(final int commentId, final AddApkCommentVoteRequest.CommentVote vote) {
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment != null) {
((AddCommentVoteCallback) fragment).voteComment(commentId, vote);
}
}
@Override
public void addApkFlagClick(final String flag) {
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment != null) {
((FlagApkDialog.ApkFlagCallback) fragment).addApkFlagClick(flag);
}
}
@Nullable
public DownloadService getService() {
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment != null) {
return ((AppViewFragment) fragment).downloadService;
}
return null;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
resultBundle = new ResultBundle(requestCode, resultCode, data);
}
public static class AppViewFragment extends Fragment implements FlagApkDialog.ApkFlagCallback, AddCommentVoteCallback, ServiceConnection {
private String download_from;
private static final String BADGE_DIALOG_TAG = "badgeDialog";
protected SpiceManager spiceManager = new SpiceManager(AptoideSpiceHttpService.class);
private boolean lifecycleController;
public static AppViewFragment newInstance(boolean lifecycleController) {
AppViewFragment f = new AppViewFragment();
Bundle args = new Bundle();
args.putBoolean("lifecycleController", lifecycleController);
f.setArguments(args);
return f;
}
public AppViewFragment() { }
Toolbar mToolbar;
ImageView mFeaturedGraphic;
ImageView mAppIcon;
View mStoreView;
ImageView mStoreAvatar;
TextView mStoreName;
TextView mStoreUsers;
CollapsingToolbarLayout mCollapsingToolbarLayout;
TextView mVersionName;
TextView mDownloadsNumber;
TextView mFileSize;
RatingBar mRatingBarTop;
RatingBar mRatingBar;
TextView mDescription;
TextView mSeeMore;
LinearLayout mSeeMoreLayout;
Button mButtonInstall;
NestedScrollView mContentView;
ProgressBar mProgressBar;
AppBarLayout mAppBarLayout;
ScrollView layoutNoNetwork;
ScrollView layoutError;
ScrollView layoutError410;
TextView retryError;
TextView retryNoNetwork;
RecyclerView recyclerComments;
TextView mSeeMoreComments;
LinearLayout mLatestVersionLayout;
Button mButtonGetLatest;
Button mButtonUninstall;
Button mButtonSubscribe;
RelativeLayout mTrustedLayout;
RelativeLayout mWarningLayout;
RelativeLayout mUnknownLayoutt;
RelativeLayout badgeLayout;
ImageView mBadgeMarket;
ImageView mBadgeSignature;
ImageView mBadgeFlag;
ImageView mBadgeAntiVirus;
LinearLayout mFlagsLayout;
Button mButtonFlagThisApp;
ImageView mArrow;
TextView tvAgvRating;
TextView tvNumberRates;
ProgressBar progressBarRating5;
ProgressBar progressBarRating4;
ProgressBar progressBarRating3;
ProgressBar progressBarRating2;
ProgressBar progressBarRating1;
RatingBar avgRatingBar;
TextView tvNumberOfStarts5;
TextView tvNumberOfStarts4;
TextView tvNumberOfStarts3;
TextView tvNumberOfStarts2;
TextView tvNumberOfStarts1;
TextView tvNumberGoodFlags;
TextView tvNumberFakeFlags;
TextView tvNumberFreezeFlags;
TextView tvNumberLicenceFlags;
TextView tvNumberVirusFlags;
View manualReviewLayout;
LinearLayout mInstallAndLatestVersionLayout;
RelativeLayout mDownloadProgressLayout;
ImageView mActionResume;
TextView mProgressText;
ProgressBar mDownloadingProgress;
RelativeLayout mMoreVersionsLayoutHeader;
Button mMoreVersionsLayoutButton;
TextView mMoreVersionsTitle;
TextView mWebsiteLabel;
TextView mEmailLabel;
TextView mPrivacyLabel;
TextView mPermissionsLabel;
RecyclerView mScreenshotsList;
RecyclerView mMoreVersionsList;
int descriptionLines;
private String cpd;
private String[] referrer = new String[1];
private WebView[] webview = new WebView[1];
private boolean fromSponsored;
private DownloadService downloadService;
private volatile CountDownLatch downloadServiceLatch;
////// evil fields from the v6's AppView
private boolean isPaidToschedule = true;
private String installedSignature;
private boolean isFromActivityResult;
private boolean autoDownload;
private boolean isDownloadCompleted;
private int bucketSize;
private int recyclerOffset;
/** See More/Less description logic */
private boolean extended = false;
/** Y coordinate in order to scroll when hiding the description */
int scrollPosition = 0;
/**
* v7 json attributes
*/
@Getter private long appId;
private long adId;
private String signature;
private String path;
private long fileSize; //this is just the fileSize of the apk
private String altPath;
private String appName;
private String versionName;
private int versionCode;
private long downloads;
private String packageName;
private String developer;
private String storeName;
private String storeAvatar;
private EnumStoreTheme storeTheme;
private long storeSubscribers;
private String screen;
private int minSdk;
private GetAppMeta.Pay pay;
private String md5sum;
private String iconUrl;
private float rating;
private long storeId;
private String description;
private String graphic;
private String wUrl;
private String userVote;
private GetAppMeta.Obb obb;
private List<String> permissions;
private GetAppMeta.File.Malware malware;
private String website;
private String email;
private String privacy;
/**
* In v6 is the hashCode of the md5sum. Used as an Id for the downloadService
*/
private long downloadId;
private List<GetAppMeta.Media.Screenshot> screenshots;
private List<GetAppMeta.Media.Video> videos;
/**
* Atributes for comments
*/
protected List<Displayable> displayableCommentsList = new ArrayList<>();
/**
* flag to control when the secondary requests should use cache or not
*/
boolean forceReload;
/**
* Flag to inform if there is a more recent version
*/
boolean latestAvailable;
/**
* When it's not the latest, use this Id to call a new AppViewActivity
*/
long latestAppId;
/**
* Flag to inform if the app is an update to an already installed app
*/
boolean isUpdate;
/**
* Controls if the App is installed
*/
boolean isInstalled;
/**
* Used to control the cache of GetApkInfo, for the "pay app" use-case
*/
private boolean refreshOnResume;
/**
* When we want an app to start autoDownloading <b>without</b> showing the yes/no dialog
* (but can still show the "Root" dialog)
*/
boolean forceAutoDownload;
private ApkSuggestionJson.Ads appSuggested;
private RequestManager glide;
/**
* Used to control when we need to refresh the install/open button when coming back from the onResume
*/
private boolean reloadButtons;
private ResultBundle resultBundle;
private RequestListener<GetAppModel> listener = new RequestListener<GetAppModel>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
handleErrorCondition(spiceException);
}
@Override
public void onRequestSuccess(GetAppModel model) {
boolean unrecoverableErrorsFound = false;
try {
appId = model.getApp.nodes.meta.data.id.longValue();
signature = model.getApp.nodes.meta.data.file.signature.sha1;
path = model.getApp.nodes.meta.data.file.path;
altPath = model.getApp.nodes.meta.data.file.pathAlt;
fileSize = model.getApp.nodes.meta.data.file.filesize.longValue();
appName = model.getApp.nodes.meta.data.name;
versionName = model.getApp.nodes.meta.data.file.vername;
versionCode = model.getApp.nodes.meta.data.file.vercode.intValue();
downloads = model.getApp.nodes.meta.data.stats.downloads.longValue();
packageName = model.getApp.nodes.meta.data.packageName;
developer = model.getApp.nodes.meta.data.developer.name;
website = model.getApp.nodes.meta.data.developer.website;
email = model.getApp.nodes.meta.data.developer.email;
privacy = model.getApp.nodes.meta.data.developer.privacy;
storeName = model.getApp.nodes.meta.data.store.name;
storeAvatar = model.getApp.nodes.meta.data.store.avatar;
storeSubscribers = model.getApp.nodes.meta.data.store.stats.subscribers.longValue();
storeTheme = EnumStoreTheme.get(model.getApp.nodes.meta.data.store.appearance.theme);
screen = model.getApp.nodes.meta.data.file.hardware.screen;
minSdk = model.getApp.nodes.meta.data.file.hardware.sdk.intValue();
pay = model.getApp.nodes.meta.data.pay;
md5sum = model.getApp.nodes.meta.data.file.md5sum;
iconUrl = AptoideUtils.UI.parseIcon(getActivity(), model.getApp.nodes.meta.data.icon);
rating = model.getApp.nodes.meta.data.stats.rating.avg.floatValue();
screenshots = model.getApp.nodes.meta.data.media.screenshots;
videos = model.getApp.nodes.meta.data.media.videos;
graphic = model.getApp.nodes.meta.data.graphic;
wUrl = model.getApp.nodes.meta.data.urls.w;
storeId = model.getApp.nodes.meta.data.store.id.longValue();
description = model.getApp.nodes.meta.data.media.description;
downloadId = md5sum.hashCode();
obb = model.getApp.nodes.meta.data.obb;
permissions = model.getApp.nodes.meta.data.file.usedPermissions;
malware = model.getApp.nodes.meta.data.file.malware;
Analytics.ViewedApplication.view(packageName, developer, download_from);
if (model.getApp.nodes.versions != null && !model.getApp.nodes.versions.list.isEmpty() &&
model.getApp.nodes.meta.data.file.vercode.longValue() < model.getApp.nodes.versions.list.get(0).file.vercode.longValue()) {
latestAvailable = true;
latestAppId = model.getApp.nodes.versions.list.get(0).id.longValue();
}
} catch (Exception e) {
Crashlytics.logException(e);
Crashlytics.setLong("appId", appId);
Crashlytics.setString("packageName", packageName);
Crashlytics.setString("md5sum", md5sum);
handleErrorCondition(e);
unrecoverableErrorsFound = true;
}
if (!unrecoverableErrorsFound) {
handleSuccessCondition();
updateUI();
updateBadges();
updateFlags(model.getApp);
populateScreenShotsView();
populateSeeMore();
populatePermissionsTable(model.getApp);
updateStoreInfo();
checkInstallation();
handleLatestVersionLogic();
populateMoreVersions(model);
requestComments(false);
showDialogIfComingFromBrowser();
showDialogIfComingFromAPKFY();
populateRatings(model.getApp);
if (!fromSponsored) {
new AppViewMiddleSuggested((AppViewActivity) getActivity(), getView().findViewById(R.id.middleAppViewContainer), spiceManager, appId, packageName, model
.getApp.nodes.meta.data.media.keywords);
getOrganicAds();
}
if (isFromActivityResult || forceAutoDownload) {
download();
}
if (resultBundle != null) {
onActivityResult(resultBundle.requestCode, resultBundle.resultCode, resultBundle.data);
resultBundle = null;
}
}
}
};
private boolean isApkFy;
private static boolean isApkFyDialogShowed = false;
private void showDialogIfComingFromAPKFY() {
if (obb != null ) {
AptoideUtils.AppUtils.checkPermissions(getActivity());
}
isApkFy = getActivity().getIntent().getBooleanExtra(Constants.FROM_APKFY_KEY, false);
if (isApkFy && !isPaidApp() && !isApkFyDialogShowed) {
isApkFyDialogShowed = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(Aptoide.getContext()).edit();
edit.putString(AptoideConfiguration.PREF_PATH_CACHE_APK, Aptoide.getContext().getFilesDir().getPath()).apply();
}
final InstallListener installListener = new InstallListener(iconUrl, appName, versionName, packageName, md5sum, isPaidApp());
DialogFragment dialog = AptoideDialog.myAppInstall(appName, installListener, null);
AptoideDialog.showDialogAllowingStateLoss(dialog, getChildFragmentManager(), Constants.FROM_APKFY_KEY);
}
}
private RequestListener<GetApkInfoJson> getApkInfoJsonRequestListener = new RequestListener<GetApkInfoJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) { }
@Override
public void onRequestSuccess(GetApkInfoJson getApkInfoJson) {
final GetApkInfoJson.Payment payment = getApkInfoJson.getPayment();
Logger.d("AppViewActivity", "User_ID: " + SecurePreferences.getInstance().getInt("User_ID", 0));
getActivity().supportInvalidateOptionsMenu();
if (!getApkInfoJson.getStatus().equals("OK")) {
return;
}
if (getApkInfoJson.getPayment().status.equals("OK")) {
mButtonInstall.setText(R.string.install);
InstallListener installListener = new InstallListener(iconUrl, appName, versionName, packageName, md5sum, true);
mButtonInstall.setOnClickListener(installListener);
mButtonInstall.setVisibility(View.VISIBLE);
path = getApkInfoJson.getApk().getPath();
} else {
mButtonInstall.setText(getString(R.string.buy) + " (" + payment.symbol + " " + payment.getAmount() + ")");
mButtonInstall.setVisibility(View.VISIBLE);
final Activity thisActivity = getActivity();
if (SecurePreferences.getInstance().getInt("User_ID", 0) == 0) {
Logger.d("AppViewActivity", "is 0, making request");
CheckUserCredentialsRequest request = CheckUserCredentialsRequest.buildDefaultRequest(thisActivity, SecurePreferences.getInstance().getString("access_token", null));
spiceManager.execute(request, new RequestListener<CheckUserCredentialsJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
Toast.makeText(Aptoide.getContext(), R.string.error_occured, Toast.LENGTH_SHORT).show();
}
@Override
public void onRequestSuccess(CheckUserCredentialsJson checkUserCredentialsJson) {
if ("OK".equals(checkUserCredentialsJson.getStatus())) {
SharedPreferences.Editor securePreferences = SecurePreferences.getInstance().edit();
securePreferences.putInt("User_ID", checkUserCredentialsJson.getId());
Logger.d("AppViewActivity", "updating user id to " + checkUserCredentialsJson.getId());
securePreferences.commit();
} else {
Toast.makeText(Aptoide.getContext(), R.string.error_occured, Toast.LENGTH_SHORT).show();
}
}
});
}
mButtonInstall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FlurryAgent.logEvent("App_View_Clicked_On_Buy_Button");
final AccountManager accountManager = AccountManager.get(thisActivity);
final Account[] accounts = accountManager.getAccountsByType(Aptoide.getConfiguration().getAccountType());
if (accounts.length > 0) {
final Intent i = new Intent(thisActivity, PaidAppPurchaseActivity.class);
i.putExtra("packageName", packageName);
i.putExtra("ID", payment.metadata.id);
i.putExtra("user", accounts[0].name);
i.putExtra("icon", iconUrl);
i.putExtra("label", appName);
i.putExtra("price", payment.amount.floatValue());
i.putExtra("currency_symbol", payment.symbol);
i.putParcelableArrayListExtra("PaymentServices", new ArrayList<Parcelable>(payment.payment_services));
startActivityForResult(i, Purchase_REQUEST_CODE);
} else {
Toast.makeText(Aptoide.getContext(), "You need to login to purchase.", Toast.LENGTH_LONG).show();
accountManager.addAccount(Aptoide.getConfiguration().getAccountType(), AptoideConfiguration.AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, null, thisActivity, new AccountManagerCallback<Bundle>() {
@Override
public void run(AccountManagerFuture<Bundle> bundleAccountManagerFuture) {
refreshOnResume = true;
}
}, new Handler(Looper.getMainLooper()));
}
}
});
}
mButtonInstall.setVisibility(View.VISIBLE);
}
};
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
glide = Glide.with(this);
lifecycleController = getArguments().getBoolean("lifecycleController");
if (savedInstanceState != null) {
appId = savedInstanceState.getLong(Constants.APP_ID_KEY);
appName = savedInstanceState.getString(Constants.APPNAME_KEY);
fileSize = savedInstanceState.getLong(Constants.FILESIZE_KEY);
downloadId = savedInstanceState.getLong(Constants.DOWNLOAD_ID_KEY);
downloads = savedInstanceState.getLong(Constants.DOWNLOADS_KEY);
storeId = savedInstanceState.getLong(Constants.STOREID_KEY);
storeAvatar = savedInstanceState.getString(Constants.STOREAVATAR_KEY);
packageName = savedInstanceState.getString(Constants.PACKAGENAME_KEY);
versionName = savedInstanceState.getString(Constants.VERSIONNAME_KEY);
md5sum = savedInstanceState.getString(Constants.MD5SUM_KEY);
} else {
forceAutoDownload = getActivity().getIntent().getBooleanExtra("forceAutoDownload", false);
}
}
@Nullable
@Override
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
BusProvider.getInstance().register(this);
spiceManager.start(getActivity());
final View view = inflater.inflate(R.layout.fragment_app_view, container, false);
bindViews(view);
recyclerOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
bucketSize = AptoideUtils.UI.getBucketSize();
mRatingBar.setOnRatingBarChangeListener(new RatingBarClickListener());
return view;
}
private void bindViews(View view) {
mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
mFeaturedGraphic = (ImageView) view.findViewById(R.id.featured_graphic);
mAppIcon = (ImageView) view.findViewById(R.id.app_icon);
mStoreView = (View) view.findViewById(R.id.store);
mStoreAvatar = (ImageView) view.findViewById(R.id.store_avatar);
mStoreName = (TextView) view.findViewById(R.id.store_name);
mStoreUsers = (TextView) view.findViewById(R.id.store_number_users);
mCollapsingToolbarLayout = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
mVersionName = (TextView) view.findViewById(R.id.versionName);
mDownloadsNumber = (TextView) view.findViewById(R.id.downloads_number);
mFileSize = (TextView) view.findViewById(R.id.file_size);
mRatingBarTop = (RatingBar) view.findViewById(R.id.rating_bar_top);
mRatingBar = (RatingBar) view.findViewById(R.id.ratingbar_appview);
mDescription = (TextView) view.findViewById(R.id.description);
mSeeMore = (TextView) view.findViewById(R.id.see_more_button);
mSeeMoreLayout = (LinearLayout) view.findViewById(R.id.see_more_layout);
mButtonInstall = (Button) view.findViewById(R.id.btn_install);
mContentView = (NestedScrollView) view.findViewById(R.id.scrollview_content);
mProgressBar = (ProgressBar) view.findViewById(R.id.progress);
mAppBarLayout = (AppBarLayout) view.findViewById(R.id.appbar);
layoutNoNetwork = (ScrollView) view.findViewById(R.id.no_network_connection);
layoutError = (ScrollView) view.findViewById(R.id.error);
layoutError410 = (ScrollView) view.findViewById(R.id.error410);
retryError = (TextView) view.findViewById(R.id.retry_error);
retryNoNetwork = (TextView) view.findViewById(R.id.retry_no_network);
recyclerComments = (RecyclerView) view.findViewById(R.id.appview_comments_list);
mSeeMoreComments = (TextView) view.findViewById(R.id.see_more_comments);
mLatestVersionLayout = (LinearLayout) view.findViewById(R.id.latestversion_layout);
mButtonGetLatest = (Button) view.findViewById(R.id.btn_get_latest);
mButtonUninstall = (Button) view.findViewById(R.id.btn_uninstall);
mButtonSubscribe = (Button) view.findViewById(R.id.btn_subscribe);
mTrustedLayout = (RelativeLayout) view.findViewById(R.id.trusted_layout);
mWarningLayout = (RelativeLayout) view.findViewById(R.id.warning_layout);
mUnknownLayoutt = (RelativeLayout) view.findViewById(R.id.unknown_layout);
badgeLayout = (RelativeLayout) view.findViewById(R.id.badge_layout);
mBadgeMarket = (ImageView) view.findViewById(R.id.iv_market_badge);
mBadgeSignature = (ImageView) view.findViewById(R.id.iv_signature_badge);
mBadgeFlag = (ImageView) view.findViewById(R.id.iv_flag_badge);
mBadgeAntiVirus = (ImageView) view.findViewById(R.id.iv_antivirus_badge);
mFlagsLayout = (LinearLayout) view.findViewById(R.id.flags_layout);
mButtonFlagThisApp = (Button) view.findViewById(R.id.btn_flag_this_app);
mArrow = (ImageView) view.findViewById(R.id.iv_arrow);
tvAgvRating = (TextView) view.findViewById(R.id.appview_avg_rating);
tvNumberRates = (TextView) view.findViewById(R.id.tv_number_of_rates);
progressBarRating5 = (ProgressBar) view.findViewById(R.id.appview_rating_bar5);
progressBarRating4 = (ProgressBar) view.findViewById(R.id.appview_rating_bar4);
progressBarRating3 = (ProgressBar) view.findViewById(R.id.appview_rating_bar3);
progressBarRating2 = (ProgressBar) view.findViewById(R.id.appview_rating_bar2);
progressBarRating1 = (ProgressBar) view.findViewById(R.id.appview_rating_bar1);
avgRatingBar = (RatingBar) view.findViewById(R.id.appview_rating_bar_avg);
tvNumberOfStarts5 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number5);
tvNumberOfStarts4 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number4);
tvNumberOfStarts3 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number3);
tvNumberOfStarts2 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number2);
tvNumberOfStarts1 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number1);
tvNumberGoodFlags = (TextView) view.findViewById(R.id.number_good_flags);
tvNumberFakeFlags = (TextView) view.findViewById(R.id.number_fake_flags);
tvNumberFreezeFlags = (TextView) view.findViewById(R.id.number_freeze_flags);
tvNumberLicenceFlags = (TextView) view.findViewById(R.id.number_licence_flags);
tvNumberVirusFlags = (TextView) view.findViewById(R.id.number_virus_flags);
manualReviewLayout = (View) view.findViewById(R.id.manual_reviewed_message_layout);
mInstallAndLatestVersionLayout = (LinearLayout) view.findViewById(R.id.install_and_latest_version_layout);
mDownloadProgressLayout = (RelativeLayout) view.findViewById(R.id.download_progress_layout);
mActionResume = (ImageView) view.findViewById(R.id.ic_action_resume);
mProgressText = (TextView) view.findViewById(R.id.text_progress);
mDownloadingProgress = (ProgressBar) view.findViewById(R.id.downloading_progress);
mMoreVersionsLayoutHeader = (RelativeLayout) view.findViewById(R.id.more_layout);
mMoreVersionsLayoutButton = (Button) view.findViewById(R.id.more);
mMoreVersionsTitle = (TextView) view.findViewById(R.id.title);
mWebsiteLabel = (TextView) view.findViewById(R.id.website_label);
mEmailLabel = (TextView) view.findViewById(R.id.email_label);
mPrivacyLabel = (TextView) view.findViewById(R.id.privacy_policy_label);
mPermissionsLabel = (TextView) view.findViewById(R.id.permissions_label);
mScreenshotsList = (RecyclerView) view.findViewById(R.id.screenshots_list);
mMoreVersionsList = (RecyclerView) view.findViewById(R.id.more_versions_recycler);
descriptionLines = view.getContext().getResources().getInteger(R.integer.minimum_description_lines);
}
@Override
public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final AppViewActivity appViewActivity = (AppViewActivity) getActivity();
appViewActivity.setSupportActionBar(mToolbar);
ActionBar supportActionBar = appViewActivity.getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setDisplayHomeAsUpEnabled(true);
}
continueLoading();
}
@Override
public void onStart() {
super.onStart();
downloadServiceLatch = new CountDownLatch(1);
getActivity().bindService(new Intent(getActivity(), DownloadService.class), this, BIND_AUTO_CREATE);
}
@Override
public void onResume() {
super.onResume();
if (pay != null && pay.price != null) {
setupInstallButton();
}
if (reloadButtons) {
checkInstallation();
updateStoreInfo();
handleLatestVersionLogic();
reloadButtons = false;
}
populateDownloadUI();
}
@Override
public void onStop() {
if (downloadService != null) {
// downloadService = null;
getActivity().unbindService(this);
}
super.onStop();
}
@Override
public void onDestroyView() {
BusProvider.getInstance().unregister(this);
spiceManager.shouldStop();
if (webview[0] != null) {
webview[0].removeAllViews();
webview[0].destroy();
}
AptoideUtils.UI.unbindDrawables(getView());
super.onDestroyView();
}
@Override
public void onDestroy() {
super.onDestroy();
// Aptoide.getRefWatcher(getContext()).watch(this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong(Constants.APP_ID_KEY, appId);
outState.putString(Constants.MD5SUM_KEY, md5sum);
outState.putString(Constants.APPNAME_KEY, appName);
outState.putString(Constants.ICON_KEY, iconUrl);
outState.putLong(Constants.DOWNLOADS_KEY, downloads);
outState.putFloat(Constants.RATING_KEY, rating);
outState.putString(Constants.GRAPHIC_KEY, graphic);
outState.putLong(Constants.FILESIZE_KEY, fileSize);
outState.putLong(Constants.STOREID_KEY, storeId);
outState.putString(Constants.STORENAME_KEY, storeName);
outState.putString(Constants.PACKAGENAME_KEY, packageName);
outState.putString(Constants.VERSIONNAME_KEY, versionName);
outState.putLong(Constants.DOWNLOAD_ID_KEY, downloadId);
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_appview_activity, menu);
SearchManager.setupSearch(menu, getActivity());
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int i = item.getItemId();
if (i == android.R.id.home) {
getActivity().onBackPressed();
return true;
} else if (i == R.id.menu_share) {
FlurryAgent.logEvent("App_View_Clicked_On_Share_Button");
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.install) + " \"" + appName + "\"");
sharingIntent.putExtra(Intent.EXTRA_TEXT, wUrl);
if (wUrl != null) {
startActivity(Intent.createChooser(sharingIntent, getString(R.string.share)));
}
} else if (i == R.id.menu_schedule) {
new AptoideDatabase(Aptoide.getDb()).scheduledDownloadIfMd5(packageName, md5sum, versionName, storeName, appName, iconUrl);
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == DOWNGRADE_REQUEST_CODE) {
try {
// md5sum is not loaded yet
if (md5sum == null) {
resultBundle = new ResultBundle(requestCode, resultCode, data);
return;
}
getActivity().getPackageManager().getPackageInfo(packageName, 0);
Toast.makeText(getActivity(), getString(R.string.downgrade_requires_uninstall), Toast.LENGTH_SHORT).show();
} catch (PackageManager.NameNotFoundException e) {
isFromActivityResult = true;
executeSpiceRequestWithMd5(md5sum, storeName);
}
} else if (requestCode == Purchase_REQUEST_CODE) {
Logger.d("AppViewActivity", "AppViewActivity onActivityResult Purchase_REQUEST_CODE");
if (resultCode == RESULT_OK) {
refreshOnResume = true;
autoDownload = false;
}
}
}
@Override
public void onServiceConnected(final ComponentName name, final IBinder service) {
downloadService = ((DownloadService.LocalBinder) service).getService();
if (downloadService.getDownload(downloadId).getDownload() != null) {
onDownloadUpdate(downloadService.getDownload(downloadId).getDownload());
} else {
mInstallAndLatestVersionLayout.setVisibility(View.VISIBLE);
mDownloadProgressLayout.setVisibility(View.GONE);
}
downloadServiceLatch.countDown();
}
@Override
public void onServiceDisconnected(final ComponentName name) { }
private void populateSeeMore() {
if (description != null && description.length() > 250) {
try {
// Fix for AN-348: replace the & with & (that's was causing the pushback buffer full)
mDescription.setText(Html.fromHtml(description.replace("\n", "<br/>").replace("&", "&")));
mDescription.setMovementMethod(LinkMovementMethod.getInstance());
mSeeMoreLayout.setOnClickListener(extendListener);
} catch (Exception e) {
Logger.printException(e);
mSeeMoreLayout.setVisibility(View.GONE);
mDescription.setText(getString(R.string.error_APK_Description));
}
} else {
mSeeMoreLayout.setVisibility(View.GONE);
mDescription.setText(getString(R.string.error_APK_Description));
}
}
private void populateRatings(GetApp getApp) {
if (getApp.nodes == null || getApp.nodes.meta == null || getApp.nodes.meta.data== null
|| getApp.nodes.meta.data.stats == null|| getApp.nodes.meta.data.stats.rating == null){
return;
}
GetAppMeta.Stats.Rating ratings = getApp.nodes.meta.data.stats.rating;
try {
float numberfloat = ratings.avg.floatValue();
//Avg ratings
tvAgvRating.setText(String.format("%.1f", numberfloat));
} catch (NullPointerException | IllegalFormatException e) {
tvAgvRating.setText(ratings.avg.toString());
}
long numberVotes = ratings.votes.get(0).count.longValue() + ratings.votes.get(1).count.longValue()
+ ratings.votes.get(2).count.longValue() + ratings.votes.get(3).count.longValue()
+ ratings.votes.get(4).count.longValue();
tvNumberRates.setText(String.valueOf(numberVotes));
avgRatingBar.setRating(ratings.avg.floatValue());
//rating bars
progressBarRating5.setProgress(getPercentage(numberVotes, ratings.votes.get(0).count));
tvNumberOfStarts5.setText(ratings.votes.get(0).count.toString());
progressBarRating4.setProgress(getPercentage(numberVotes, ratings.votes.get(1).count));
tvNumberOfStarts4.setText(ratings.votes.get(1).count.toString());
progressBarRating3.setProgress(getPercentage(numberVotes, ratings.votes.get(2).count));
tvNumberOfStarts3.setText(ratings.votes.get(2).count.toString());
progressBarRating2.setProgress(getPercentage(numberVotes, ratings.votes.get(3).count));
tvNumberOfStarts2.setText(ratings.votes.get(3).count.toString());
progressBarRating1.setProgress(getPercentage(numberVotes, ratings.votes.get(4).count));
tvNumberOfStarts1.setText(ratings.votes.get(4).count.toString());
}
private void populatePermissionsTable(final GetApp getApp) {
String websiteAux;
String emailAux;
final String privacyAux;
if (TextUtils.isEmpty(website)) {
websiteAux = getString(R.string.na);
} else {
websiteAux = website;
mWebsiteLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (AptoideUtils.Algorithms.copyToClipBoard(getActivity(), website)) {
Toast.makeText(getActivity(), R.string.website_copied, Toast.LENGTH_SHORT).show();
}
}
});
}
if (TextUtils.isEmpty(email)) {
emailAux = getString(R.string.na);
} else {
emailAux = email;
mEmailLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (AptoideUtils.Algorithms.copyToClipBoard(getActivity(), email)) {
Toast.makeText(getActivity(), R.string.email_copied, Toast.LENGTH_SHORT).show();
}
}
});
}
if (TextUtils.isEmpty(privacy)) {
privacyAux = getString(R.string.na);
} else {
privacyAux = privacy;
mPrivacyLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (AptoideUtils.Algorithms.copyToClipBoard(getActivity(), privacyAux)) {
Toast.makeText(getActivity(), R.string.privacy_copied, Toast.LENGTH_SHORT).show();
}
}
});
}
// if (TextUtils.isEmpty(email)) {
// email = getString(R.string.na);
// }
// if (TextUtils.isEmpty(privacy)) {
// privacy = getString(R.string.na);
// }
mWebsiteLabel.setText(Html.fromHtml(AptoideUtils.StringUtils.getFormattedString(getActivity(), R.string.website, websiteAux)));
mEmailLabel.setText(Html.fromHtml(AptoideUtils.StringUtils.getFormattedString(getActivity(), R.string.email, emailAux)));
mPrivacyLabel.setText(Html.fromHtml(AptoideUtils.StringUtils.getFormattedString(getActivity(), R.string.privacy_policy, privacyAux)));
if (getApp == null || getApp.nodes == null || getApp.nodes.meta == null || getApp.nodes.meta.data == null
|| getApp.nodes.meta.data.file == null || getApp.nodes.meta.data.file.usedPermissions == null
|| getApp.nodes.meta.data.file.usedPermissions.isEmpty()) {
mPermissionsLabel.setText(getString(R.string.permissions_na));
} else {
mPermissionsLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DialogPermissions dialogPermissions = DialogPermissions.newInstance(getApp, appName, versionName, iconUrl, AptoideUtils.StringUtils.formatBits(AptoideUtils.AppUtils.sumFileSizes(fileSize, obb)));
dialogPermissions.show(getChildFragmentManager(), "");
}
});
}
}
RequestListener<GetComments> requestCommentListener = new RequestListener<GetComments>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
Logger.printException(spiceException);
}
@Override
public void onRequestSuccess(GetComments get) {
forceReload = false;
if (get != null && get.list != null) {
if (get.list.size() > MAX_VISIBLE_COMMENTS) {
mSeeMoreComments.setVisibility(View.VISIBLE);
mSeeMoreComments.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(getActivity(), MoreCommentsActivity.class);
i.putExtra(Constants.STORENAME_KEY, storeName);
i.putExtra(Constants.PACKAGENAME_KEY, packageName);
i.putExtra(Constants.VERSIONNAME_KEY, versionName);
i.putExtra(Constants.EVENT_LABEL, appName); // The label is used to populate the title
// in the MoreActivity
startActivity(i);
}
});
}
displayableCommentsList.clear();
displayableCommentsList.add(new HeaderRow("Comments", false, bucketSize));
if (!get.list.isEmpty()) {
for (int i = 0; i < get.list.size() && i < MAX_VISIBLE_COMMENTS; i++) {
displayableCommentsList.add(LatestCommentsFragment.createComment(get.list.get(i)));
}
displayableCommentsList = LatestCommentsFragment.sortComments(displayableCommentsList);
} else {
displayableCommentsList.add(new NoCommentPlaceHolderRow(bucketSize));
}
CommentsStoreAdapter adapter = new CommentsStoreAdapter(displayableCommentsList, getActivity(), getResources().getColor(EnumStoreTheme.APTOIDE_STORE_THEME_DEFAULT.getStoreHeader()), true, addCommentCallback);
recyclerComments.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(recyclerOffset, recyclerOffset, recyclerOffset, 0);
}
});
recyclerComments.setLayoutManager(new WrappingLinearLayoutManager(getActivity()));
recyclerComments.setNestedScrollingEnabled(false);
recyclerComments.setAdapter(adapter);
}
}
};
AddCommentCallback addCommentCallback = new AddCommentCallback() {
@Override
public void addComment(String comment, String answerTo) {
if (comment != null && comment.length() < Constants.MIN_COMMENT_CHARS) {
Toast.makeText(getActivity(), R.string.error_IARG_100, Toast.LENGTH_LONG).show();
return;
}
AddCommentRequest request = new AddCommentRequest(getActivity());
request.setApkversion(versionName);
request.setPackageName(packageName);
request.setRepo(storeName);
request.setText(comment);
if (answerTo != null) {
request.setAnswearTo(answerTo);
}
spiceManager.execute(request, addCommentRequestListener);
AptoideDialog.pleaseWaitDialog().show(getChildFragmentManager(), "pleaseWaitDialog");
}
};
RequestListener<GenericResponseV2> addCommentRequestListener = new AlmostGenericResponseV2RequestListener() {
@Override
public void CaseOK() {
Toast.makeText(getActivity(), getString(R.string.comment_submitted), Toast.LENGTH_LONG).show();
refresh();
dismissDialog();
}
@Override
public void onRequestFailure(SpiceException spiceException) {
super.onRequestFailure(spiceException);
dismissDialog();
}
@Override
public void onRequestSuccess(GenericResponseV2 genericResponse) {
super.onRequestSuccess(genericResponse);
dismissDialog();
}
protected void dismissDialog() {
DialogFragment pd = (DialogFragment) getChildFragmentManager().findFragmentByTag("pleaseWaitDialog");
if (pd != null) {
pd.dismissAllowingStateLoss();
}
}
};
View.OnClickListener badgeClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
AptoideDialog.badgeDialogV7(malware, appName, malware.rank).show(getFragmentManager(), BADGE_DIALOG_TAG);
}
};
private View.OnClickListener extendListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
extendSeeMore();
}
};
/**
* Callback when dismissing MyAppInstallDialog
*/
DialogInterface.OnDismissListener onDismissListener = new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
if (!new AptoideDatabase(Aptoide.getDb()).existsRepo(storeName)) {
AptoideDialog.addMyAppStore("http://" + storeName + ".store.aptoide.com/", appsAddStoreInterface).show(getChildFragmentManager(), "myAppStore");
}
}
};
/**
* Callback to be provided to a Dialog in order to add a store
*/
MyAppStoreDialog.MyAppsAddStoreInterface appsAddStoreInterface = new MyAppStoreDialog.MyAppsAddStoreInterface() {
@Override
public DialogInterface.OnClickListener getOnMyAppAddStoreListener(final String repo) {
return new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Store store = new Store();
store.setBaseUrl(AptoideUtils.RepoUtils.formatRepoUri(repo));
store.setName(AptoideUtils.RepoUtils.split(repo));
AptoideUtils.RepoUtils.startParse(store.getName(), getActivity(), spiceManager);
}
};
}
};
private void updateFlags(GetApp getApp) {
if (getApp == null || getApp.nodes == null || getApp.nodes.meta == null || getApp.nodes.meta.data == null
|| getApp.nodes.meta.data.file == null || getApp.nodes.meta.data.file.flags == null) {
return;
}
GetAppMeta.File.Flags flags = getApp.nodes.meta.data.file.flags;
if (GetAppMeta.File.Flags.GOOD.equals(flags.review)) {
mFlagsLayout.setVisibility(View.GONE);
mButtonFlagThisApp.setVisibility(View.GONE);
manualReviewLayout.setVisibility(View.VISIBLE);
} else {
manualReviewLayout.setVisibility(View.GONE);
mFlagsLayout.setVisibility(View.VISIBLE);
mButtonFlagThisApp.setVisibility(View.VISIBLE);
mButtonFlagThisApp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (AptoideUtils.AccountUtils.isLoggedIn(getActivity())) {
AptoideDialog.flagAppDialog(userVote).show(getChildFragmentManager(), "flagAppDialog");
} else {
Intent intent = new Intent(getActivity(), MyAccountActivity.class);
getActivity().startActivity(intent);
}
}
});
if (flags.votes != null) {
for (GetAppMeta.File.Flags.Vote vote : flags.votes) {
Number numberVotes = vote.count;
if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.GOOD)) {
tvNumberGoodFlags.setText(String.valueOf(numberVotes));
} else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.FREEZE)) {
tvNumberFreezeFlags.setText(String.valueOf(numberVotes));
} else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.FAKE)) {
tvNumberFakeFlags.setText(String.valueOf(numberVotes));
} else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.LICENSE)) {
tvNumberLicenceFlags.setText(String.valueOf(numberVotes));
} else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.VIRUS)) {
tvNumberVirusFlags.setText(String.valueOf(numberVotes));
}
}
}
}
}
private void updateBadges() {
if (malware == null || malware.rank == null) {
return;
}
badgeLayout.setOnClickListener(badgeClickListener);
switch (malware.rank) {
case TRUSTED:
mTrustedLayout.setVisibility(View.VISIBLE);
mTrustedLayout.setOnClickListener(badgeClickListener);
break;
case WARNING:
mWarningLayout.setVisibility(View.VISIBLE);
mWarningLayout.setOnClickListener(badgeClickListener);
break;
case UNKNOWN:
mUnknownLayoutt.setVisibility(View.VISIBLE);
mUnknownLayoutt.setOnClickListener(badgeClickListener);
break;
}
if (malware.reason != null) {
if (malware.reason.thirdpartyValidated != null && GetAppMeta.File.Malware.GOOGLE_PLAY.equalsIgnoreCase(malware.reason.thirdpartyValidated.store)) {
mBadgeMarket.setVisibility(View.VISIBLE);
}
if (malware.reason.signatureValidated != null && GetAppMeta.File.Malware.PASSED.equals(malware.reason.signatureValidated.status)) {
mBadgeSignature.setVisibility(View.VISIBLE);
}
if (malware.reason.scanned != null && GetAppMeta.File.Malware.PASSED.equals(malware.reason.scanned.status)) {
mBadgeAntiVirus.setVisibility(View.VISIBLE);
}
if (malware.reason.manualQA != null && GetAppMeta.File.Malware.PASSED.equals(malware.reason.manualQA.status)) {
mBadgeFlag.setVisibility(View.VISIBLE);
}
}
}
private void updateStoreInfo() {
final Context context = getActivity();
if (TextUtils.isEmpty(storeAvatar)) {
glide.fromResource().load(R.drawable.ic_avatar_apps).transform(new CircleTransform(context)).into(mStoreAvatar);
} else {
glide.load(storeAvatar).bitmapTransform(new CircleTransform(context)).into(mStoreAvatar);
}
mStoreName.setText(storeName);
mStoreName.setTextColor(getResources().getColor(storeTheme.getStoreHeader()));
mStoreUsers.setText(String.valueOf(storeSubscribers));
if(Build.VERSION.SDK_INT > 10 ) {
mButtonSubscribe.setBackgroundDrawable(getResources().getDrawable(storeTheme.getButtonLayout()));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mButtonSubscribe.setElevation(0);
}
}
mButtonSubscribe.setTextColor(getResources().getColor(storeTheme.getStoreHeader()));
OpenStoreOnClickListener openStoreOnClickListener = new OpenStoreOnClickListener();
mStoreView.setOnClickListener(openStoreOnClickListener);
final boolean subscribed = new AptoideDatabase(Aptoide.getDb()).existsStore(storeId);
if (subscribed) {
int checkmarkDrawable = storeTheme.getCheckmarkDrawable();
mButtonSubscribe.setCompoundDrawablesWithIntrinsicBounds(checkmarkDrawable, 0, 0, 0);
mButtonSubscribe.setText(getString(R.string.appview_subscribed_store_button_text));
mButtonSubscribe.setOnClickListener(openStoreOnClickListener);
} else {
int plusMarkDrawable = storeTheme.getPlusmarkDrawable();
mButtonSubscribe.setCompoundDrawablesWithIntrinsicBounds(plusMarkDrawable, 0, 0, 0);
mButtonSubscribe.setText(getString(R.string.appview_subscribe_store_button_text));
mButtonSubscribe.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AptoideUtils.RepoUtils.startParse(storeName, getActivity(), spiceManager);
}
});
}
}
class OpenStoreOnClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
reloadButtons = true;
final Context context = getActivity();
final Intent intent = StoresActivity.newIntent(context,
storeId, storeName, storeAvatar, storeTheme.ordinal());
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
context.startActivity(intent);
}
}
private void updateUI() {
if (graphic != null) {
glide.load(graphic).into(mFeaturedGraphic);
} else if (screenshots != null && screenshots.size() > 0 && !TextUtils.isEmpty(screenshots.get(0).url)) {
glide.load(screenshots.get(0).url).into(mFeaturedGraphic);
}
if (iconUrl != null) {
glide.load(iconUrl).into(mAppIcon);
}
mVersionName.setText(versionName);
mDownloadsNumber.setText(AptoideUtils.StringUtils.withSuffix(downloads));
mFileSize.setText(AptoideUtils.StringUtils.formatBits(AptoideUtils.AppUtils.sumFileSizes(fileSize, obb)));
mRatingBarTop.setRating(rating);
mCollapsingToolbarLayout.setTitle(appName);
}
private void populateMoreVersions(GetAppModel model) {
GetApp getApp = model.getApp;
mMoreVersionsList.setNestedScrollingEnabled(false);
/**
* If the size of the list is 1, it means it's the own app and should be removed.
*/
if (getApp == null || getApp.nodes == null || getApp.nodes.versions == null || getApp.nodes.versions.list == null
|| getApp.nodes.versions.list.size() < 2) {
mMoreVersionsLayoutHeader.setVisibility(View.GONE);
mMoreVersionsList.setVisibility(View.GONE);
return;
}
mMoreVersionsLayoutButton.setClickable(false);
mMoreVersionsLayoutHeader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), MoreVersionsActivity.class);
intent.putExtra(Constants.PACKAGENAME_KEY, packageName);
intent.putExtra(Constants.EVENT_LABEL, appName);
startActivity(intent);
}
});
mMoreVersionsTitle.setText(R.string.appview_other_versions_in_others_stores);
// AN-227: remove the first app if it's the same as this
if (!model.list.isEmpty()
&& model.list.get(0).versionCode == versionCode) {
model.list.remove(0);
}
// Moar hack: only use one row
List<MoreVersionsAppViewItem> list = new ArrayList<>();
for (int i = 0; i < model.list.size() && i < bucketSize; i++) {
list.add(model.list.get(i));
}
MoreAppViewVersionsAdapter adapter = new MoreAppViewVersionsAdapter(list);
mMoreVersionsList.setAdapter(adapter);
final short recyclerViewOffset = (short) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
mMoreVersionsList.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(recyclerViewOffset, recyclerViewOffset, recyclerViewOffset, recyclerViewOffset);
}
});
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), bucketSize);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (!(mMoreVersionsList.getAdapter() instanceof SpannableRecyclerAdapter)) {
throw new IllegalStateException("RecyclerView adapter must extend SpannableRecyclerAdapter");
}
return AptoideUtils.UI.getSpanSize(mMoreVersionsList, position);
}
});
gridLayoutManager.setSpanCount(bucketSize);
mMoreVersionsList.setLayoutManager(gridLayoutManager);
}
private void setupInstallButton() {
setBtnState();
BtnInstallState state = (BtnInstallState) mButtonInstall.getTag();
switch (state) {
case BUY:
changebtInstalltoBuy();
mButtonInstall.setVisibility(View.GONE);
break;
case DOWNGRADE:
mButtonInstall.setText(R.string.downgrade);
break;
case UPDATE:
mButtonInstall.setText(R.string.update);
break;
case INSTALL:
mButtonInstall.setText(R.string.install);
break;
case OPEN:
mButtonInstall.setText(R.string.open);
changebtInstalltoOpen();
break;
}
}
private void changebtInstalltoBuy() {
GetApkInfoRequestFromId getApkInfoRequestFromId = new GetApkInfoRequestFromId(getActivity());
getApkInfoRequestFromId.setAppId(Long.toString(appId));
spiceManager.execute(getApkInfoRequestFromId, getApkInfoJsonRequestListener);
}
public void setBtnState() {
PackageInfo info = getPackageInfo(getActivity(), packageName);
//check if the app is installed
if (info == null) {
//check if the app is payed
if (pay != null && pay.price.doubleValue() > 0) {
mButtonInstall.setTag(BtnInstallState.BUY);
} else {
mButtonInstall.setTag(BtnInstallState.INSTALL);
}
} else {
if (versionCode > info.versionCode) {
mButtonInstall.setTag(BtnInstallState.UPDATE);
} else if (versionCode < info.versionCode) {
mButtonInstall.setTag(BtnInstallState.DOWNGRADE);
} else {
mButtonInstall.setTag(BtnInstallState.OPEN);
}
}
}
private void checkInstallation() {
mButtonInstall.setEnabled(true);
if (pay != null && pay.price.doubleValue() > 0) {
isPaidToschedule = true;
// mButtonInstall.setVisibility(View.GONE);
InstallListener installListener = new InstallListener(iconUrl, appName, versionName, packageName, md5sum, isPaidApp());
mButtonInstall.setOnClickListener(installListener);
} else {
PackageInfo info = getPackageInfo(getActivity(), packageName);
if (info == null) {
mButtonInstall.setText(getString(R.string.install));
mButtonInstall.setOnClickListener(new InstallListener(iconUrl, appName, versionName, packageName, md5sum, isPaidApp()));
isInstalled = false;
} else {
isInstalled = true;
try {
installedSignature = AptoideUtils.Algorithms.computeSHA1sumFromBytes(info.signatures[0].toByteArray()).toUpperCase(Locale.ENGLISH);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
Logger.printException(e);
}
if (versionCode > info.versionCode) {
isUpdate = true;
mButtonInstall.setText(getString(R.string.update));
mButtonInstall.setEnabled(true);
mButtonInstall.setOnClickListener(new InstallListener(iconUrl, appName, versionName, packageName, md5sum, isPaidApp()));
// UpdateAppVersionInstalled(info.versionName);
} else if (versionCode < info.versionCode) {
isUpdate = false;
mButtonInstall.setText(getString(R.string.downgrade));
mButtonInstall.setOnClickListener(new DowngradeListener(iconUrl, appName, info.versionName, versionName, info.packageName));
// UpdateAppVersionInstalled(info.versionName);
} else {
changebtInstalltoOpen();
}
getActivity().supportInvalidateOptionsMenu();
}
}
setupInstallButton();
}
private void changebtInstalltoOpen() {
final Intent i = getActivity().getPackageManager().getLaunchIntentForPackage(packageName);
mButtonInstall.setText(getString(R.string.open));
if (i != null) {
mButtonInstall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
startActivity(i);
} catch (ActivityNotFoundException e) {
Logger.printException(e);
}
}
});
} else {
mButtonInstall.setEnabled(false);
}
}
/**
* Changes maxLines of the description textView. Needs to be synchronized because it can be
* called simultaneously on two different views.
*/
public synchronized void extendSeeMore() {
/** The MAX_LINES parameter cannot be too long, or the animation will not be seen smoothly */
final int MAX_LINES = 200;
final int ANIMATION_DELAY = 0;
int maxLines;
int[] values;
String text;
if (extended) {
maxLines = descriptionLines;
values = new int[]{MAX_LINES, maxLines};
text = getString(R.string.see_more);
mArrow.setImageDrawable(getResources().getDrawable(R.drawable.ic_down_arrow));
} else {
maxLines = MAX_LINES;
values = new int[]{descriptionLines, maxLines};
text = getString(R.string.see_less);
mArrow.setImageDrawable(getResources().getDrawable(R.drawable.ic_up_arrow));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ObjectAnimator animation = ObjectAnimator.ofInt(mDescription, "maxLines", values);
animation.setDuration(ANIMATION_DELAY).start();
} else {
mDescription.setMaxLines(maxLines);
}
if (extended) {
mContentView.scrollTo(0, scrollPosition);
} else {
scrollPosition = mDescription.getLeft();
}
mSeeMore.setText(text);
extended = !extended;
}
private void getOrganicAds() {
if (lifecycleController) {
return;
}
final GetAdsRequest getAdsRequest = new GetAdsRequest("", false);
getAdsRequest.setLocation("appview");
getAdsRequest.setKeyword("__NULL__");
getAdsRequest.setRepo(storeName);
getAdsRequest.setPackage_name(packageName);
getAdsRequest.setLimit(1);
getAdsRequest.setRetryPolicy(new RetryPolicy() {
@Override
public int getRetryCount() {
return 0;
}
@Override
public void retry(SpiceException e) {
}
@Override
public long getDelayBeforeRetry() {
return 0;
}
});
getAdsRequest.setTimeout(2000);
spiceManager.execute(getAdsRequest, new RequestListener<ApkSuggestionJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
}
@Override
public void onRequestSuccess(ApkSuggestionJson apkSuggestionJson) {
try {
ApkSuggestionJson.Ads appSuggested = apkSuggestionJson.getAds().get(0);
if (apkSuggestionJson.getAds().size() == 0) {
return;
}
if (appSuggested.getPartner() == null) {
return;
}
if (appSuggested.getPartner().getPartnerData() == null) {
return;
}
appSuggested = apkSuggestionJson.getAds().get(0);
String clickUrl = appSuggested.getPartner().getPartnerData().getClick_url();
final String adPackageName = appSuggested.getData().getPackageName();
long id = appSuggested.getData().getId().longValue();
adId = appSuggested.getInfo().getAd_id();
ReferrerUtils.extractReferrer(packageName, appId, adId, -1, clickUrl, spiceManager, null, ReferrerUtils.RETRIES);
OkHttpClient client = new OkHttpClient();
Request cpc_click = new Request.Builder().url(appSuggested.getInfo().getCpc_url()).build();
client.newCall(cpc_click).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(Response response) throws IOException {
}
});
Intent intent = getActivity().getIntent();
intent.putExtra("cpi", appSuggested.getInfo().getCpi_url());
getActivity().setIntent(intent);
} catch (Exception e) {
Logger.printException(e);
}
}
});
}
@Subscribe
public void refreshStoresEvent(OttoEvents.RepoAddedEvent event) {
Toast.makeText(getActivity(), AptoideUtils.StringUtils.getFormattedString(getActivity(), com.aptoide.amethyst.R.string.store_subscribed, storeName), Toast.LENGTH_SHORT).show();
updateStoreInfo();
}
@Subscribe
public void onDownloadEventUpdate(OttoEvents.DownloadEvent download) {
if (downloadService != null && download.getId() == downloadId) {
onDownloadUpdate(downloadService.getDownload(download.getId()).getDownload());
}
}
@Subscribe
public void onInstalledEvent(OttoEvents.InstalledApkEvent event) {
refresh();
}
@Subscribe
public void onUnInstalledEvent(OttoEvents.UnInstalledApkEvent event) {
refresh();
}
@Subscribe
public void onRefresh(OttoEvents.AppViewRefresh event) {
refresh();
}
@Subscribe
public void onDownloadUpdate(OttoEvents.DownloadInProgress event) {
if (event != null) {
Download download = event.getDownload();
onDownloadUpdate(download);
}
}
private void refresh() {
forceReload = true;
executeSpiceRequestWithAppId(appId, storeName, packageName);
}
/**
* Hides the layout with the install button and shows the download progress bar.
* Creates a {@link Download} object and send it to the {@link DownloadService}
*
*/
private void download() {
this.showRootDialog();
Download download = new Download();
download.setId(downloadId);
download.setName(appName);
download.setVersion(versionName);
download.setIcon(iconUrl);
download.setPackageName(packageName);
download.setMd5(md5sum);
download.setPaid(isPaidApp());
if (!isUpdate) {
download.setCpiUrl(getActivity().getIntent().getStringExtra("cpi"));
}
try {
//TODO Main thread synchronization
downloadServiceLatch.await();
} catch (InterruptedException e) {
Logger.printException(e);
}
if (downloadService == null) {
return;
}
downloadService.downloadFromV7WithObb(path, altPath, md5sum, fileSize, appName, packageName, versionName, iconUrl, appId, pay != null, obb, download, permissions);
isFromActivityResult = false;
autoDownload = false;
populateDownloadUI();
}
private void onDownloadUpdate(Download download) {
if (download != null && download.getId() == downloadId) {
mInstallAndLatestVersionLayout.setVisibility(View.GONE);
mDownloadProgressLayout.setVisibility(View.VISIBLE);
switch (download.getDownloadState()) {
case ACTIVE:
mActionResume.setVisibility(View.GONE);
mDownloadingProgress.setIndeterminate(false);
mDownloadingProgress.setProgress(download.getProgress());
mProgressText.setText(download.getProgress() + "% - " + AptoideUtils.StringUtils.formatBits((long) download.getSpeed()) + "/s");
break;
case INACTIVE:
break;
case COMPLETE:
mInstallAndLatestVersionLayout.setVisibility(View.VISIBLE);
mDownloadProgressLayout.setVisibility(View.GONE);
break;
case PENDING:
mActionResume.setVisibility(View.GONE);
mDownloadingProgress.setIndeterminate(false);
mDownloadingProgress.setProgress(download.getProgress());
mProgressText.setText(getString(R.string.download_pending));
break;
case ERROR:
mActionResume.setVisibility(View.VISIBLE);
mProgressText.setText(download.getDownloadState().name());
mDownloadingProgress.setIndeterminate(false);
mDownloadingProgress.setProgress(download.getProgress());
break;
}
}
}
private void setShareTimeLineButton() {
final CheckBox btinstallshare = (CheckBox) getView().findViewById(R.id.btinstallshare);
if (Preferences.getBoolean(Preferences.TIMELINE_ACEPTED_BOOL, false)) {
btinstallshare.setVisibility(View.VISIBLE);
btinstallshare.setChecked(Preferences.getBoolean(Preferences.SHARE_TIMELINE_DOWNLOAD_BOOL, true));
btinstallshare.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final Map<String, String> shareTimelineParams = new HashMap<String, String>();
shareTimelineParams.put("Share_Timeline", String.valueOf(isChecked));
FlurryAgent.logEvent("App_View_Clicked_On_Share_Timeline_Checkbox", shareTimelineParams);
Preferences.putBooleanAndCommit(Preferences.SHARE_TIMELINE_DOWNLOAD_BOOL, isChecked);
}
});
} else {
btinstallshare.setVisibility(View.INVISIBLE);
}
}
private void populateDownloadUI() {
setShareTimeLineButton();
getView().findViewById(R.id.ic_action_cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (downloadService != null) {
FlurryAgent.logEvent("App_View_Canceled_Download");
downloadService.stopDownload(downloadId);
}
}
});
getView().findViewById(R.id.ic_action_resume).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (downloadService != null) {
downloadService.resumeDownload(downloadId);
}
}
});
if (downloadService != null && downloadService.getDownload(downloadId).getDownload() != null) {
onDownloadUpdate(downloadService.getDownload(downloadId).getDownload());
}
if(refreshOnResume) {
spiceManager.removeDataFromCache(GetApkInfoJson.class);
refreshOnResume = false;
}
}
/**
* Will create the views that show images and video screenshots.
*/
private void populateScreenShotsView() {
ArrayList<IMediaObject> mediaObjects = new ArrayList<>();
if(videos != null) {
// Add Videos' screenshots first
for (GetAppMeta.Media.Video video : videos) {
mediaObjects.add(new Video(video.thumbnail, video.url));
}
}
if (screenshots != null) {
for (GetAppMeta.Media.Screenshot screenshot : screenshots) {
mediaObjects.add(new Screenshot(screenshot.url, screenshot.getOrientation()));
}
}
ScreenshotsAdapter adapter = new ScreenshotsAdapter(glide, mediaObjects);
mScreenshotsList.addItemDecoration(new DividerItemDecoration(AptoideUtils.getPixels(getActivity(), 5)));
mScreenshotsList.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
mScreenshotsList.setNestedScrollingEnabled(false); // because otherwise the AppBar won't be collapsed
mScreenshotsList.setAdapter(adapter);
if(mediaObjects.isEmpty()) {
mScreenshotsList.setVisibility(View.GONE);
}
}
private boolean isPaidApp() {
return pay != null && pay.price.doubleValue() > 0;
}
private void handleErrorCondition(Exception e) {
Logger.printException(e);
mProgressBar.setVisibility(View.GONE);
mAppBarLayout.setVisibility(View.GONE);
mContentView.setVisibility(View.GONE);
if (e != null && e.getCause() != null && e.getCause().getMessage() != null && e.getCause().getMessage().equals(APP_NOT_AVAILABLE)) {
layoutError410.setVisibility(View.VISIBLE);
Toolbar mToolbar = (Toolbar) getView().findViewById(R.id.toolbar_410);
final AppViewActivity activity = (AppViewActivity) getActivity();
activity.setSupportActionBar(mToolbar);
ActionBar supportActionBar = activity.getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setTitle("Aptoide");
supportActionBar.setHomeButtonEnabled(true);
supportActionBar.setDisplayHomeAsUpEnabled(true);
}
} else if (e instanceof NoNetworkException) {
layoutError.setVisibility(View.GONE);
layoutNoNetwork.setVisibility(View.VISIBLE);
retryNoNetwork.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mProgressBar != null && layoutNoNetwork != null) {
mProgressBar.setVisibility(View.VISIBLE);
layoutNoNetwork.setVisibility(View.GONE);
}
refresh();
}
});
} else {
showGenericError();
}
}
private void handleSuccessCondition() {
mContentView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
layoutError.setVisibility(View.GONE);
layoutNoNetwork.setVisibility(View.GONE);
mAppBarLayout.setVisibility(View.VISIBLE);
mContentView.setVisibility(View.VISIBLE);
}
private void showGenericError() {
layoutNoNetwork.setVisibility(View.GONE);
layoutError.setVisibility(View.VISIBLE);
retryError.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mProgressBar != null && layoutError != null) {
mProgressBar.setVisibility(View.VISIBLE);
layoutError.setVisibility(View.GONE);
}
refresh();
}
});
}
private void handleLatestVersionLogic() {
if (latestAvailable) {
mLatestVersionLayout.setVisibility(View.GONE);
mButtonUninstall.setVisibility(View.GONE);
mButtonGetLatest.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mButtonGetLatest.setElevation(0);
}
mButtonGetLatest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(getActivity(), AppViewActivity.class);
i.putExtra(Constants.FROM_RELATED_KEY, true);
i.putExtra(Constants.APP_ID_KEY, latestAppId);
i.putExtra(Constants.APPNAME_KEY, appName);
i.putExtra(Constants.PACKAGENAME_KEY, packageName);
i.putExtra(Constants.DOWNLOAD_FROM_KEY, "app_view_more_multiversion");
startActivity(i);
}
});
} else if (isInstalled) {
mButtonGetLatest.setVisibility(View.GONE);
mLatestVersionLayout.setVisibility(View.GONE);
mButtonUninstall.setVisibility(View.VISIBLE);
mButtonUninstall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
reloadButtons = true;
Fragment uninstallFragment = new UninstallRetainFragment();
Bundle args = new Bundle();
args.putString("name", appName);
args.putString("package", packageName);
args.putString("version", versionName);
args.putString("icon", iconUrl);
uninstallFragment.setArguments(args);
getFragmentManager().beginTransaction().add(uninstallFragment, "uninstallFrag").commit();
}
});
} else {
mButtonUninstall.setVisibility(View.GONE);
mButtonGetLatest.setVisibility(View.GONE);
mLatestVersionLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void addApkFlagClick(String flag) {
final DialogFragment dialogFragment = AptoideDialog.pleaseWaitDialog();
dialogFragment.show(getChildFragmentManager(), "pleaseWaitDialog");
AddApkFlagRequest flagRequest = new AddApkFlagRequest();
flagRequest.setRepo(storeName);
flagRequest.setMd5sum(md5sum);
flagRequest.setFlag(flag);
userVote = flag;
spiceManager.execute(AptoideUtils.RepoUtils.buildFlagAppRequest(storeName, flag, md5sum), new RequestListener<GenericResponseV2>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
dialogFragment.dismiss();
}
@Override
public void onRequestSuccess(GenericResponseV2 genericResponseV2) {
if (genericResponseV2.getStatus().toUpperCase().equals("OK")) {
BusProvider.getInstance().post(new OttoEvents.AppViewRefresh());
Toast.makeText(getActivity(), R.string.flag_added, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), R.string.error_occured, Toast.LENGTH_SHORT).show();
}
spiceManager.removeDataFromCache(GetApp.class, md5sum);
try {
dialogFragment.dismiss();
} catch (Exception e) {
Logger.e(TAG, e.getMessage());
}
}
});
}
@Override
public void voteComment(int commentId, AddApkCommentVoteRequest.CommentVote vote) {
RequestListener<GenericResponseV2> commentRequestListener = new AlmostGenericResponseV2RequestListener() {
@Override
public void CaseOK() {
Toast.makeText(getActivity(), getString(R.string.vote_submitted), Toast.LENGTH_LONG).show();
}
};
AptoideUtils.VoteUtils.voteComment(
spiceManager,
commentId,
storeName,
SecurePreferences.getInstance().getString("token", "empty"),
commentRequestListener,
vote);
}
private void showRootDialog() {
if (!PreferenceManager.getDefaultSharedPreferences(getActivity()).contains("allowRoot") && !Aptoide.IS_SYSTEM) {
final Handler handler = new Handler(Looper.getMainLooper());
new Thread(new Runnable() {
@Override
public void run() {
if (AptoideUtils.AppUtils.isRooted()) {
handler.post(new Runnable() {
@Override
public void run() {
// in a try because we might be already out of this Activity
try {
AptoideDialog.allowRootDialog().show(getChildFragmentManager(), "allowRoot");
} catch (Exception e) {
Logger.printException(e);
}
}
});
}
}
}).start();
}
}
private void showDialogIfComingFromBrowser() {
if (getActivity().getIntent().getBooleanExtra(Constants.FROM_MY_APP_KEY, false) && !isPaidApp()) {
final InstallListener installListener = new InstallListener(iconUrl, appName, versionName, packageName, md5sum, isPaidApp());
DialogFragment dialog = AptoideDialog.myAppInstall(appName, installListener, onDismissListener);
AptoideDialog.showDialogAllowingStateLoss(dialog, getChildFragmentManager(),"myApp");
}
}
private void requestComments(boolean useCache) {
long cacheExpiryDuration = (useCache || !forceReload) ? DurationInMillis.ONE_HOUR * 6 : DurationInMillis.ALWAYS_EXPIRED;
// call list apkcomments, which need: storeName, packageName, versionName
// http://webservices.aptoide.com/webservices/2/listApkComments/apps/com.android.vending/5.12.9/json
AllCommentsRequest request = new AllCommentsRequest();
request.storeName = storeName;
request.versionName = versionName;
request.packageName = packageName;
request.filters = Aptoide.filters;
request.limit = MAX_COMMENTS_REQUEST;
request.lang = AptoideUtils.StringUtils.getMyCountryCode(getActivity());
spiceManager.execute(request, "comments" + appName + appId + storeName + versionName + packageName, cacheExpiryDuration, requestCommentListener);
}
private void continueLoading() {
final Intent intent = getActivity().getIntent();
if (intent.getBooleanExtra(Constants.FROM_RELATED_KEY, false)) {
appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
appName = intent.getStringExtra(Constants.APPNAME_KEY);
iconUrl = intent.getStringExtra(Constants.ICON_KEY);
downloads = intent.getLongExtra(Constants.DOWNLOADS_KEY, 0);
rating = intent.getFloatExtra(Constants.RATING_KEY, 0.0f);
graphic = intent.getStringExtra(Constants.GRAPHIC_KEY);
fileSize = intent.getLongExtra(Constants.FILESIZE_KEY, 0);
storeId = intent.getLongExtra(Constants.STOREID_KEY, 0);
storeName = intent.getStringExtra(Constants.STORENAME_KEY);
packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
versionName = intent.getStringExtra(Constants.VERSIONNAME_KEY);
executeSpiceRequestWithAppId(appId, storeName, packageName);
} else if (intent.getBooleanExtra(Constants.FROM_SPONSORED_KEY, false)) {
fromSponsored = true;
appId = intent.getLongExtra(Constants.APP_ID_KEY, -1);
adId = intent.getLongExtra(Constants.AD_ID_KEY, -1);
packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
storeName = intent.getStringExtra(Constants.STORENAME_KEY);
appName = intent.getStringExtra(Constants.APPNAME_KEY);
String location = intent.getStringExtra(Constants.LOCATION_KEY);
String keyword = intent.getStringExtra(Constants.KEYWORD_KEY);
String cpc = intent.getStringExtra(Constants.CPC_KEY);
String cpi = intent.getStringExtra(Constants.CPI_KEY);
cpd = intent.getStringExtra(Constants.CPD_KEY);
String whereFrom = intent.getStringExtra(Constants.WHERE_FROM_KEY);
download_from = intent.getStringExtra(Constants.DOWNLOAD_FROM_KEY);
executeSpiceRequestWithAppId(appId, storeName, packageName);
AptoideUtils.AdNetworks.knock(cpc);
if (intent.hasExtra("partnerExtra")) {
final String clickUrl = intent.getBundleExtra("partnerExtra").getString("partnerClickUrl");
ReferrerUtils.extractReferrer(packageName, appId, adId, -1, clickUrl, spiceManager, null, ReferrerUtils.RETRIES);
}
} else if (intent.getBooleanExtra(Constants.ROLLBACK_FROM_KEY, false)) {
md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
executeSpiceRequestWithMd5(md5sum, storeName);
} else if (intent.getBooleanExtra(Constants.FROM_TIMELINE_KEY, false)) { // From Timeline
appName = intent.getStringExtra(Constants.APPNAME_KEY);
storeName = intent.getStringExtra(Constants.STORENAME_KEY);
md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
executeSpiceRequestWithMd5(md5sum, storeName);
} else if (intent.getBooleanExtra(Constants.FROM_COMMENT_KEY, false)) {
appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
appName = intent.getStringExtra(Constants.APPNAME_KEY);
executeSpiceRequestWithAppId(appId, storeName, null);
} else if (intent.getBooleanExtra("fromApkInstaller", false)) {
autoDownload = true;
appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
appName = intent.getStringExtra(Constants.APPNAME_KEY);
storeName = intent.getStringExtra(Constants.STORENAME_KEY);
packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
executeSpiceRequestWithAppId(appId, storeName, packageName);
} else if (intent.getBooleanExtra(Constants.GET_BACKUP_APPS_KEY, false)) {
packageName = Defaults.BACKUP_APPS_PACKAGE;
appName = Defaults.BACKUP_APPS_NAME;
executeSpiceRequestWithPackageName(packageName, appName);
} else if (intent.getBooleanExtra(Constants.FROM_MY_APP_KEY, false)) { // from browser
appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
executeSpiceRequestWithAppId(appId, storeName, packageName);
} else if (intent.getBooleanExtra(Constants.SEARCH_FROM_KEY, false)) { // from search inside app
appName = intent.getStringExtra(Constants.APPNAME_KEY);
md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
storeName = intent.getStringExtra(Constants.STORENAME_KEY);
executeSpiceRequestWithMd5(md5sum, storeName);
} else if (intent.getBooleanExtra(Constants.UPDATE_FROM_KEY, false)) {
iconUrl = intent.getStringExtra(Constants.ICON_KEY);
appName = intent.getStringExtra(Constants.APPNAME_KEY);
versionName = intent.getStringExtra(Constants.VERSIONNAME_KEY);
packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
storeName = intent.getStringExtra(Constants.STORENAME_KEY);
executeSpiceRequestWithMd5(md5sum, storeName);
} else if (intent.getBooleanExtra(Constants.MARKET_INTENT, false)) {
packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
executeSpiceRequestWithPackageName(packageName, null);
}
mCollapsingToolbarLayout.setTitle(appName);
}
private void executeSpiceRequestWithAppId(long appId, @Nullable String storeName, String packageName) {
long cacheExpiryDuration = forceReload ? DurationInMillis.ALWAYS_EXPIRED : DurationInMillis.ONE_HOUR;
spiceManager.execute(
AptoideUtils.RepoUtils.buildGetAppRequestFromAppId(appId, storeName, packageName),
appId + bucketSize,
cacheExpiryDuration,
listener);
}
private void executeSpiceRequestWithMd5(String md5, String storeName) {
long cacheExpiryDuration = forceReload ? DurationInMillis.ALWAYS_EXPIRED : DurationInMillis.ONE_HOUR;
spiceManager.execute(
AptoideUtils.RepoUtils.buildGetAppRequestFromMd5(md5, storeName),
md5 + bucketSize,
cacheExpiryDuration,
listener);
}
private void executeSpiceRequestWithPackageName(String packageName, String appName) {
long cacheExpiryDuration = forceReload ? DurationInMillis.ALWAYS_EXPIRED : DurationInMillis.ONE_HOUR;
spiceManager.execute(
AptoideUtils.RepoUtils.buildGetAppRequestFromPackageName(packageName),
packageName + appName + bucketSize,
cacheExpiryDuration,
listener);
}
private void executeSpiceRequestWithAppRate(long appId, float rating) {
mRatingBar.setIsIndicator(true);
spiceManager.execute(AptoideUtils.RepoUtils.buildRateRequest(appId, rating), new RequestListener<RateApp>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
Toast.makeText(getActivity(), getString(R.string.error_occured), Toast.LENGTH_SHORT).show();
mRatingBar.setIsIndicator(false);
}
@Override
public void onRequestSuccess(RateApp rateApp) {
mRatingBar.setIsIndicator(false);
Toast.makeText(getActivity(), getString(R.string.appview_rate_Success), Toast.LENGTH_SHORT).show();
}
});
}
class RatingBarClickListener implements RatingBar.OnRatingBarChangeListener {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
if (!fromUser) {
return;
}
final Activity activity = getActivity();
if (AptoideUtils.AccountUtils.isLoggedIn(activity)) {
executeSpiceRequestWithAppRate(appId, rating);
} else {
Intent intent = new Intent(activity, MyAccountActivity.class);
activity.startActivity(intent);
}
}
}
public class DowngradeListener implements View.OnClickListener {
private String icon;
private String name;
private String versionName;
private String downgradeVersion;
private String package_name;
public DowngradeListener(String icon, String name, String versionName, String downgradeVersion, String package_name) {
this.icon = icon;
this.name = name;
this.versionName = versionName;
this.downgradeVersion = downgradeVersion;
this.package_name = package_name;
}
@Override
public void onClick(View v) {
reloadButtons = true;
Fragment downgrade = new UninstallRetainFragment();
Bundle args = new Bundle();
args.putString("name", name);
args.putString("package", package_name);
args.putString("version", versionName);
args.putString("downgradeVersion", downgradeVersion);
args.putString("icon", icon);
downgrade.setArguments(args);
getFragmentManager().beginTransaction().add(downgrade, "downgrade").commit();
}
}
public class InstallListener implements View.OnClickListener, DialogInterface.OnClickListener {
protected String icon;
protected String name;
protected String versionName;
protected String package_name;
protected String md5;
private long downloadId;
private boolean paid;
public InstallListener(String icon, String name, String versionName, String packageName, String md5, boolean paid) {
this.icon = icon;
this.name = name;
this.versionName = versionName;
this.package_name = packageName;
this.md5 = md5;
this.paid = paid;
this.downloadId = md5.hashCode();
}
protected Download makeDownLoad() {
Download download = new Download();
showRootDialog();
download.setId(this.downloadId);
download.setName(this.name);
download.setVersion(this.versionName);
download.setIcon(this.icon);
download.setPackageName(this.package_name);
download.setMd5(this.md5);
download.setPaid(this.paid);
if (!isUpdate) download.setCpiUrl(getActivity().getIntent().getStringExtra("cpi"));
return download;
}
@Override
public void onClick(View v) {
reloadButtons = true;
if (appSuggested != null && appSuggested.getInfo().getCpc_url() != null) {
AptoideUtils.AdNetworks.knock(appSuggested.getInfo().getCpd_url());
}
if (cpd != null) {
AptoideUtils.AdNetworks.knock(cpd);
}
download();
Analytics.ClickedOnInstallButton.clicked(package_name, developer);
}
@Override
public void onClick(DialogInterface dialog, int which) {
// shouldnt check if which is positive?
download();
}
}
}
}